[Backend] DTO를 사용하는 이유
들어가며
Java 16부터 정식으로 도입된 Record
는 불변(Immutable) 객체를 간결하게 정의할 수 있도록 도와주는 특별한 클래스입니다. 특히 DTO나 VO와 같은 데이터 캡슐화 용도에 매우 적합하여 백엔드 개발에서 활용도가 높아지고 있습니다. 이번 글에서는 Record를 DTO로 사용하는 이유, VO와의 차이점, 그리고 Record의 한계에 대해 정리해보겠습니다.
목차
- Record란 무엇인가요?
- DTO로 사용하는 이유
- 모든 Record가 DTO인가요?
- Record vs VO
- Record의 한계
- 결론
1. Record란 무엇인가요?
Record는 Java 16에서 도입된 새로운 타입으로, 데이터를 캡슐화하면서도 불변성을 보장합니다. 모든 필드는 자동으로 private final
로 선언되며, 컴파일러가 생성자, getter
, equals()
, hashCode()
, toString()
메서드를 자동으로 만들어줍니다.
✅ 기존 클래스 기반 DTO
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class MemberDto {
private final String name;
private final String email;
private final int age;
public MemberDto(String name, String email, int age) {
this.name = name;
this.email = email;
this.age = age;
}
public String getName() {
return name;
}
public String getEmail() {
return email;
}
public int getAge() {
return age;
}
}
✅ Record를 사용한 DTO
1
public record MemberDto(String name, String email, int age) {}
불필요한 보일러플레이트 코드를 제거하고 짧고 깔끔하게 정의할 수 있습니다.
2. DTO로 사용하는 이유
Record는 다음과 같은 이유로 DTO로 사용하기에 적합합니다:
이유 | 설명 |
---|---|
✅ 불변성 | 모든 필드는 final, 객체 생성 후 값 변경 불가 |
✅ 자동 생성 메서드 | 생성자, getter, equals, hashCode, toString 자동 생성 |
✅ 간결한 문법 | DTO 정의 시 코드량 감소, 가독성 향상 |
✅ 스레드 안전성 | 불변 객체는 동시성 문제에서 상대적으로 안전함 |
즉, Record를 사용하면 데이터 전달 객체로써의 역할에 충실하면서도 구현이 훨씬 쉬워집니다.
3. 그럼 모든 Record는 DTO인가요?
아닙니다. Record는 단순히 데이터를 캡슐화하는 구조일 뿐, 용도에 따라 DTO, VO, Config 객체 등으로 다양하게 사용될 수 있습니다.
✅ 예: 값 객체(Value Object)로 사용
1
public record Coordinates(double x, double y) {}
위 객체는 좌표라는 개념 자체를 표현하는 VO(Value Object)에 가깝습니다.
- DTO: 계층 간 데이터 전송 목적
- VO: 도메인 내에서 의미 있는 값을 표현하는 객체
둘 다 Record로 구현 가능하지만 목적과 맥락에 따라 구분해야 합니다.
4. Record vs VO
항목 | Record | VO (Value Object) |
---|---|---|
공통점 | 불변 객체, 값 기반 동등성, 캡슐화 | |
사용 목적 | 데이터를 전달 (DTO 등) | 도메인 모델 내 의미 있는 값 표현 |
도메인 로직 포함 여부 | ❌ 보통 없음 | ✅ 포함될 수 있음 |
비즈니스 역할 | 없음 | 도메인 모델에 가까움 |
결론적으로, Record는 VO를 구현하는 데 적합하지만, VO의 복잡한 도메인 로직까지 표현하는 데에는 한계가 있습니다.
5. Record의 한계
Record는 편리하지만 다음과 같은 제한 사항이 있습니다:
클래스 상속 불가: 다른 클래스를 extends할 수 없습니다. 모든 Record는 java.lang.Record를 암묵적으로 상속합니다.
모든 필드는 final: 불변성으로 인해 값을 변경할 수 없습니다. 상황에 따라 유연한 구조가 필요한 경우 불리할 수 있습니다.
비즈니스 로직 부적합: Record는 데이터 표현에 초점을 맞춘 구조로, 복잡한 로직 처리에는 부적합합니다.
버전 호환성 문제: Java 16 이상에서만 정식 지원됩니다. Java 8이나 11을 사용하는 프로젝트에서는 사용할 수 없습니다.
6. 결론
Record는 불변 객체이면서, 데이터 전송 객체로서의 장점이 많아 DTO에 매우 적합합니다. 그러나 모든 Record가 DTO는 아니며, VO처럼 의미 있는 값 객체로도 활용될 수 있습니다. 복잡한 도메인 로직이나 상속이 필요한 경우에는 Record보다 일반 클래스를 사용하는 것이 적절할 수 있습니다.
참고 자료
- Java 공식 문서 - Records
- Baeldung - Java Record Guide
- DDD 패턴 - DTO와 VO 차이
Record는 Java의 생산성을 높이는 강력한 도구입니다. 하지만 “언제, 왜” 사용하는지가 더 중요합니다.