| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 |
- builder-pattern
- OpenSearch
- React
- object-creation
- 회고
- ReverseNested
- 클린 아키텍처
- HashMap
- Level2
- 글또
- axios
- 포트앤어댑터 아키텍처
- 가용영역
- DevOps
- 레벨1
- 코엑스그랜드볼룸
- static-factory-method
- UserLand
- 3계층 아키텍처
- 프로그래머스
- design-pattern
- 글쓰기세미나
- 헥사고날 아키텍처
- SpringBoot
- 다짐글
- 클라우드아키텍처
- 코딩테스트
- 글또10기
- QueryDSL
- constructor
- Today
- Total
oguri's garage
Spring DTO 설계 시 기본 생성자만 두는 이유 본문
Spring 기반 서버 개발을 하다 보면 Request DTO를 어떻게 설계해야 할지 고민하게 된다.
Lombok의 여러 어노테이션 중 무엇을 사용해야 하는지, record를 써도 되는지, 왜 @AllArgsConstructor는 피해야 하는지에 대한 경험을 정리한다.
불변 전달 객체는 클래스 또는 record로
단순히 값을 담아 전달하는 DTO는 두 가지 방식으로 설계할 수 있다.
방식 1: Lombok 기반 클래스
@Getter
@NoArgsConstructor
public class UserRequest {
private String name;
private int age;
}
방식 2: Java 17+ record
public record UserRequest(
String name,
int age
) {}
두 방식 모두 Spring의 @RequestBody, @ModelAttribute로 역직렬화할 때 문제없이 동작한다.
값 변경이 필요 없는 단순 전달 객체라면 어떤 방식을 선택해도 안전하다.
@AllArgsConstructor를 만들지 않는 이유
Spring의 JSON 역직렬화(Jackson)는 기본 생성자를 통해 객체를 생성한 뒤 필드에 값을 주입하는 방식으로 동작한다.@AllArgsConstructor만 있으면 기본 생성자가 생성되지 않아 다음과 같은 오류가 발생한다.
Cannot construct instance of `UserRequest`
(no Creators, like default constructor, exist)
Request DTO는 setter나 전체 생성자 호출이 거의 필요 없다.
이런 생성 경로는 주로 Service나 Entity 계층에서 Builder 패턴으로 사용된다.
불필요한 객체 생성 경로를 막고 역직렬화를 보장하기 위해 기본 생성자만 두는 것이 안전하다.
값 변경이 필요한 경우
DTO의 값을 수정해야 하는 상황이라면 setter 방식보다는 불변 패턴을 사용한다.
// 안티패턴: setter 사용
request.setName("newName");
// 권장: 새 객체 생성
UserRequest updated = UserRequest.builder()
.name("newName")
.age(request.getAge())
.build();
record는 불변 객체이므로 값 변경 시 항상 새 객체를 생성해야 한다.
이것이 오히려 불변성을 보장하는 장점이 된다.
권장사항
단순 불변 전달 객체
- 클래스 방식:
@Getter,@NoArgsConstructor조합 - record 방식: Java 17+ 환경이라면 record 활용
- 필드 기본값은 선언부에서 직접 할당
복잡한 객체나 값 변경 필요 시
@Builder패턴 추가- 불변성 유지를 위해 새 객체 생성 방식 사용
핵심 정리
Request DTO는 불변 전달 객체로 설계하는 것이 안전하다.
클래스에 Lombok을 적용하든 record를 사용하든 Spring/Jackson과 문제없이 호환되며, 역직렬화 이슈도 발생하지 않는다.@AllArgsConstructor는 역직렬화를 방해하므로 피하고, 기본 생성자만 제공하는 것이 실무에서 검증된 방식이다.
프로젝트 환경과 코드 스타일에 맞춰 자유롭게 선택하되, 불변성과 명확한 생성 경로를 유지하는 것이 중요하다.
'개발하다 > Spring' 카테고리의 다른 글
| Spring Boot 외부 설정 우선순위 정리 (0) | 2025.11.01 |
|---|---|
| JPA Entity에서 Lombok @EqualsAndHashCode 사용 시 주의사항 (0) | 2025.10.24 |
| Spring Data JPA Native Query에서 만난 InvalidDataAccessApiUsageException (0) | 2025.10.21 |
| DB부터 시작하는 JPA Entity 매핑 정리 (0) | 2025.10.20 |
| JPA에서 DISTINCT가 필요한 경우와 필요하지 않은 경우 (0) | 2025.10.18 |