📌개요
DTO는 계층 간 데이터 전송을 위한 객체로 Java 개발에서 빈번히 사용된다.
기존에는 Class로 DTO를 구현했지만 Java 14부터 등장한 Record를 활용해보면 불변성, 간결성, 명확성을 모두 확보할 수 있다.
주문 시스템을 예시로 Record를 활용해 DTO를 효과적으로 구현하는 방법을 알아보자.
- DTO: Data Transfer Object
- 불변성(Immutability): 생성 후 수정 불가
- 간결성(Simplicity): 반복 코드 자동 생성
- 명확성(Clarity): 순수 데이터 객체임을 명시
📌내용
DTO란?
Data Transfer Object는 다음과 같은 특징을 가진다.
- 데이터 전송 전용 객체
- 비즈니스 로직 없이 순수 데이터만 포함한다.
- 계층 간 데이터 변환
- 예: Controller <-> Service 계층 연결
- 선택적 데이터 노출
- 민감 정보 필터링 또는 필요한 데이터만 전송
DTO 사용 Flow
sequenceDiagram participant Client as 클라이언트 participant Controller as 컨트롤러 participant Service as 서비스 participant Repository as 리포지토리 Client->>Controller: Request DTO 전송 Controller->>Service: Record DTO 변환 전달 Service->>Repository: Entity 변환 저장 Repository->>Service: Entity 반환 Service->>Controller: Record DTO 변환 Controller->>Client: Response DTO 반환
Class DTO VS Record DTO
Class DTO (기존 방식)
|
|
Record DTO (Java 16+)
Record는 Constructor
, getter
, equals()
, hashCode()
, toString()
을 자동 생성한다.
그 외에도 추가적인 기능을 제공하지만 직접 구현해야 하는 부분도 있다.
|
|
Record로 DTO 구현하기
간단히 어떻게 동작하는지 알아본다.
테스트 프로젝트 구조
|
|
UserDTO.java
|
|
ProductDTO.java
|
|
UserService.java
|
|
Main.java
|
|
Record DTO의 적절한 사용처
✅ Record DTO를 사용하면 좋은 경우
Tip
성능 팁
Record는 일반 클래스보다 메모리 사용량이 20~30% 적고 생성 속도가 약 15% 빠른 것으로 측정된다고 한다. (JMH 벤치마크 기준)
- 간단한 데이터 전송 객체
- API 요청/응답 모델
- 계층 간 데이터 전달
- 데이터베이스 조회 결과 매핑
- 값 객체(Value Object)
- 좌표(Coordinate), 금액(Money) 등 도메인 원시값 래핑
- 임시 데이터 그룹핑
- 다중 반환값 처리
|
|
❌ RecordDTO가 부적합한 경우
- 가변 객체가 필요한 경우
- 상태 변경이 빈번한 도메인 모델
- 복잡한 비즈니스 로직 포함
- 유효성 검사 외 추가 로직이 필요한 경우
- 상속이 필요한 구조
주의사항
- 불변성 유지
- 값 변경이 필요하면 새 객체 생성
1 2 3 4 5
ProductResponse updated = new ProductResponse( original.id(), "새 이름", // 변경 original.price() );
- 값 변경이 필요하면 새 객체 생성
- Jackson 직렬화
- 기본 지원되지만 커스텀 설정 필요시
@JsonCreator
사용1 2 3 4
public record ProductRequest(String name, double price) { @JsonCreator public ProductRequest { /* ... */ } }
- 기본 지원되지만 커스텀 설정 필요시
- 상속 불가
final
클래스이므로 상속할 수 없음
⚙️EndNote
사전 지식
- Java 16+ (Record 정식 기능)
- DTO 패턴
- 불변 객체(Immutable Object)