Flutter

블로그 프로젝트 - 데이터 통신을 위한 Repository 만들기

whs5758 2025. 8. 22. 18:35

1. Repository란?

Repository는 데이터 통신을 담당하는 클래스입니다.

  • UI와 서버 통신 코드를 분리
  • 재사용 가능한 API 호출 메서드 제공
// Repository 사용 전 (UI에서 직접 통신)
Response response = await dio.post("/login", data: {...});

// Repository 사용 후 (깔끔한 분리)
Map<String, dynamic> result = await userRepository.login(username, password);
안드로이드 앱에서 HTTP 통신을 허용하려면 AndroidManifest.xml 파일에 android:usesCleartextTraffic="true" 설정을 추가해야 합니다. 또한, 인터넷 사용 권한(android.permission.INTERNET)을 추가해야 합니다. 
1. AndroidManifest.xml 파일 수정: 
코드

<application
    ...
    android:usesCleartextTraffic="true"
    ... >
    ...
</application>

 

UserRepository
import 'package:dio/dio.dart';
import 'package:flutter_blog/_core/utils/my_http.dart';
import 'package:logger/logger.dart';

class UserRepository {
  // 회원 가입 요청 - post 요청
  Future<Map<String, dynamic>> join(
      String username, String email, String password) async {
    // 1. 요청 데이터 구성 - map 구조로 설계
    final requestBody = {
      "username": username,
      "email": email,
      "password": password,
    };

    // 2. HTTP post 요청
    Response response = await dio.post("/join", data: requestBody);

    // 3. 응답 처리
    final responseBody = response.data; // body 데이터 모두
    Logger().d(responseBody); // 개발용 로깅 처리
    // 4. 리턴
    return requestBody;
  }

  // 로그인 요청
  Future<Map<String, dynamic>> login(String username, String password) async {
    final requestBody = {
      "username": username,
      "password": password,
    };

    Response response = await dio.post("/login", data: requestBody);

    Map<String, dynamic> responseBody = response.data;
    // 개발 로깅용
    Logger().d(responseBody);
    return responseBody;
  }

  // 자동 로그인 - 토큰 값이 유효하다면
  Future<Map<String, dynamic>> autoLogin(String accessToken) async {
    Response response = await dio.post(
      "/auto/login",
      options: Options(
        headers: {"Authorization": accessToken},
      ),
    );

    Map<String, dynamic> responseBody = response.data;
    Logger().e(responseBody);
    return responseBody;
  }
}

 

PostRepository
import 'package:dio/dio.dart';
import 'package:flutter_blog/_core/utils/my_http.dart';
import 'package:flutter_blog/data/models/post.dart';
import 'package:logger/logger.dart'; // main() 실행시 추가 <---

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;
  }
}