DTO, Mapper

허준호·2025년 6월 27일
0

dart 언어 공부

목록 보기
15/16
post-thumbnail

DTO(Data Transfer Object)

데이터 소스를 모델 클래스로 변환하는 과정에서 순수하게 클래스에 담기 위한 중간 전달 객체

DTO를 사용하는 이유

  • 서버에서 데이터를 받을 때 잘못된 형식의 데이터를 받더라도 유연하게 처리하기 위해 클라이언트에서 사용하는 방어 수단이다
  • json 키의 값의 타입이 한가지가 아니거나, 키가 없어 모델로 정의하기 어려운 경우에 사용하면 좋다

Model 클래스와 차이점

  • 모든 필드가 nullable이다
  • 타입 선언 시 가능한 상위 타입으로 지정한다
    • 정수, 실수인 경우 → num
    • 값이 String과 num 둘 다 해당하는 경우 → dynamic
  • 직렬화, 역직렬화를 제공한다

DTO를 적용한 후 Model 클래스

  • 모든 필드는 non-nullable 상수(final로 지정)
  • ==, hashCode, copyWith, toString 메서드만 정의

장점

  • 실제 데이터 형태를 몰라도 모델 클래스를 정의할 수 있다
  • 내 앱에서 필요한 형태로 모델을 만들 수 있다
  • Map -> Model Class 변환시 null 값 등의 예외를 사전에 걸러내기 용이하다

Mapper

순수한 데이터 소스 (DTO) 를 원하는 모델 클래스로 변환하려면

fromJson(), toJson() 처럼 변환 기능이 필요한데, 별도의 mapper 를 통해 변환해야 한다

흐름

  1. DataSource에서 http 통신을 통해 json 데이터를 가져온다
  2. 가져온 json을 DTO 객체로 반환한다
  3. Repository에서 DataSource로부터 받은 DTO를 mapper를 사용하여 Model 클래스로 변환시킨다
  4. 변환시킨 Model을 사용하여 비즈니스 로직을 구현한다

예시

extension TodoMapper on TodoDto {
	Todo toTodo() {
		return Todo(
			userId: userId?.toInt() ?? -1,
			id: id?.toInt() ?? -1,
			title: title ?? '',
			completed: completed ?? false
		);
	}
}

extension을 사용하는 이유

  • DTO 클래스는 단순 직렬화, 역직렬화 기능에만 집중시킨다(코드 실수 방지를 위해 자동 생성 사용)
  • mapper는 복잡한 로직이 포함될 수 있기 때문에 따로 분리하여 관리한다

freezed

모델 클래스 4종 메서드(==, hashCode, toString, copyWith)와 직렬화, 역직렬화를 자동 생성해주는 패키지이다

  • json_serializable을 내장하고 있어서 필요 시 fromJson, toJson을 추가하면 된다

예시

import 'package:freezed_annotation/freezed_annotation.dart';

part 'photo_dto.freezed.dart';
part 'photo_dto.g.dart';


abstract class PhotoDto with _$PhotoDto {
  const factory PhotoDto({
    dynamic id,
    String? type,
    String? title,
    String? content,
    String? url,
    String? caption,
    (name: "created_at") String? createdAt,
  }) = _PhotoDto;

  factory PhotoDto.fromJson(Map<String, dynamic> json) =>
      _$PhotoDtoFromJson(json);
}
  • @JsonKey는 json key와 필드명을 다르게 하고 싶을 때 사용하면 된다
  • freezed.dart 파일은 4종 메서드, g.dart는 직렬화, 역직렬화 파일이다
profile
후추랑 소금 좋아하는 개발자

0개의 댓글