MVVM_(DoranDoran App_TP)_Flutter 숙련주차 15일_

박진·2026년 1월 23일

2026.01.23 (금)
DoranDoran APP 팀프로젝트 완료 후 KTP 회고 및 트러블 슈팅


이번 주 학습 요약

이번 주는 MVVM 패턴 기반으로 Riverpod과 Firebase를 연동해서 실시간 채팅 기능까지 구현해봤다. 데이터 흐름을 이해하고 UI와 로직을 분리하는 과정에서 발생한 다양한 트러블슈팅을 통해 설계의 중요성을 배웠다

  • 프로젝트: 위치 기반 채팅 앱 '도란도란'
  • 내가 맡은 주요 기능: 실시간 채팅 시스템 구축
  • 사용 기술: Flutter, Dart, Riverpod(State Management), Firebase Firestore(NoSQL)
  • 핵심 키워드: MVVM 패턴, Stream, AsyncValue, 모델링(Data Modeling)

Trouble Shooting

AsyncValue.when 매개변수 누락 문제

[문제 상황]

chatRoomsAsync.when을 사용하여 실시간 채팅방 목록을 불러오려 했으나, 컴파일 에러가 발생했다

에러 메시지: The named parameter 'error' is required, but there's no corresponding argument.

[원인 분석]

RiverpodAsyncValue는 비동기 데이터를 처리할 때 Data(데이터 로드 성공), Error(에러 발생), Loading(로딩 중)이라는 세 가지 상태를 반드시 모두 처리해주어야 했다. 스크린샷에서는 data 부분만 작성되어 있어 나머지 필수 상태가 누락된 것이 원인으로ㅓ 확인했다

[해결 방법]

errorloading 콜백을 추가하여 모든 상태에 대응하도록 코드를 수정해서 해결 완료!

body: chatRoomsAsync.when(
  data: (rooms) => _buildRoomList(rooms),
  error: (err, stack) => Center(child: Text('에러 발생: $err')), // 에러 상태 추가
  loading: () => Center(child: CircularProgressIndicator()), // 로딩 상태 추가
),

Widget/Function 매개변수 개수 불일치

[문제 상황]

ListView 내에서 개별 아이템을 렌더링하기 위해 item(context, room)을 호출했으나 에러가 발생했다

에러 메시지: Too many positional arguments: 1 expected, but 2 found.

[원인 분석]

작성된 item 위젯(또는 함수)은 매개변수를 1개만 받도록 설계되어 있었으나, 실제 호출 시에는 context와 room 2개를 전달하고 있었던 걸로 확인되었다

[해결 방법]

item 함수의 정의 부분을 확인하여 매개변수를 (context, room) 두 개를 받도록 수정하거나, 호출부에서 불필요한 인자를 제거하여 일치시켰다ㅣ


Model과 Firestore 데이터 불일치 (Required Parameter)

[문제 상황]

Firestore에서 데이터를 가져와 ChatRoomModel 객체로 변환하는 fromMap 팩토리 생성자에서 에러가 발생했었다

에러 메시지: The named parameter 'des' is required, but there's no corresponding argument.

[원인 분석]

ChatRoomModel 정의부에서 des(설명) 필드를 required로 설정했지만, fromMap 함수 내에서 해당 값을 할당해주지 않았다. 데이터베이스(Entity) 구조와 앱 내부 모델(Model) 구조 사이의 차이를 간과한 결과였던 걸로 확인했다

[해결 방법]

fromMap 생성자에서 des 값을 맵 데이터로부터 할당하거나, 기본값을 제공하도록 수정해서 해결했다!

factory ChatRoomModel.fromMap(Map<String, dynamic> map, String id) {
  return ChatRoomModel(
    roomId: id,
    title: map['title'] ?? '',
    des: map['des'] ?? '설명 없음', // 누락된 필드 추가
    // ... 나머지 필드들
  );
}

새롭게 깨달은 점

  • Entity vs Model
    데이터베이스에 저장되는 형태(Entity)와 UI에서 사용되는 형태(Model)를 분리하여 관리하는 이유를 이해했다. 이는 데이터 구조가 변경되어도 UI 로직에 미치는 영향을 최소화할 수 있다.

  • 실시간 데이터 처리
    Stream과 snapshots()를 활용해 Firestore의 데이터 변화를 실시간으로 감지하고 UI를 자동 갱신하는 Riverpod의 강력함을 경험했다.

  • 꼼꼼한 에러 체크
    Dart 컴파일러의 에러 메시지는 매우 정확합니다. "Required"라는 단어가 보이면 누락된 값이 없는지 모델 클래스부터 확인하는 습관을 갖게 되었다!

0개의 댓글