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

chatRoomsAsync.when을 사용하여 실시간 채팅방 목록을 불러오려 했으나, 컴파일 에러가 발생했다
에러 메시지: The named parameter 'error' is required, but there's no corresponding argument.
Riverpod의 AsyncValue는 비동기 데이터를 처리할 때 Data(데이터 로드 성공), Error(에러 발생), Loading(로딩 중)이라는 세 가지 상태를 반드시 모두 처리해주어야 했다. 스크린샷에서는 data 부분만 작성되어 있어 나머지 필수 상태가 누락된 것이 원인으로ㅓ 확인했다
error와 loading 콜백을 추가하여 모든 상태에 대응하도록 코드를 수정해서 해결 완료!
body: chatRoomsAsync.when(
data: (rooms) => _buildRoomList(rooms),
error: (err, stack) => Center(child: Text('에러 발생: $err')), // 에러 상태 추가
loading: () => Center(child: CircularProgressIndicator()), // 로딩 상태 추가
),
ListView 내에서 개별 아이템을 렌더링하기 위해 item(context, room)을 호출했으나 에러가 발생했다
에러 메시지: Too many positional arguments: 1 expected, but 2 found.
작성된 item 위젯(또는 함수)은 매개변수를 1개만 받도록 설계되어 있었으나, 실제 호출 시에는 context와 room 2개를 전달하고 있었던 걸로 확인되었다
item 함수의 정의 부분을 확인하여 매개변수를 (context, room) 두 개를 받도록 수정하거나, 호출부에서 불필요한 인자를 제거하여 일치시켰다ㅣ
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"라는 단어가 보이면 누락된 값이 없는지 모델 클래스부터 확인하는 습관을 갖게 되었다!