[트러블 슈팅 ①] — Firestore CRUD 구현 중 데이터 조회(docs) 자동완성 오류
[상황 인지]
Firestore에서 Todo 목록을 조회하는 getToDos() 작성 중
querySnapshot.docs 부분에서 자동완성이 인식되지 않고
타입 불일치 오류가 발생했다.
final querySnapshot = db.collection('Todos').get(); // ← await 누락 final todos = querySnapshot.docs.map(...); // docs 인식 안 됨
[고민]
- docs 속성이 인식되지 않는 이유는?
- Firestore 문서(QuerySnapshot)의 반환 타입 문제인가?
- 혹시 비동기 처리가 누락되어서 Future<QuerySnapshot>을 그대로 받고 있는 건 아닐까?
[적용]
- await 키워드 누락 확인 → Future<QuerySnapshot>을 QuerySnapshot으로 동기 변환.
- 아래처럼 수정함으로써 docs 접근 가능해짐:
final querySnapshot = await db.collection('Todos').get(); final todos = querySnapshot.docs.map((doc) => ToDoModel.fromJson(doc.data())).toList();
[결과]
- Firestore 데이터 정상 조회 성공
- CRUD (add(), get(), update(), delete()) 기능 전체 정상 작동
- 전체 데이터 흐름이 Repository–ViewModel–UI로 잘 연결됨
[배운 점]
- Firestore의 모든 CRUD 메서드는 Future를 반환하므로 await 필수
- 단순한 IDE 경고라도 비동기 구조를 이해해야 근본 해결 가능
- Repository–ViewModel–UI 계층 분리가 유지보수성 향상에 결정적
[트러블 슈팅 ②] — Freezed, Riverpod, Hook 적용 과정
[상황 인지]
Todo 앱 구조를 Freezed + Riverpod + Hook으로 리팩토링하면서
다음과 같은 복합 오류 발생:
- The named parameter 'id' is required, but there's no corresponding argument.
- Missing concrete implementations of getter ...
- Map<String, dynamic> ↔ Map<String, Object> 타입 불일치
- Hook 적용 중 (_) => 관련 문법 오류
[고민]
- Freezed 사용 시 getter 관련 에러의 원인은?
→ part 'file.freezed.dart'; 또는 build_runner 미실행,
혹은 잘못된 타입(Map<String, dynamic>)으로 선언된 필드 때문. - Hook 문법 오류((_) =>)는 불필요한 매개변수가 포함된 콜백이 원인.
- StatefulWidget → HookConsumerWidget 전환 과정에서
상태값 접근 방식(.value) 혼동으로 런타임 오류 발생.
[적용]
Freezed 모델 수정
- @freezed 어노테이션 및 part 파일 정확히 선언
- Map<String, Object?>로 타입 일원화
- flutter pub run build_runner build --delete-conflicting-outputs 재실행
ViewModel 수정
- 기존 수동 객체 수정 → copyWith 활용
- toggleFavorite, toggleDone 시 불변 객체 복제 방식으로 변경
Hook 적용
- StatefulWidget → HookConsumerWidget 구조로 리팩토링
- useState, useTextEditingController, useFocusNode 적용
- setState() 제거 및 .value 활용으로 상태 제어
- 잘못된 (_) => 콜백 제거, 블록 구조 {}로 수정
[결과]
- Freezed + Riverpod + Hook 구조 완전 안정화
- 비동기 ViewModel과 Repository 간 연결 완성
- dispose() 제거 → 리소스 자동 관리
- UI 상태 반응성이 개선되고, 유지보수가 용이해짐
[배운 점]
- Freezed는 불변성 + 코드 자동화를 동시에 제공
- Riverpod AsyncNotifier는 상태 관리의 핵심이 ‘state 재할당’임을 체득
- Hook으로 setState() 없는 반응형 UI 구현 가능
- 각 프레임워크의 문법적 규칙을 정확히 이해하면 연결 시 오류 최소화
오늘의 핵심 정리
주제핵심 키워드요약
| Firestore CRUD | .add(), .get(), .update(), .delete() | 모든 CRUD는 이 4개로 구성 |
| Repository 패턴 | Firestore 통신 분리 | ViewModel과 UI에서 데이터 접근 단순화 |
| AsyncNotifier | state 재할당 구조 | 로딩, 데이터, 에러 상태를 명확히 구분 |
| Freezed | 불변 객체 + copyWith | 유지보수성과 안정성 강화 |
| Hook | useState, useTextEditingController | setState() 제거, 간결한 상태 관리 |
한줄 소감
오늘은 Firestore의 CRUD 흐름과
Freezed–Riverpod–Hook 구조의 연결 방식을 완벽히 이해했다.
단순히 동작만이 아니라 비동기 처리, 불변 데이터, 상태 재할당의 원리를 명확히 체득한 하루였다.