[Flutter] 35. 게시판 만들기 과제

김주희's avatar
Jun 11, 2025
[Flutter] 35. 게시판 만들기 과제

서버

record 문법

notion image
 
커스텀 생성자 DTO(Post post)를 통해 Post 객체로부터 DTO
public record DTO(Integer id, String title) { public DTO(Post post) { this(post.getId(), post.getTitle()); } }
 
내부적으로 자동 생성되는 코드 예상
public final class DTO { private final Integer id; private final String title; public DTO(Integer id, String title) { ... } public Integer id() { return id; } public String title() { return title; } public boolean equals(Object o) { ... } public int hashCode() { ... } public String toString() { ... } }
 

게시글 쓰기

notion image
 

게시글 목록

notion image
 

게시글 삭제

notion image
 

 

프론트

요구사항

# 플러터 CRUD (기초) ## 게시글 목록 - 화면에 id, title만 출력 - PostListVM 만들기 -> 컬렉션 관리 ## 게시글 쓰기 - TextEditingController를 사용 - PostListVM에서 글쓰기 하기 ## 게시글 상세보기 - PostList 화면에서 Post 객체 전달해서 출력하기 (뒤로가기 할 때 vm이 없으니까 autoDispose 필요X) - PostDetail 화면은 ViewModel이 없음 ## 게시글 삭제하기 - PostListVM에 삭제하기 요청 - PostList 화면의 상태 변경 (다시 통신X) ## 게시글 수정하기 - 없음
 

Riverpod으로 상태 관리

상태관리할 범위 정하고 시작해야한다!
notion image
 

게시글 목록

post_list_vm

notion image
notion image
 

PostRepository getList 테스트

C:\workspace\tools\flutter\bin\flutter.bat --no-color test --machine --start-paused test\data\post_repository_test.dart Testing started at 오전 10:18 ... ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── │ #0 PostRepository.getList (package:blog/data/post_repository.dart:9:14) │ #1 <asynchronous suspension> ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄ │ 🐛 { │ 🐛 "status": 200, │ 🐛 "msg": "성공", │ 🐛 "body": [ │ 🐛 { │ 🐛 "id": 23, │ 🐛 "title": "title 23", │ 🐛 "content": "content 23", │ 🐛 "createdAt": "2025-06-11" │ 🐛 }, │ 🐛 { │ 🐛 "id": 22, │ 🐛 "title": "title 22", │ 🐛 "content": "content 22", │ 🐛 "createdAt": "2025-06-11" │ 🐛 }, │ 🐛 { │ 🐛 "id": 21, │ 🐛 "title": "title 21", │ 🐛 "content": "content 21", │ 🐛 "createdAt": "2025-06-11" │ 🐛 }, │ 🐛 { │ 🐛 "id": 20, │ 🐛 "title": "title 20", │ 🐛 "content": "content 20", │ 🐛 "createdAt": "2025-06-11" │ 🐛 }, │ 🐛 { │ 🐛 "id": 19, │ 🐛 "title": "title 19", │ 🐛 "content": "content 19", │ 🐛 "createdAt": "2025-06-11" │ 🐛 }, │ 🐛 { │ 🐛 "id": 18, │ 🐛 "title": "title 18", │ 🐛 "content": "content 18", │ 🐛 "createdAt": "2025-06-11" │ 🐛 }, │ 🐛 { │ 🐛 "id": 17, │ 🐛 "title": "title 17", │ 🐛 "content": "content 17", │ 🐛 "createdAt": "2025-06-11" │ 🐛 }, │ 🐛 { │ 🐛 "id": 16, │ 🐛 "title": "title 16", │ 🐛 "content": "content 16", │ 🐛 "createdAt": "2025-06-11" │ 🐛 }, │ 🐛 { │ 🐛 "id": 15, │ 🐛 "title": "title 15", │ 🐛 "content": "content 15", │ 🐛 "createdAt": "2025-06-11" │ 🐛 }, │ 🐛 { │ 🐛 "id": 14, │ 🐛 "title": "title 14", │ 🐛 "content": "content 14", │ 🐛 "createdAt": "2025-06-11" │ 🐛 }, │ 🐛 { │ 🐛 "id": 13, │ 🐛 "title": "title 13", │ 🐛 "content": "content 13", │ 🐛 "createdAt": "2025-06-11" │ 🐛 }, │ 🐛 { │ 🐛 "id": 12, │ 🐛 "title": "title 12", │ 🐛 "content": "content 12", │ 🐛 "createdAt": "2025-06-11" │ 🐛 }, │ 🐛 { │ 🐛 "id": 11, │ 🐛 "title": "title 11", │ 🐛 "content": "content 11", │ 🐛 "createdAt": "2025-06-11" │ 🐛 }, │ 🐛 { │ 🐛 "id": 10, │ 🐛 "title": "title 10", │ 🐛 "content": "content 10", │ 🐛 "createdAt": "2025-06-11" │ 🐛 }, │ 🐛 { │ 🐛 "id": 9, │ 🐛 "title": "title 9", │ 🐛 "content": "content 9", │ 🐛 "createdAt": "2025-06-11" │ 🐛 }, │ 🐛 { │ 🐛 "id": 8, │ 🐛 "title": "title 8", │ 🐛 "content": "content 8", │ 🐛 "createdAt": "2025-06-11" │ 🐛 }, │ 🐛 { │ 🐛 "id": 7, │ 🐛 "title": "title 7", │ 🐛 "content": "content 7", │ 🐛 "createdAt": "2025-06-11" │ 🐛 }, │ 🐛 { │ 🐛 "id": 6, │ 🐛 "title": "title 6", │ 🐛 "content": "content 6", │ 🐛 "createdAt": "2025-06-11" │ 🐛 }, │ 🐛 { │ 🐛 "id": 5, │ 🐛 "title": "title 5", │ 🐛 "content": "content 5", │ 🐛 "createdAt": "2025-06-11" │ 🐛 }, │ 🐛 { │ 🐛 "id": 4, │ 🐛 "title": "title 4", │ 🐛 "content": "content 4", │ 🐛 "createdAt": "2025-06-11" │ 🐛 }, │ 🐛 { │ 🐛 "id": 3, │ 🐛 "title": "title 3", │ 🐛 "content": "content 3", │ 🐛 "createdAt": "2025-06-11" │ 🐛 }, │ 🐛 { │ 🐛 "id": 2, │ 🐛 "title": "title 2", │ 🐛 "content": "content 2", │ 🐛 "createdAt": "2025-06-11" │ 🐛 }, │ 🐛 { │ 🐛 "id": 1, │ 🐛 "title": "title 1", │ 🐛 "content": "content 1", │ 🐛 "createdAt": "2025-06-11" │ 🐛 } │ 🐛 ] │ 🐛 } └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── No tests were found.
 

post_list_body

notion image
 

실행 결과

notion image
 

게시글 상세보기

post 넘기기

notion image
 

post_detail_body

notion image
 

실행 결과

notion image
 

게시글 쓰기

통신

notion image
 

통신 테스트

notion image
 

post_write_form

TextEditingController를 사용할 것이므로 post_list_vm에 write 함수를 만들고 title과 content를 vm에게 write 함수를 통해 전달해야함.
notion image
 

post_list_vm의 write 함수

notion image
 

실행 결과

게시글 등록 후 목록으로 돌아간다.
notion image
 
상세보기 화면
notion image
 

게시글 삭제

통신

notion image
 

통신 테스트

notion image
 

post_detail_body

notion image
 

post_list_vm의 deleteOne 함수

notion image
 
 

실행 결과

삭제 후 목록으로 돌아갈 때 재통신 하지 않는 것이 요구사항이었다. id = 21 게시글을 삭제 후 삭제 통신에 대한 응답은 왔으나 목록에 대한 통신의 응답은 오지 않았기 때문에 재통신이 일어나지 않고 상태를 갱신한 것을 확인할 수 있다.
notion image
Share article

jay0628