inblog logo
|
jay0628
    Flutter

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

    김주희's avatar
    김주희
    Jun 11, 2025
    [Flutter] 35. 게시판 만들기 과제
    Contents
    서버프론트요구사항Riverpod으로 상태 관리게시글 목록게시글 상세보기게시글 쓰기게시글 삭제

    서버

    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

    RSS·Powered by Inblog