Flutter

BaseResponseDto를 통해 DTO 중복 코드 줄이기

flutter developer 2025. 2. 24. 17:51

 

API 문서를 확인해보 응답코드와 데이터로 네스팅되어있는 구조로 되어었는 동일한 response dto 구조를 파악할 수 있었다. 따라서 매번 같은 구조를 반복해서 코드로 DTO를 선언하기보다 BaseResponse 모델을 만들어 선언해보기로 했다.

 

1. BaseResponseDto<T>

먼저 대부분의 API 응답은 아래와 같은 공통적인 구조를 가진 상황이다

{
  "code": 200,
  "data": {
    "id": 1,
    "phone": "1234567890",
    "email": "test@example.com",
    "name": "John Doe"
  }
}

이를 Flutter에서 BaseResponseDto<T> 형태로 관리하면 모든 API 응답을 재사용할 수 있다 .

 

위와같이 공통구조를 짜주어 dto모델을 선언할 수 있다. 하지만 위 상태에서 빌드러너를 돌리면 에러가 나는데 T가 제네릭 타입이기 때문에, Dart는 T를 어떤 객체로 변환해야 하는지 알 수 없기 때문이다. 따라서 아직 fromJson()과 toJson()을 자동 생성할 수 없는 상태이다.

 

2. 해결 방법: genericArgumentFactories: true 적용

이를 해결하기 위해 genericArgumentFactories: true를 추가하고, T의 변환 함수를 명시적으로 전달해야 한다.

수정된 BaseResponseDto<T>

문제를 해결하기 위해 BaseResponseDto<UserDto>를 변환할 때 UserDto.fromJson()을 지정해야 한다. genericArgumentFactories: true를 추가하면  제너릭이 어떤 타입으로 변환될지 넣을 수 있게 된다.

 

3. 사용 예제

JSON → DTO 변환 (fromJson)

final json = {
  "code": 200,
  "data": {
    "id": 1,
    "phone": "1234567890",
    "email": "test@example.com",
    "name": "John Doe"
  }
};

// ✅ UserDto를 변환하는 함수를 직접 전달해야 함
final response = BaseResponseDto<UserDto>.fromJson(json, UserDto.fromJson);

💡 제네릭(T)이 UserDto인 경우, UserDto.fromJson을 변환 함수로 전달해야 함.

 

DTO → JSON 변환 (toJson)

final userDto = UserDto(id: 1, phone: "1234567890", email: "test@example.com", name: "John Doe");

final response = BaseResponseDto<UserDto>(code: 200, data: userDto);

// ✅ UserDto의 `toJson()`을 변환 함수로 전달해야 함
final json = response.toJson((user) => user?.toJson());

💡 제네릭(T)이 UserDto인 경우, user.toJson()을 직접 호출해야 함.

 

4. 내가 활용하고 있는 BaseResponseDto<T> 방식

위에선 제너릭 타입을 명시하기위해 BaseResponseDto<UserDto> 위와 같이 제너릭 타입을 명시해주는 구조로 갔지만 나는 이것보다 좀더 간결하게 가고 싶어서 typedef를 활용하고 있다.