본문 바로가기
Framework/nestjs

[Nest.js] DTO란?

by Lseing 2025. 7. 7.

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

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