DTO
📦 DTO란?
정의
DTO(Data Transfer Object)는 계층 간 데이터를 전달하기 위해 사용하는 객체이다. 특히 API 요청과 응답처럼 표현용 데이터를 분리해서 다룰 때 유용하다.
DTO는 Entity와 분리해서 사용하며, 필요한 데이터만 담는 용도로 설계한다.
🎯 DTO의 주요 목적
- 계층 간 데이터 전달을 명확하게 구분한다.
- Entity에 종속되지 않는 표현 전용 구조를 만든다.
- API 응답에서 불필요한 정보를 노출하지 않는다.
- 요청과 응답 형태를 화면이나 API에 맞게 유연하게 조정한다.
🧩 DTO와 Entity의 차이점
| 항목 | Entity | DTO |
|---|---|---|
| 목적 | DB 테이블과 매핑 | 데이터 전달 |
| 포함 정보 | 도메인 전체 데이터 | 필요한 데이터만 |
| 위치 | 영속성 계층과 밀접 | Controller, Service 경계 |
| 책임 | 비즈니스 로직과 상태 표현 | 전달과 표현 중심 |
구분 포인트
Entity는 저장에 가깝고, DTO는 전달에 가깝다. 둘을 섞으면 구조는 편해 보일 수 있지만, 유지보수성이 떨어질 수 있다.
🧷 주요 어노테이션 비교
| 어노테이션 | 전달 방식 | 주 사용 용도 | DTO 바인딩 | Bean Validation 적용 |
|---|---|---|---|---|
@RequestParam |
쿼리 파라미터, 폼 데이터 | 단일 값, 간단한 입력 | ❌ | ✅ (@Validated와 함께 사용) |
@RequestBody |
JSON 등 HTTP Body | 복잡한 JSON 구조 | ✅ | ✅ |
@ModelAttribute |
쿼리 파라미터, 폼 데이터 | 폼 전체 객체 바인딩 | ✅ | ✅ |
✍️ 사용 예시
✅ @RequestParam 예시
@GetMapping("/search")
public String search(@RequestParam String keyword) {
return "검색어: " + keyword;
}
✅ @RequestBody 예시
@PostMapping("/users")
public ResponseEntity<String> createUser(@RequestBody @Valid UserRequest request) {
return ResponseEntity.ok("사용자 등록 완료: " + request.getName());
}
✅ @ModelAttribute 예시
@PostMapping("/form")
public String submitForm(@ModelAttribute UserForm userForm) {
return "제출 완료: " + userForm.getName();
}
🧱 DTO 사용 예제
1️⃣ DTO 클래스 정의
public class UserResponseDTO {
private String name;
private String email;
public UserResponseDTO(String name, String email) {
this.name = name;
this.email = email;
}
// getter, setter 생략
}
2️⃣ Entity → DTO 변환 예시
User user = userRepository.findById(1L).orElseThrow();
UserResponseDTO dto = new UserResponseDTO(user.getName(), user.getEmail());
활용
DTO는 조회 결과를 그대로 내보내기보다 응답 전용 형태로 가공할 때 특히 유용하다.
🛠️ DTO 자동 매핑 도구
| 라이브러리 | 특징 |
|---|---|
ModelMapper |
필드 이름 기반 자동 매핑 |
MapStruct |
컴파일 타임 매핑, 성능 우수 |
Orika |
속도와 유연성을 함께 제공 |
[!important] 선택 기준 단순함이 필요하면
ModelMapper, 성능과 명확성이 중요하면MapStruct를 고려한다.
✅ 장점과 단점
장점
- 도메인 모델과 API 응답 구조를 분리할 수 있다.
- 불필요한 정보 노출을 줄일 수 있다.
- View 또는 API에 맞는 형태로 쉽게 가공할 수 있다.
- 요청 DTO와 응답 DTO를 나눠서 더 명확하게 설계할 수 있다.
단점
- DTO 클래스가 많아지면 관리 비용이 늘어난다.
- Entity와 DTO 사이 변환 로직이 필요하다.
- 작은 프로젝트에서는 오히려 코드가 늘어나 보일 수 있다.
댓글남기기