Flutter MVVM 패턴 - model

Angela Jeong·2024년 1월 11일

Flutter 아키텍처 

목록 보기
2/3

한 페이지에 코드를 짜다보면 정말 정신이 없다. 하지만 코드를 페이지별로 나누고, 기능별로 나누다보면 가독성도 높아지고 수정하고자하는 코드를 빨리 찾을 수 있어 편하다.

아키텍쳐 패턴 중 일반적으로 많이 쓰이는 MVVM 패턴을 적용해서 한 페이지로 빠르게 만든 내 코드를 차근 차근 분리해볼 것이다.

그 전에 model의 개념과 왜 써야하는지를 이해해보자!



model은 왜 써야 하지?

1) 위젯의 재사용과 가독성 향상을 위해 만든다

  • 코드를 짜다보면 특히 UI를 그릴 때 반복적으로 등장하고 다른 페이지에서도 계속 써야 하는 위젯이 생긴다.

  • 이럴 때 하나의 위젯으로 만들어 필요할 때마다 불러서 사용하면 굉장히 편할 것이다.

  • 이렇게 따로 클래스로 만들어 내면 이 클래스는 데이터를 담은 틀이 되기 때문에 모델이라고 부른다.

  • 아래 예시에서는 CardNews를 만들기 위해 반복적으로 등장하는 imgPath, title, subtitle을 한번에 불러다 쓰기 위해 CardContent 위젯을 따로 뻈다. 이때 CardContent이 바로 모델이 된다.

class CardNews extends StatelessWidget {
  const CardNews({
    Key? key,
  }) : super(key: key);

@override
  Widget build(BuildContext context) {
    final List<CardContent> cardContentList = [
      CardContent(
          imgPath: 'assets/images/04_01_cardnews.png',
          title: 'test',
          subtitle: 'test'),
      CardContent(
          imgPath: 'assets/images/04_02_cardnews.png',
          title: 'test',
          subtitle: 'test'),

class CardContent {
  final String imgPath;
  final String title;
  final String subtitle;

  CardContent(
      {required this.imgPath, required this.title, required this.subtitle});
}

2) 네트워크 통신 시 활용을 위한 model 생성

  • json 으로 네트워크 통신을 해서 데이터를 가져올 때 dart 내에서 사용할 데이터 틀 즉 모델에 맞추기 위해 클래스 안에 fromjson을 추가로 정의한다.

  • 이때 fromjson 메서드를 통해 모델 클래스 내 값들과 json 데이터 값들이 일치된다.

  • model을 UI에서 사용할 때는 가져온 데이터들을 순회하며 각 요소들을 모델 클래스의 객체로 변환시키는 작업이 추가로 필요하게 된다.

  • 아래 예시는 fromJson 메서드를 통해 일치시키는 작업을 하고, UI에 뿌려주기 전 모델 클래스의 객체로 변환시키는 작업을 했다.

class MovieInfo {
  int? userId;
  int? id;
  String? title;

  MovieInfo({this.userId, this.id, this.title});

  MovieInfo.fromJson(Map<String, dynamic> json) {
    userId = json['userId'];
    id = json['id'];
    title = json['title'];
  }
  
class MainScreen extends StatefulWidget {
  const MainScreen({super.key});

  @override
  State<MainScreen> createState() => _MainScreenState();
}

class _MainScreenState extends State<MainScreen> {
  final List<MovieInfo> movieInfoList = [];


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

  Future getData() async {
    final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/albums'));
    final jsonResult = jsonDecode(response.body);


    setState(() {
      jsonResult.forEach((e) {
        movieInfoList.add(MovieInfo.fromJson(e));
      });
    });

  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: const Text('영화정보 api 연습'),
        ),
        body: ListView(
          children: movieInfoList.map((e) => ListTile(
            title: Text(e.title ?? 'error'),
            subtitle: Text(e.id.toString()),
          ),
          ).toList(),
        )

0개의 댓글