Spring Boot에서 Java record를 DTO로 사용하는 방법
Spring Boot 프로젝트에서 데이터를 주고받는 DTO(Data Transfer Object)를 정의할 때, Java 16부터 정식 도입된 record를 활용하면 더 간결하고 명확한 코드를 작성할 수 있습니다. 본 글에서는 record란 무엇인지, DTO로 사용할 때의 장점과 주의사항을 정리합니다.
record란 무엇인가?
record는 Java에서 불변 데이터 구조를 간결하게 표현할 수 있도록 도입된 키워드입니다. 흔히 DTO처럼 데이터를 담기만 하는 클래스에 적합합니다.
public record UserDTO(String name, int age) {}
위 한 줄의 코드는 다음과 같은 클래스와 동일한 기능을 합니다:
public class UserDTO {
private final String name;
private final int age;
public UserDTO(String name, int age) {
this.name = name;
this.age = age;
}
public String name() { return name; }
public int age() { return age; }
@Override
public String toString() { return ... }
@Override
public boolean equals(Object o) { return ... }
@Override
public int hashCode() { return ... }
}
Spring Boot에서 DTO로 record를 사용할 때의 장점
항목 | 설명 |
코드 간결성 | 생성자, getter, equals, hashCode 등을 자동 생성 |
불변성 보장 | 모든 필드는 final, setter 없음 |
직렬화 호환 | Spring에서 @RequestBody, @ResponseBody에 기본적으로 잘 작동 |
유지보수 용이 | DTO의 구조를 직관적으로 파악 가능 |
실전 예제: 회원 가입 요청 DTO로 사용하기
1. record 기반 Request DTO 정의
public record RegisterUserRequest(String email, String password, String name) {}
2. Controller에서 사용
@PostMapping("/register")
public ResponseEntity<String> register(@RequestBody RegisterUserRequest request) {
userService.register(request.email(), request.password(), request.name());
return ResponseEntity.ok("회원가입 완료");
}
주의할 점
1. Setter가 없다
record는 불변(immutable) 객체이므로 setter가 없습니다. 필드 수정이 필요한 경우 class를 사용하세요.
2. 기본 생성자 없음
기본 생성자가 없기 때문에 Jackson이 JSON → Object 변환 시 모든 필드를 정확히 매칭해야 합니다. 아래 JSON과 필드명이 달라지면 오류가 발생합니다:
{
"email": "test@example.com",
"password": "secure123",
"name": "John Doe"
}
3. Lombok과 혼용 불가
@Builder, @NoArgsConstructor 같은 Lombok 어노테이션은 record에 사용할 수 없습니다. 생성자나 빌더가 필요한 경우 class를 사용하세요.
언제 record를 DTO에 쓰면 좋은가?
추천 사용처:
- Controller의 입력/출력 DTO
- 조회 전용 Query DTO
- 변형 없이 전달만 하는 계층 간 데이터
지양할 곳:
- 상태 변화가 필요한 Command 객체
- 빌더 패턴이 필요한 복잡한 생성 구조
실무에서는 record를 사용할까?
사용되는 경우
- 조회 전용 응답 DTO
- REST API의 출력 전용 데이터에 적합
- ex) ProductSummary, UserProfileView
- 단순 요청 DTO
- 수정이 필요 없는 @RequestBody용 객체
사용이 어려운 경우
- 상태 변경이 필요한 객체 (Command 등)
- 복잡한 생성자나 Lombok @Builder가 필요한 경우
- 엔티티(Entity) → JPA에서 record는 지원되지 않음
실제 기업 사례
- Java 17 이상을 도입한 기업에서는 점진적으로 도입 중
- 쿠팡, 배달의민족 등 일부 기업에서 조회 응답 DTO 위주로 활용
정리
상황 | record 사용 여부 | 비고 |
REST API 응답 DTO | 사용 권장 | 간결하고 직관적 |
단순 요청(Request) DTO | 조건부 사용 | JSON 필드 일치 필요 |
DB Entity | 사용 지양 | JPA 미지원 |
상태 변경이 필요한 객체 | 사용 지양 | 불변성 문제 |
Builder 패턴 필요한 경우 | 사용 불가 | 일반 class 사용 |
마치며
Spring Boot에서 DTO를 정의할 때 record는 불변성과 간결함을 동시에 잡을 수 있는 좋은 도구입니다. 다만, 모든 상황에 적합한 것은 아니며 쓰임새에 따라 class와 record를 적절히 나누어 사용하는 것이 중요합니다.
Spring Boot + Java 17 이상 환경이라면, DTO 작성의 기본값으로 record를 도입해보는 것도 추천드립니다.
'백엔드 개발' 카테고리의 다른 글
[Node.js] Redis + DB로 안전하게 토큰 관리하기 – 실전 적용기 (1) | 2024.01.02 |
---|