"[Flutter] 블로그 만들기 - 서버 통신의 모든 것 (Dio 활용)

2025. 2. 9. 10:29·Flutter/App
728x90

이번 글에서는 Flutter 블로그 프로젝트에서 Dio를 활용한 서버 통신 구현을 다룹니다.
서버와 데이터를 주고받기 위한 Dio 설정, UserRepository 설계, 테스트 코드 작성까지 모든 과정을 설명과 함께 정리합니다.


1. 사전 지식: JSON과 Flutter의 데이터 처리

서버와 통신할 때 주로 사용하는 데이터 형식인 JSON을 Flutter에서 처리하는 방법을 먼저 이해해 봅시다.

 

JSON 데이터의 두 가지 타입

 

JSON Object

{
  "status": "success",
  "users": [
    { "username": "ssar", "password": 1234 },
    { "username": "cos", "password": 5678 }
  ]
}
  • JSON Object는 Map 구조와 유사하며, Flutter에서 Map<String, dynamic> 타입으로 처리됩니다.

 

JSON Array

[
  {
    "username": "ssar",
    "password": 1234
  },
  {
    "username": "cos",
    "password": 5678
  }
]
  • JSON Array는 리스트 구조와 유사하며, Flutter에서 List<Map<String, dynamic>> 타입으로 처리됩니다.

 

Flutter에서 JSON 데이터 처리 방법

  • JSON Object → Map<String, dynamic>로 변환하여 사용.
  • JSON Array → List<Map<String, dynamic>>로 변환하여 사용.
  • DTO(Data Transfer Object) 또는 모델 클래스를 활용하여 구조화된 데이터로 처리할 수 있습니다.

2. Dio 클래스 선언

Dio는 HTTP 요청/응답을 처리하기 위한 강력한 Flutter 패키지입니다.
전역적으로 사용할 Dio 객체를 선언하여 프로젝트 전반에서 쉽게 HTTP 요청을 보낼 수 있습니다.

📌 Dio 객체 설정

// API 서버의 기본 URL 설정
// 전역 변수 사용
import 'package:dio/dio.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';

final baseUrl = 'http://192.168.0.48:8080';

// 전역 변수 dio <--
final dio = Dio(
  BaseOptions(
    baseUrl: baseUrl,
    contentType: 'application/json;charset=utf-8',
    // 주의 ! 200 번 이외에는 모두 에러로 간주 하게 기본값 설정되어 있음
    // 다른 상태코드 다 허용
    validateStatus: (status) => true,
  ),
);

// 중요 데이터 보관소(금고 생성)
// 로컬에 민감한 데이터를 보관하는 안전한 금고 역할을 한다.
const secureStorage = FlutterSecureStorage();

📌 설명

  1. baseUrl: 서버의 기본 URL.
  2. contentType: 요청/응답을 JSON 형식으로 처리.
  3. validateStatus: 모든 상태 코드를 허용(기본값은 200만 허용).
  4. secureStorage: 민감한 데이터를 안전하게 저장할 수 있는 Flutter Secure Storage.

 

3. HTTP 요청 메시지 구조 이해

HTTP 요청 메시지는 다음과 같은 구조로 이루어져 있습니다.

  1. 시작 줄: 요청 메서드, URL, HTTP 버전을 포함.
    • 예: POST /login HTTP/1.1
  2. 헤더: 요청 메타데이터를 포함.
    • 예: Content-Type: application/json
  3. 바디: 요청 데이터를 포함.
    • 예: { "username": "user", "password": "1234" }

4. UserRepository 구현

UserRepository는 외부 API와 데이터를 주고받는 역할을 담당하는 클래스입니다.
Dio 객체를 활용해 사용자 등록, 로그인 요청 등을 처리합니다.


-  사용자 등록 메서드

서버에 새 사용자를 등록하는 메서드입니다.

📌 UserRepository 구현: save 메서드

import 'package:dio/dio.dart';

class UserRepository {
  const UserRepository();

  // 사용자 등록 요청
  Future<Map<String, dynamic>> save(Map<String, dynamic> reqData) async {
    // HTTP POST 요청을 /join 경로로 보냅니다.
    Response response = await dio.post('/join', data: reqData);

    // 응답 바디 추출
    Map<String, dynamic> responseBody =
        response.data; // header, body 중 body만 추출
    logger.i(responseBody); // 결과를 로깅
    return responseBody;
  }
}

-  로그인 요청 메서드

서버에 로그인 요청을 보내고 JWT 토큰과 사용자 정보를 반환합니다.

 

📌 UserRepository 구현: findByUsernameAndPassword 메서드

  // 로그인 요청 (레코드 문법)
  Future<(Map<String, dynamic>, String)> findByUsernameAndPassword(
      Map<String, dynamic> reqData) async {
    // HTTP 응답 메시지 전송
    Response response = await dio.post('/login', data: reqData);

    // JWT 토큰 추출 (Authorization 헤더에서 가져옴)
    String accessToken = response.headers['Authorization']?[0] ?? '';
    logger.i(accessToken); // 토큰 로깅

    // 응답 바디 추출
    Map<String, dynamic> responseBody = response.data; // 응답 메시지 바디
    return (responseBody, accessToken); // 레코드 문법을 활용해 반환
  }

5. 테스트 코드 작성

UserRepository의 메서드가 올바르게 동작하는지 확인하기 위한 테스트 코드를 작성합니다.

 

📌 테스트 코드

import 'package:flutter/material.dart';
import 'package:class_f_story/data/repository/user_repository.dart';
import '../utils/logger.dart';

void main() async {
  UserRepository userRepository = UserRepository();

  // 회원 등록 테스트

  Map<String, dynamic> resBody = await userRepository.save({
    "username": "hello",
    "password": "1234",
    "email": "hello@nate.com",
    "imgBase64":
        "data:image/jpg;base64,yrxsJ0Eg29JPHQXDFSZhEhYuhofZaFOzLh8wTob3JVMuFC4kX5CqWYBDubwLt23VjmQ4ZLXMMcKNly2Db2w2EHwDgeR844F1b91tUBeuALOzb2yxz0MSBMOlEhBtLGzVW0UbIicvHgOrTFGupuXW8OOQI2rzyIFQ2IwnBcXWQo72d7k9Ai88QZa6qYsd23YAn0KyvoTOKOXN6EWY1ZIVh73TbkQV4sx64WEFCLHkKqKWm16JhEhUJNzwaQQWiXFBl2JAyZ5CpBanN2UxRZcPntH2Nk9lcllPkwltiNcNwxJqcBplUMhTOS4hdfYpkJxL1it1CpsCBlFYdeMFHJn3XI8qQDgccUB0gar5F9pyyTaAE9J9ka4PRTBv5xgiPRB2Tpse69fzqNFpLJWuuy0HhKrLZ7vJCsy8Ykf226BiiA42v0WLvWtPchfLJJnuA2Y8XBICyiHFO8cBULOIqD0H0f4xn92k8bjdtJ1gw0nRiy3HevT632cGBOtvXMY4KJ9S9LFBsUkGeYjdHcTvVR4ZSvto6elYwMFHiPlcUGrI6g5y1AAYNbf2PHSXkJ0KGsqeOaVbYGP7WViL7au9GOHT9lptz49u1td7RRjqU5MKDIYoYDCpuxWoSJEHNVegho8nrmRtzLMBgm9RonQNa4rzDtdVdppE20KOIm8Hrfr7H5JPHwVjSzZsabktSbLWnVEaoALQkbgWhg2FcbLCmhg7lYDOAzYWd3rUIFNRjA4m1BQ6zVGozEIXL1FgptL5u0TRmA1ISAHUBtU2FpmQ6Vc0UQRfutLM6qNLJlKSHCQ7QPJSoAAibFLKKv2JxyKWjpVfRKKcBRS5jVzAby1y1hr3XmU22zPCPvyDT7ZqJMxHfZovUawHYQ96I3wQGO9vFXAvreDn62kOFp5A8CXHUaMBoPzugoXl8ywejlzEyz2TIR1ObRjZsHoeeDbOcMJO3SNVFs059G4ed2rdvX3ptYR00fsgZlDtwfVxVH4paCbH"
  });
  logger.e(resBody);

  // (Map<String, dynamic>, String) userInfoTest = await userRepository
  //     .findByUsernameAndPassword({"username": "ssar", "password": "1234"});
  // logger.e(userInfoTest);
  // // 레코드 문법 사용해보기
  // logger.d(userInfoTest.$1);
  // logger.d(userInfoTest.$1['response']['username']);
  // logger.d(userInfoTest.$1['response']['id']);
  // logger.d(userInfoTest.$1['response']['password']);
  // logger.d(userInfoTest.$2);
}

6. 마무리 및 정리

이번 글에서는 Dio와 UserRepository 구현을 통해 서버 통신을 처리하는 방법을 다뤘습니다.

✅ 정리

  1. Dio 클래스 선언:
    • 기본 URL, Content-Type, validateStatus 설정.
  2. UserRepository 구현:
    • 사용자 등록 요청(save), 로그인 요청(findByUsernameAndPassword) 메서드 구현.
  3. HTTP 메시지 구조 이해:
    • 요청의 시작 줄, 헤더, 바디의 역할과 구성.

다음 글에서는 로그인 기능 구현의 상세 내용을 다룹니다.
특히, **상태 관리(Riverpod)**와 예외 처리를 활용해 실질적인 로그인 기능을 구현할 예정입니다.  🚀


로그인 UI 구성하는 방법이 궁금하다면??

 

[Flutter] 블로그 만들기 (로그인 UI 구성 하기)

이번 글에서는 로그인 UI를 구성하고, 이를 위한 위젯들을 정리해보겠습니다.디자인 시안을 확인한 후, 필요한 위젯을 만들고 LoginPage와 LoginBody를 구성하겠습니다.UI에 사용될 파일  디자인 시

seohong.tistory.com

 

'Flutter > App' 카테고리의 다른 글

[Flutter] 블로그 만들기 - 회원가입 기능 구현 및 UI  (1) 2025.02.09
[Flutter] 블로그 만들기 - 로그인 기능 구현 (상태관리 및 예외처리)  (0) 2025.02.09
[Flutter] 블로그 만들기 - 로그인 UI 구성  (0) 2025.02.08
[Flutter] 블로그 만들기 - 기본 프로젝트 설정  (1) 2025.02.08
[Flutter] 상태 관리 앱 만들기 (라이브러리 사용)  (0) 2025.02.05
'Flutter/App' 카테고리의 다른 글
  • [Flutter] 블로그 만들기 - 회원가입 기능 구현 및 UI
  • [Flutter] 블로그 만들기 - 로그인 기능 구현 (상태관리 및 예외처리)
  • [Flutter] 블로그 만들기 - 로그인 UI 구성
  • [Flutter] 블로그 만들기 - 기본 프로젝트 설정
공돌이 출신 개발자
공돌이 출신 개발자
공돌이 출신 개발자입니다
  • 공돌이 출신 개발자
    공돌이 출신 개발자
    공돌이 출신 개발자
  • 전체
    오늘
    어제
    • 분류 전체보기 (124)
      • Database (0)
        • SQL (0)
        • 1일 1쿼리 (9)
      • Flutter (40)
        • Dart 언어 (18)
        • App (22)
      • Git (0)
      • Http 기초 지식 (14)
      • HTML5 & CSS3 (0)
      • Java (33)
      • JSP (0)
      • JavaScript (0)
      • Linux (0)
      • MSA (0)
      • Project (0)
      • React (0)
      • Spring (19)
      • 설치 메뉴얼 (1)
      • [Flutter] 프로젝트 (눈길) (8)
        • 작업일지 (8)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • GitHub
  • 공지사항

  • 인기 글

  • 태그

    안드로이드 앱 개발
    안드로이드
    Android
    앱 개발
    데이터
    Java
    객체
    플러터
    객체지향
    앱개발
    클래스
    jsp
    HTTP
    메서드
    회원가입
    1일1쿼리
    spring boot
    공부
    블로그 만들기
    코딩
    JAVA 기초
    SQLD
    프로젝트
    개발
    로그인
    android studio
    SQL
    프로그래밍
    dart
    flutter
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.2
공돌이 출신 개발자
"[Flutter] 블로그 만들기 - 서버 통신의 모든 것 (Dio 활용)
상단으로

티스토리툴바