main.dart


import 'package:flutter/material.dart';
import 'package:webtoon_app/screens/home_screen.dart';
import 'package:webtoon_app/services/api_service.dart';

void main() {
  ApiService().getTodaysToons();
  runApp(const App());
}

class App extends StatelessWidget {
  const App({super.key}); // 이 위젯의 key를 stateless widget이라는 슈퍼클래스에 보낸다.
  // 위젯은 key라는 걸 가지고 있고 ID처럼 쓰인다.
  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: HomeScreen(),
    );
  }
}

services/api_service.dart


import 'dart:convert';

import 'package:http/http.dart' as http;
import 'package:webtoon_app/models/webtoon_model.dart';

class ApiService {
  static const String baseUrl =
      "<https://webtoon-crawler.nomadcoders.workers.dev>";
  static const String today = "today";
  // api요청을 하기 위해서 웹에서 fetch나 axios를 사용하는 것처럼 http 모듈을 사용해주자!

  Future<List<WebtoonModel>> getTodaysToons() async {
    List<WebtoonModel> webtoonInstances = [];
    final url = Uri.parse('$baseUrl/$today');
    final response = await http.get(url);
    // 데이터가 올 때까지 잠깐 멈춰야될 때가 있을 때 사용한다.
    // await으로 future가 완료될 때까지 기다린다.
    if (response.statusCode == 200) {
      final List<dynamic> webtoons = jsonDecode(response.body);
      // 텍스트로 응답된 body를 JSON으로 디코딩해준다.
      // dynamic으로 반환값이 나와서 type지정해주는게 좋음
      for (var webtoon in webtoons) {
        final toon = WebtoonModel.fromJson(webtoon);
        webtoonInstances.add(toon);
        print(webtoon);
      }
      return webtoonInstances;
    }
    throw Error();
  }
}

models/webtoon_model.dart


class WebtoonModel {
  final String title, thumb, id;

  WebtoonModel.fromJson(Map<String, dynamic> json)
      : title = json['title'],
        thumb = json['thumb'],
        id = json['id'];
  // Map<String, dynamic>은 TS로 따지면 key값이 String value값이 any이다.
  // named constructor라고 하고 이름이 있는 클래스 constructor
}

screens/home_screen.dart


import 'package:flutter/material.dart';
import 'package:webtoon_app/models/webtoon_model.dart';
import 'package:webtoon_app/services/api_service.dart';

class HomeScreen extends StatefulWidget {
  const HomeScreen({super.key});

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  List<WebtoonModel> webtoons = [];
  bool isLoading = true;

  void waitForWebtoons() async {
    webtoons = await ApiService().getTodaysToons();
    isLoading = false;
  }

  @override
  void initState() {
    super.initState();
    waitForWebtoons();
  }

  @override
  Widget build(BuildContext context) {
    print(webtoons);
    print(isLoading);
    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppBar(
        elevation: 2,
        title: const Text("오늘의 웹툰",
            style: TextStyle(fontSize: 24, fontWeight: FontWeight.w500)),
        backgroundColor: Colors.white,
        foregroundColor: Colors.green,
      ),
    );
  }
}