Java에서 DTO(Data Transfer Object) 클래스와 record는 데이터를 전달하는 역할을 하지만, 구조적 차이와 사용 목적에서 차이가 있다.
DTO는 일반적인 Java 클래스이며, 데이터 전달 및 변환을 위한 객체.
✔ 클래스 형태로 선언됨 (public class ...)
✔ 필드 + Getter/Setter + 생성자 포함
✔ 불변성을 직접 제어 가능 (final 사용 가능)
✔ 커스텀 로직 추가 가능 (예: 유효성 검사, 데이터 가공)
✔ 기본적으로 직렬화 가능 (implements Serializable)
public class UserDto {
private Long id;
private String name;
private int age;
public UserDto(Long id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public Long getId() { return id; }
public String getName() { return name; }
public int getAge() { return age; }
public void setId(Long id) { this.id = id; }
public void setName(String name) { this.name = name; }
public void setAge(int age) { this.age = age; }
@Override
public String toString() {
return "UserDto{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + '}';
}
}
record는 DTO와 비슷하지만, 더 간결한 문법으로 데이터를 불변 객체로 표현하는 Java 14+의 새로운 기능
✔ 자동으로 final 적용 (불변 객체)
✔ 필드, 생성자, Getter, equals(), hashCode(), toString() 자동 생성
✔ 데이터를 간결하게 표현하는 용도
✔ DTO에서 반복되는 코드를 줄일 수 있음
✔ 추가적인 로직(메서드) 정의 가능, 하지만 상태 변경 불가능
public record UserRecord(Long id, String name, int age) { }
🚀 위 코드만 작성해도 생성자, Getter, toString(), equals(), hashCode()가 자동 생성됨!
| 비교 항목 | DTO (클래스 기반) | Record (Java 14+) |
|---|---|---|
| 불변성 | final 선언해야 가능 | 항상 불변 (mutable 불가) |
| 코드 양 | 많음 (getter/setter, 생성자 필요) | 적음 (자동 생성) |
| 객체 상태 변경 | setXxx() 메서드로 변경 가능 | 변경 불가 |
| 기능 추가 가능 여부 | 커스텀 로직 가능 (메서드 추가 가능) | 메서드 추가 가능, 상태 변경 불가 |
| 직렬화 | implements Serializable 필요 | 자동 직렬화 가능 |
| Spring 사용 시 | @Getter, @Setter, @NoArgsConstructor, @AllArgsConstructor 필요 (Lombok 사용 가능) | 별도 어노테이션 없이도 가능 |
| 상황 | DTO (클래스 기반) | Record |
|---|---|---|
| 불변 객체가 필요한 경우 | ❌ 가능하지만, final로 직접 지정해야 함 | ✅ 항상 불변 |
| Spring에서 사용 (Request/Response) | ✅ 일반적으로 사용 | ✅ 가능하지만, 일부 라이브러리 호환 이슈 있음 |
| 복잡한 비즈니스 로직 포함 | ✅ 가능 | ❌ 복잡한 상태 변경 불가 |
| 가독성과 간결한 코드가 중요 | ❌ Getter/Setter 필요 | ✅ 코드가 훨씬 간결 |
| 직렬화(Serializable) 필요 | ❌ 직접 구현 필요 | ✅ 자동 가능 |
record를 추천할 수도 있음.record는 불변성이 강제되므로 JPA에서 엔티티 변경이 필요한 경우 DTO 클래스를 사용하는 것이 더 적절 .record는 @RequestBody로 JSON 데이터를 받을 때도 잘 동작함.record 사용 (더 간결하고 안전함)record 사용 가능하지만, 상황에 따라 DTO 클래스가 더 적절한마디로, record는 가볍고 불변성을 보장해야 할 때, DTO는 더 유연한 데이터 구조가 필요할 때 사용!