BaseResponseDto를 통해 DTO 중복 코드 줄이기
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를 활용하고 있다.