데이터의 '생김새'와 '가져오는 방법'을 정의한 부분입니다.
Post 클래스: "게시글은 id, 제목, 내용으로 구성된다"라는 데이터의 규격.
PostRepository 클래스: "파이어베이스에서 데이터를 가져오거나 지운다"라는 데이터의 출처.
파일: post.dart, post_repository.dart
화면과 데이터를 연결하는 '중간 관리자'입니다. Repository에서 데이터를 받아와 UI가 쓰기 좋게 '상태'로 들고 있는 부분입니다.
HomeViewModel 클래스: Notifier를 상속받아 state(List<Post>)를 관리하는 곳.
homeViewModelProvider: UI가 ViewModel에 접근할 수 있게 해주는 관리자.
파일: home_view_model.dart
사용자의 눈에 보이는 '화면' 그 자체입니다. 데이터를 직접 가져오지 않고, 오직 ViewModel의 상태만 지켜보다가 화면을 그립니다. (이 부분은 보통 ConsumerWidget으로 만듭니다.)
HomePage 위젯: ListView, Text, Image 등으로 구성된 실제 화면.
특징: ref.watch(homeViewModelProvider)를 사용하여 ViewModel의 데이터를 실시간으로 관찰함.
파일: home_page.dart
[ 사용자 ]
|
(1) 검색어 입력 ("플러터")
|
v
[ HomePage (UI) ] ---- (2) 검색해줘! ----> [ HomeViewModel (관리자) ]
|
(3) 데이터 좀 가져와!
|
v
[ BookRepository (공장) ]
|
<------- (5) "JSON 문자열" 응답 -------- (4) API 요청 (GET)
[ 네이버 서버 ] |
|
(6) 가공 단계 (중요!)
- jsonDecode (해체)
- Book.fromJson (조립)
|
<------- (7) List<Book> 반환 ------------------+
|
v
[ HomeViewModel ]
|
(8) state = HomeState(books) <--- "창고에 새 상품 채움!"
|
(9) 알림 (Riverpod) ----------------------> [ HomePage ]
|
(10) 화면 다시 그리기!
(Image.network 출력)
class PostRepository { // Future<List<Post>> getAll() async { // 1. 파이어스토어 인스턴스 가지고오기 final firestore = FirebaseFirestore.instance; // 2. 컬렉션 참조 만들기 final collectionRef = firestore.collection('posts'); // 3. 값 불러오기 final result = await collectionRef.get(); final docs = result.docs; return docs.map((doc) { final map = doc.data(); doc.id; final newMap = {'id': doc.id, ...map}; return Post.fromJson(newMap); }).toList(); } }
Future<List<Post>> getAll() async {
Future<List<Post>>: 이 함수는 당장 결과가 나오지 않고, 시간이 조금 걸린 뒤에(Future) Post 객체들이 담긴 리스트(List)를 돌려준다는 뜻입니다.
async: 비동기 처리를 하겠다는 선언입니다. (데이터를 가져올 동안 앱이 멈추지 않게 함)
final firestore = FirebaseFirestore.instance;
FirebaseFirestore.instance: 파이어베이스 데이터베이스에 접속하기 위한 통로를 여는 명령입니다. "자, 이제 파이어베이스랑 대화할 준비 됐어!"라고 말하는 것과 같습니다
final collectionRef = firestore.collection('posts');
collection('posts'): 파이어베이스 콘솔에 보면 'posts'라는 이름의 컬렉션(폴더와 비슷함)이 있습니다. 그 특정 폴더를 가리키는 주소록을 만드는 작업입니다.
final result = await collectionRef.get();
await ... get(): 실제로 서버에 "데이터 줘!"라고 요청하고 기다리는 과정입니다. 결과물result는 QuerySnapshot이라는 형태의 큰 뭉텅이로 넘어옵니다.
다음은 가져온 데이터 뭉텅이를 우리가 쓸 수 있는 Post 객체로 바꾸는 핵심 부분입니다.
final docs = result.docs; // 1. 문서(문서 꾸러미)들만 따로 뽑아냄 return docs.map((doc) { // 2. 문서 하나하나를 순회하며(반복문과 비슷) 작업함 final map = doc.data(); // 3. 문서 안의 실제 내용(제목, 내용 등)을 Map 형태로 가져옴 // 4. 중요! 파이어베이스는 '문서 ID'가 데이터 내용물(Map) 밖에 따로 있습니다. // 그래서 id와 나머지 내용(map)을 하나로 합쳐주는 과정이 필요합니다. final newMap = { 'id': doc.id, // 문서의 고유 ID (예: "ABC12345") ...map // 나머지 내용 (title: "안녕", content: "반가워" 등)을 펼쳐서 합침 }; // 5. 합쳐진 Map을 사용해서 Post 객체를 생성함 return Post.fromJson(newMap); }).toList(); // 6. 가공된 Post 객체들을 다시 리스트 형태로 묶어서 반환함
CRUD 에서 id
Ref: 실제 데이터가 아니라, 데이터를 찾을 수 있는 '주소값' 혹은 '통로'다"라는 것을 명시하기 위해사용