본문 바로가기
Flutter

[flutter] 블로그 만들기 03

by JINJINC 2025. 2. 3.
728x90
반응형

Json 타입

보통 서버에서 문자열 형식 JSON 던져 줄 때 , 크게 사용하는 두가지 타입이 있다.

Json Object 타입

{ "status": "success", "users": \[ { "username": "ssar", "password": 1234 }, { "username": "cos", "password": 5678 } \] }

Json Array 타입

\[ { "username": "ssar", "password": 1234 }, { "username": "cos", "password": 5678 } \]

플러터에서 파싱하는 형태

JSON Object → Map<String, dynamic> 형태로 받아 바로 사용.
JSON Array → List<Map<String, dynamic>> 형태로 받아 바로 사용.

DTO를 만들어서 활용가능, 또는 바로 모델 클래스로 변환 사용해도 됨 
// 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();

sessionUser

class SessionUser {
  int? id;
  String? username;
  String? accessToken;
  bool? isLogin;

  SessionUser(
      {required this.id,
      required this.username,
      required this.accessToken,
      required this.isLogin});
}

userRepository

import 'package:dio/dio.dart';

import '../../_core/utils/logger.dart';
import '../../_core/utils/m_http.dart';
import '../model/user.dart';
import 'dart:convert';

class UserRepository {
  //회원가입 요청

  //json array 이거나, object이거나 둘중에 선택되어야함

  //responseDTO         requestDTO
  Future<Map<String, dynamic>> createUser(Map<String, dynamic> reqData) async {
    Response response = await dio.post('/join', data: reqData);

    //규칙1 repostiroy 영역에서는 응답 http 전체를 받아서
    //가능한 뷰모델에 http body영역만 던져준다.  => response.data부분만
    //response.header / response.data - body부분
    Map<String, dynamic> responseBody = response.data;
    logger.e(responseBody);
    return responseBody;
  }

  //로그인 요청
  //레코드 문법을 사용 => dto 설계 없이 바로 리턴() 괄호 시작
  //dart 3.0 이상부터 사용가능
  // 보통 통신하는 코드에서 기본적으로 예외처리는 무조건 해야함
  // 뷰 모델이 respository를 사용하는 구조
  Future<(Map<String,dynamic>,String?)> findByUsernameAndPassword(Map<String,dynamic> reqData) async{

    Response response = await dio.post('/login',data: reqData);
    //HTTP 응답 메세지(이미지화)
    Map<String, dynamic> responseBody = response.data;
    String? accessToken = response.headers.value('Authorization');
    return (responseBody,accessToken);

  }

  Future<(Map<String, dynamic>, String)> readUser(
      Map<String, dynamic> reqData) async {
    Response response = await dio.post('/login', data: reqData);
    Map<String, dynamic> responseBody = response.data;
    logger.d(responseBody);
    String? accessToken = response.headers['Authorization']?[0] ?? '';
    logger.i('response Header!! Token $accessToken}');
    List<String> access = accessToken.split(" ");
    logger.i('access Token만 : ${access[1].trim()}');

    //jwt 토큰 파싱
    try {
      logger.i('jwt 토큰 확인 : ${response.headers['Authorization']?[0]}');
      accessToken = response.headers['Authorization']![0];

      //레고드 문법
      // 위치기반 레코드 문법
      // 명명기반 레코드 문법
      return (responseBody, accessToken);
    } catch (e) {
      logger.e('jwt 파싱 오류');
    }

    return (responseBody, '');
  }

  //사용자 등록 요청
  Future<Map<String,dynamic>> saveUser(Map<String,dynamic> reqData) async{
    Response response = await dio.post('/join',data: reqData);
    Map<String,dynamic> responseBody = response.data;
    return responseBody;
  }

}

테스트

//userRepository에서 던지는 테스트 해보자

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

import '../utils/logger.dart';

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

  //테스트1 회원 등록 요청
  Map<String,dynamic> saveUser  = await userRepository.saveUser(
    {
      "username": "hello29",
      "password": "1234",
      "email": "hello29@nate.com",
      "imgBase64":
          "data:image/jpg;base64,yrxsJ0Eg29JPHQXDFSZhEhYuhofZaFOzLh8wTob3JVMuFC4kX5CqWYBDubwLt23VjmQ4ZLXMMcKNly2Db2w2EHwDgeR844F1b91tUBeuALOzb2yxz0MSBMOlEhBtLGzVW0UbIicvHgOrTFGupuXW8OOQI2rzyIFQ2IwnBcXWQo72d7k9Ai88QZa6qYsd23YAn0KyvoTOKOXN6EWY1ZIVh73TbkQV4sx64WEFCLHkKqKWm16JhEhUJNzwaQQWiXFBl2JAyZ5CpBanN2UxRZcPntH2Nk9lcllPkwltiNcNwxJqcBplUMhTOS4hdfYpkJxL1it1CpsCBlFYdeMFHJn3XI8qQDgccUB0gar5F9pyyTaAE9J9ka4PRTBv5xgiPRB2Tpse69fzqNFpLJWuuy0HhKrLZ7vJCsy8Ykf226BiiA42v0WLvWtPchfLJJnuA2Y8XBICyiHFO8cBULOIqD0H0f4xn92k8bjdtJ1gw0nRiy3HevT632cGBOtvXMY4KJ9S9LFBsUkGeYjdHcTvVR4ZSvto6elYwMFHiPlcUGrI6g5y1AAYNbf2PHSXkJ0KGsqeOaVbYGP7WViL7au9GOHT9lptz49u1td7RRjqU5MKDIYoYDCpuxWoSJEHNVegho8nrmRtzLMBgm9RonQNa4rzDtdVdppE20KOIm8Hrfr7H5JPHwVjSzZsabktSbLWnVEaoALQkbgWhg2FcbLCmhg7lYDOAzYWd3rUIFNRjA4m1BQ6zVGozEIXL1FgptL5u0TRmA1ISAHUBtU2FpmQ6Vc0UQRfutLM6qNLJlKSHCQ7QPJSoAAibFLKKv2JxyKWjpVfRKKcBRS5jVzAby1y1hr3XmU22zPCPvyDT7ZqJMxHfZovUawHYQ96I3wQGO9vFXAvreDn62kOFp5A8CXHUaMBoPzugoXl8ywejlzEyz2TIR1ObRjZsHoeeDbOcMJO3SNVFs059G4ed2rdvX3ptYR00fsgZlDtwfVxVH4paCbH"
    },
  );
  logger.i(saveUser);

  //로그인 요청
  (Map<String,dynamic>, String?) loginuser= await userRepository.findByUsernameAndPassword({"username": "ssar", "password": "1234"});
  logger.d(loginuser);

}

dart 3 버전 이후부터는 레코드 타입이 존재하므로, 따로 dto를 설계하지않고, tuple 형태로 받아서 사용할 수 있다. ( java의 tuple과 비슷)

728x90
반응형

댓글