Spring Boot DTO 설계 시 반드시 알아야 하는 작성 원칙을 정리해 드립니다. DTO의 역할부터 Request·Response DTO 분리, Validation 적용, Entity 분리 이유, 실무 설계 방법과 예제까지 한 번에 이해하실 수 있습니다.

Spring Boot를 처음 공부하시는 분들이 가장 많이 헷갈리는 개념 중 하나가 바로 DTO(Data Transfer Object)입니다. 프로젝트를 시작하면 Controller, Service, Entity, DTO가 함께 등장하기 때문에 각각의 역할을 명확하게 이해하지 못하면 코드가 빠르게 복잡해질 수 있습니다.
특히 규모가 커지는 프로젝트에서는 DTO를 어떻게 설계했는지가 유지보수성과 확장성을 크게 좌우합니다. 처음에는 단순한 객체처럼 보이지만 시간이 지나면서 Request와 Response가 섞이고 Entity가 그대로 노출되기 시작하면 수정해야 할 범위가 계속 늘어나는 문제가 발생할 수 있습니다.
이번 글에서는 Spring Boot DTO란 무엇인지, DTO를 어떻게 설계해야 하는지, 그리고 실무에서 많이 사용하는 작성 원칙까지 차근차근 살펴보겠습니다.
01. 핵심 기준 한눈에 보기
이번 섹션에서는 DTO 설계 시 가장 먼저 기억해야 할 핵심 원칙을 소개해 드립니다.
DTO를 설계할 때는 아래 원칙만 기억하셔도 대부분의 프로젝트에서 좋은 구조를 만들 수 있습니다.
항목권장 방법
| Entity 직접 전달 | 사용하지 않는 것이 좋습니다. |
| Request와 Response | 서로 분리하는 것이 좋습니다. |
| Validation | DTO에서 처리하는 것이 좋습니다. |
| 비즈니스 로직 | Service에서 처리하는 것이 좋습니다. |
| 데이터 전달 | DTO가 담당하는 것이 좋습니다. |
| DB 매핑 | Entity가 담당하는 것이 좋습니다. |
✓ 확인할 점
DTO는 데이터를 전달하는 역할만 수행하는 객체라고 이해하시면 됩니다.
즉, 데이터베이스와 직접 연결되는 객체도 아니고, 비즈니스 로직을 수행하는 객체도 아닙니다.
02. Spring Boot DTO란 무엇일까요?
이번 섹션에서는 DTO의 개념과 사용하는 이유를 이해해 보겠습니다.
DTO는 Data Transfer Object의 약자로, 계층 간 데이터를 전달하기 위해 사용하는 객체입니다.
예를 들어 회원가입 API를 만든다고 가정해 보겠습니다.
클라이언트에서는 아래와 같은 JSON을 전송합니다.
{
"name": "홍길동",
"email": "test@test.com",
"password": "1234"
}
Spring Boot에서는 이 JSON을 DTO로 변환하여 Controller에서 받을 수 있습니다.
public class MemberCreateRequest {
private String name;
private String email;
private String password;
}
Controller에서는 다음과 같이 사용할 수 있습니다.
@PostMapping("/members")
public ResponseEntity<?> create(
@RequestBody MemberCreateRequest request) {
return ResponseEntity.ok().build();
}
✓ 확인할 점
JSON을 직접 다루는 것이 아니라 DTO를 통해 객체 형태로 전달받기 때문에 코드의 가독성과 유지보수성이 좋아집니다.
03. Entity와 DTO를 반드시 분리해야 하는 이유
이번 섹션에서는 많은 개발자가 DTO를 사용하는 가장 중요한 이유를 설명해 드립니다.
Spring Boot에서는 Entity와 DTO를 분리하는 것이 일반적으로 권장됩니다.
만약 Entity를 그대로 외부에 노출하면 여러 문제가 발생할 수 있습니다.
✓ Entity를 그대로 사용하는 문제점
- 데이터베이스 구조가 그대로 노출될 수 있습니다.
- 불필요한 컬럼까지 함께 전달될 수 있습니다.
- 내부 구현이 외부 API와 강하게 결합됩니다.
- 데이터베이스 구조가 변경될 경우 API도 함께 수정해야 할 가능성이 커집니다.
- 보안상 노출하면 안 되는 데이터가 함께 전달될 수 있습니다.
예를 들어 Entity에 아래와 같은 필드가 있다고 가정해 보겠습니다.
private String password;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
회원 목록 API에서는 이름과 이메일만 필요할 수도 있습니다.
이럴 때 Response DTO를 사용하면 필요한 데이터만 전달할 수 있습니다.
public class MemberResponse {
private Long id;
private String name;
private String email;
}
✓ 확인할 점
API는 필요한 데이터만 전달하는 것이 가장 좋은 설계 방법입니다.
04. Request DTO와 Response DTO는 분리하는 것이 좋습니다
이번 섹션에서는 DTO를 역할별로 나누는 이유를 알아보겠습니다.
실무에서는 하나의 DTO를 모든 곳에서 사용하는 것보다 목적에 따라 나누는 경우가 많습니다.
✓ Request DTO
사용자로부터 입력받는 데이터를 담습니다.
예를 들면 다음과 같습니다.
- 회원가입
- 로그인
- 게시글 작성
- 댓글 작성
예시
MemberCreateRequest
LoginRequest
BoardWriteRequest
✓ Response DTO
클라이언트에게 반환하는 데이터를 담습니다.
예시
MemberResponse
LoginResponse
BoardResponse
✓ 확인할 점
Request와 Response를 분리하면 필요한 데이터만 전달할 수 있고 API 변경에도 유연하게 대응할 수 있습니다.
05. Validation은 DTO에서 처리하는 것이 좋습니다
이번 섹션에서는 DTO에서 입력값을 검증하는 방법을 살펴보겠습니다.
Spring Boot에서는 입력값 검증을 DTO에 작성하는 경우가 많습니다.
예를 들어 이름과 이메일을 반드시 입력받아야 한다면 다음과 같이 작성할 수 있습니다.
public class MemberCreateRequest {
@NotBlank
private String name;
@Email
private String email;
@NotBlank
private String password;
}
Controller에서는 다음과 같이 사용할 수 있습니다.
@PostMapping("/members")
public ResponseEntity<?> create(
@Valid @RequestBody MemberCreateRequest request) {
return ResponseEntity.ok().build();
}
✓ Validation의 장점
- Controller 코드가 단순해집니다.
- 잘못된 요청을 빠르게 검증할 수 있습니다.
- 입력 규칙을 DTO에 모아서 관리할 수 있습니다.
- 유지보수가 쉬워집니다.
06. DTO에는 비즈니스 로직을 넣지 않는 것이 좋습니다
이번 섹션에서는 DTO가 담당하지 않아야 하는 역할을 설명해 드립니다.
DTO는 데이터를 전달하기 위한 객체입니다.
따라서 아래와 같은 기능은 DTO에 작성하지 않는 것이 일반적으로 좋습니다.
- 회원가입 처리
- 데이터 저장
- 권한 검사
- 비밀번호 암호화
- 결제 처리
이러한 기능은 Service 계층에서 처리하는 것이 역할을 명확하게 구분하는 데 도움이 됩니다.
✓ 좋은 구조
- Controller : 요청과 응답 처리
- DTO : 데이터 전달
- Service : 비즈니스 로직
- Repository : 데이터베이스 접근
- Entity : 데이터베이스 매핑
역할을 명확히 나누면 테스트와 유지보수가 쉬워지고 코드의 책임도 분명해집니다.
07. DTO 이름은 목적이 드러나도록 작성하는 것이 좋습니다
이번 섹션에서는 실무에서 많이 사용하는 네이밍 방법을 소개해 드립니다.
아래와 같은 이름은 의미가 명확하지 않을 수 있습니다.
MemberDto
UserDto
BoardDto
반면 아래처럼 목적이 드러나는 이름은 어떤 용도로 사용하는지 바로 이해할 수 있습니다.
MemberCreateRequest
MemberUpdateRequest
MemberResponse
LoginRequest
LoginResponse
BoardDetailResponse
BoardListResponse
✓ 확인할 점
DTO 이름에는 무엇을 위한 객체인지가 포함되는 것이 가독성과 유지보수에 도움이 됩니다.
08. DTO 설계 시 자주 하는 실수
이번 섹션에서는 초보 개발자가 자주 경험하는 실수를 정리해 보겠습니다.
✓ Entity를 그대로 반환하는 경우
데이터베이스 구조가 외부에 노출될 수 있습니다.
✓ 하나의 DTO만 사용하는 경우
생성, 수정, 조회까지 모두 하나의 DTO를 사용하면 불필요한 필드가 계속 늘어날 수 있습니다.
✓ Validation을 작성하지 않는 경우
입력값 검증이 Controller나 Service에 흩어질 수 있습니다.
✓ DTO에 비즈니스 로직을 작성하는 경우
객체의 역할이 모호해지고 유지보수가 어려워질 수 있습니다.
✓ 모든 API에서 동일한 Response를 사용하는 경우
API마다 필요한 데이터가 다르므로 목적에 맞는 Response DTO를 만드는 것이 좋습니다.
09. 실무에서 추천하는 DTO 설계 방법
이번 섹션에서는 유지보수하기 좋은 DTO 구조를 정리해 드립니다.
프로젝트 규모와 요구 사항에 따라 달라질 수 있지만 다음과 같은 방식은 많은 Spring Boot 프로젝트에서 활용되는 구조입니다.
dto
├── request
│ ├── LoginRequest
│ ├── MemberCreateRequest
│ └── MemberUpdateRequest
│
├── response
│ ├── LoginResponse
│ ├── MemberResponse
│ └── BoardResponse
│
└── common
└── ApiResponse
✓ 장점
- 목적별로 DTO를 쉽게 찾을 수 있습니다.
- 기능이 늘어나도 구조를 유지하기 쉽습니다.
- 협업 시 코드 이해가 쉬워집니다.
- API 확장에 유연하게 대응할 수 있습니다.
10. 마무리
이번 글에서는 Spring Boot DTO 설계 시 꼭 알아야 하는 작성 원칙을 살펴보았습니다.
DTO는 단순히 데이터를 담는 객체처럼 보일 수 있지만, 프로젝트가 커질수록 구조를 얼마나 잘 설계했는지가 유지보수성과 확장성에 큰 영향을 미칠 수 있습니다.
특히 Entity와 DTO를 분리하고, Request와 Response를 구분하며, Validation을 DTO에서 처리하는 구조를 적용하면 코드의 책임이 명확해지고 API 관리도 한층 수월해질 수 있습니다.
처음부터 완벽한 구조를 만드는 것보다 역할을 분명하게 나누는 습관을 들이는 것이 장기적으로 더 안정적인 Spring Boot 프로젝트를 만드는 데 도움이 됩니다.
FAQ
Q1. Spring Boot에서 DTO는 반드시 사용해야 하나요?
작은 예제에서는 DTO 없이도 구현할 수 있지만, 프로젝트 규모가 커질수록 Entity와 API를 분리하기 위해 DTO를 사용하는 경우가 많습니다.
Q2. Entity를 그대로 반환하면 안 되나요?
기술적으로는 가능하지만 데이터베이스 구조가 외부에 노출되거나 불필요한 정보가 전달될 수 있으므로 DTO를 사용하는 방법이 일반적으로 권장됩니다.
Q3. Request DTO와 Response DTO를 꼭 나눠야 하나요?
반드시 나누어야 하는 것은 아니지만 입력 데이터와 출력 데이터의 목적이 다르기 때문에 분리하면 유지보수와 확장에 유리한 경우가 많습니다.
Q4. Validation은 어디에 작성하는 것이 좋나요?
입력값 검증은 DTO에 작성하고 Controller에서 @Valid를 사용하는 방식이 널리 활용됩니다.
Q5. DTO에 비즈니스 로직을 넣어도 되나요?
DTO는 데이터 전달 역할에 집중하고, 비즈니스 로직은 Service 계층에서 처리하는 구조가 일반적으로 유지보수에 유리합니다.
'실무개발' 카테고리의 다른 글
| JSON 응답 구조 표준화하는 방법과 API 설계 팁 (1) | 2026.07.17 |
|---|---|
| REST API 응답 형식 ResponseEntity 사용법 총정리 (0) | 2026.07.16 |
| Jackson ObjectMapper 사용법과 JSON 변환 예제 정리 (0) | 2026.07.14 |
| Spring Boot JSON 데이터 처리 과정 완벽 이해하기 (0) | 2026.07.13 |
| Spring Boot RequestBody와 RequestParam 차이 쉽게 이해하기 (0) | 2026.07.13 |
