해당 글은 개인적으로 공부하면서 기록하는 글로써 잘못된 점이나 보충할 점이 있다면 많은 댓글 부탁드립니다~

DTO는 (Data Transfer Object)의 약자로 데이터를 안전하게 주고받기 위한 규칙서라고 이해하면 될거 같다
조금 더 쉽게 이해하기 위해
택배 상자를 DTO, 실제 물건을 데이터라 가정하고 택배를 보낼 때 행동을 보자:
- 상자에 라벨 붙이기 (어떤 데이터인지)
- 깨지기 쉬운 물건 표시 (검증 규칙)
- 수령인 확인 (타입 체크)
🔵 DTO는 왜 필요할까?
우선 DTO는 민감한 데이터가 노출되는 것을 방지해준다.
Entity를 직접 사용하는 것 보다 DTO를 사용해서 필요한 정보만 받으면 된다.
// ❌ Entity를 직접 사용하는 경우
@Post
create(@Body() box: Box) { //위험함
return this.boxService.create(box);
}
이렇게 Entity를 직접 사용한다면 클라이언트가 아래와 같은 데이터를 보낼 수 있는 문제가 있다.
{
"id": 99999, //해커가 임의로 설정
"address": "", //빈 문자열
"date": "abc", // 숫자가 아닌 문자
"request": "",
"adminSecret": "hack" // 존재하지 않는 필드
}
DTO를 사용한다면 이런 문제를 해결할 수 있다.
// ✅ DTO로 안전하게 처리
export class CreateBoxDto {
@IsNumber()
@IsNotEmpty()
readonly id: number; // 숫자, 필수값
@IsNumber()
@IsNotEmpty()
readonly address: string; // 문자열, 필수값
@IsNumber()
@IsNotEmpty()
readonly date: number; // 숫자, 필수값
@IsOptional()
@IsString({ each: true })
readonly request: string; // 문자열, 선택사항
}
참고: DTO에서는 클라이언트가 서버로 보낼 수 있는 데이터만 다룬다
❓그렇다면 언제 생성해야 하죠?
1. API 엔드포인트를 만들 때마다
// POST /boxes - 물건 생성
@Post()
create(@Body() createBoxDto: CreateBoxDto) {
return this.boxesService.create(createBoxeDto);
}
// PATCH /boxes/:id - 물건 수정
@Patch(':id')
update(@Param('id') id: string, @Body() updateBoxDto: UpdateBoxDto) {
return this.boxesService.update(+id, updateBoxDto);
}
2. 클라이언트에서 받는 데이터와 DB 엔티티가 다를 때
//물건 엔티티
export class Box {
id: number; // 물건 고유 아이디
address: string; // 배송지
date: Date; // 배송 출발 시간
warn: boolean; // 취급 주의 여부
export class CreatedBoxDto {
readonly address: string;
readonly date: Date;
readonly warn: boolean;
}
간단한 판단 기준으로는
- ✅POST, PUT, PATCH 요청(데이터를 받을 때)
- ✅클라이언트 입력값과 DB 구조가 다를 때
- ✅유효성 검사가 필요할 때
- ✅보안상 특정 필드를 숨겨야 할 때
반대로 DTO가 필요없을 때에는
- ❌GET요청(단순 조회)
- ❌내부 서비스간 통신
- ❌매우 간단한 프로토타입
자주 하는 실수와 해결책 ⚠️
- 실수 1: readonly 빼먹기
// ❌ 나쁜 예
export class CreateBoxDto {
id: number; // 수정 가능
}
// ✅ 좋은 예
export class CreateBoxDto {
readonly id: number; // 불변
}
- 실수 2: 검증 없는 DTO
// ❌ 검증 없음
export class CreateBoxDto {
id: number;
address: string;
}
// ✅ 적절한 검증
export class CreateBoxDto {
@IsNumber()
@IsNotEmpty()
readonly id: number;
@IsString()
readonly address: string;
}
- 실수 3: Entity를 직접 노출
// ❌ 위험
@Post()
create(@Body() box: Box) {
return this.service.create(box);
}
// ✅ 안전
@Post()
create(@Body() createBoxDto: CreateBoxDto) {
return this.service.create(createBoxDto);
}
위에서 Entity라는 단어를 썼는데 모를 수 있기 때문에 간단하게 남겨봅니다
🧐 Entity란 무엇인가?
Entity는 데이터베이스의 테이블을 코드로 표현한것이다.
건물의 설계도를 Entity라고 한다면
실제 건물은 데이터베이스 테이블인 셈이다.
설계도에는 :
- 방의 구조(필드)
- 방의 크기(타입)
- 방의 용도(관계)
'Framework > nestjs' 카테고리의 다른 글
| [Nest.js] Entity란? (2) | 2025.07.10 |
|---|---|
| [Nest.js] 소켓(socket.io) (2) | 2025.07.09 |