Flutter

플러터) 게시물작성 코드 구조

조충희 2025. 8. 22. 18:40

1️⃣ post_write_form.dart
사용자 인터페이스(UI)를 구성하며 제목과 내용을 입력받는 폼을 제공

사용자의 입력 데이터를 받아 PostWriteFormNotifier로 전달하는 중간 연결자

class PostWriteForm extends ConsumerWidget {
  final _formKey = GlobalKey<FormState>();
  final _title = TextEditingController();
  final _content = TextEditingController();

  PostWriteForm({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return Form(
      key: _formKey,
      child: ListView(
        shrinkWrap: true,
        children: [
          CustomTextFormField(
            controller: _title,
            hint: "Title",
          ),
          const SizedBox(height: smallGap),
          CustomTextArea(
            controller: _content,
            hint: "Content",
          ),
          const SizedBox(height: largeGap),
          CustomElevatedButton(
            text: "글쓰기",
            click: () async {
              //
              await ref
                  .read(postWriteProvider.notifier)
                  .write(_title.text, _content.text);
              Navigator.pushNamed(context, "/post/list");
              await ref.read(postListProvider.notifier).fetchPosts();
            },
          ),
        ],
      ),
    );
  }
}

 

1) ref를 통해 쓰기 

await ref.read(postWriteProvider.notifier).write(_title.text, _content.text);

 

2)작성후 리스트 표출

Navigator.pushNamed(context, "/post/list");

 

3) 리스트 새로고침

await ref.read(postListProvider.notifier).fetchPosts();

 

2️⃣ post_write_notifier.dart
게시글 작성에 필요한 데이터 모델을 정의하고, 이를 관리하는 리버팟 노티파이어의 역할

게시글을 서버에 전송하는 비즈니스 로직을 담당

class PostWriteModel {
  String title;
  String content;

  PostWriteModel(
    this.title,
    this.content,
  );

  @override
  String toString() {
    return 'PostWriteModel{title: $title, content: $content}';
  }
} // end of class PostWriteModel

// 창고 메뉴얼 설계
class PostWriteFormNotifier extends Notifier<PostWriteModel?> {
  @override
  PostWriteModel? build() {
    return null;
  }

  // 게시글 작성 로직
  Future<bool> write(String title, String content) async {
    Future body = PostRepository().write(title, content);

    return true;
  }
}

// 실제 창고를 메모리에 올리자 - 전역 변수로 관리
final postWriteProvider =
    NotifierProvider<PostWriteFormNotifier, PostWriteModel?>(
        () => PostWriteFormNotifier());

 

리포지터리를 통해 게시글 작성 작업을 서버에 맡김

Future body = PostRepository().write(title, content);

 

3️⃣ post_repository
서버와의 네트워크 통신을 전담하는 클래스

게시글의 생성, 조회, 수정, 삭제(CRUD)와 관련된 모든 API 호출을 처리

이는 앱의 데이터 로직을 한 곳에 모아 관리하는 저장소

class PostRepository {
  // 글 작성 요청
  Future<Map<String, dynamic>> write(String title, String content) async {
    // 1. 데이터 준비 - 생략
    // 2. HTTP 요청
    Response response = await dio.post("/api/post", data: {
      "title": title,
      "content": content,
    });

    // 3. 응답 처리
    final responseBody = response.data;
    Logger().d(responseBody);
    return responseBody;
  }

  // 목록 조회 (페이지 네이션 처리)
  Future<Map<String, dynamic>> getList({int page = 0}) async {
    // 1. 데이터 준비 - 생략
    Response response =
        await dio.get("/api/post", queryParameters: {"page": page});
    final responseBody = response.data;
    Logger().d(responseBody);
    return responseBody;
  }

  // 조회 - 단일 조회
  Future<Map<String, dynamic>> getOne(int postId) async {
    Response response = await dio.get("/api/post/${postId}");
    final responseBody = response.data;
    Logger().d(responseBody);
    return responseBody;
  }

  // 삭제
  Future<Map<String, dynamic>> deleteOne(int postId) async {
    Response response = await dio.delete("/api/post/${postId}");
    final responseBody = response.data;
    Logger().d(responseBody);
    return responseBody;
  }

  // 수정
  Future<Map<String, dynamic>> updateOne(Post post) async {
    Response response = await dio.put("/api/post/${post.id}", data: {
      "title": post.title,
      "content": post.content,
    });

    final responseBody = response.data;
    Logger().d(responseBody);
    return responseBody;
  }
}