본문 바로가기
Category/NestJs

NestJS에서 DTO는 왜 클래스(class)로 작성해야 할까?

by Corinee 2025. 4. 8.
728x90
반응형

NestJS 실습을 하다 보면 DTO(Data Transfer Object)를 클래스(class)로 작성하는 것을 자주 보게 됩니다. 그런데 TypeScript에서는 interface도 타입 정의가 가능한데, 왜 하필 클래스를 쓰는 걸까요?

그 이유는 바로 런타임(Runtime)에 있습니다.

interface는 컴파일 타임에만 존재

TypeScript의 interface는 오직 컴파일 타임에만 존재합니다. 즉, TypeScript가 JavaScript로 변환될 때 인터페이스는 전부 사라집니다. 런타임에는 아무 정보도 남아있지 않기 때문에, 실행 중에 이 타입을 활용할 수 없습니다.

interface CreateUserDto {
  name: string;
}

이렇게 작성된 인터페이스는 JS로 컴파일되면 완전히 없어집니다. 따라서 이 타입을 기반으로 실행 중에 유효성 검사를 하거나, 메타데이터를 읽는 작업은 불가능합니다.

class는 런타임에 남는다

반면 class는 런타임에도 객체 형태로 남아있습니다. 즉, 데코레이터를 통한 메타데이터 수집이나 NestJS의 ValidationPipe 같은 기능을 사용할 수 있게 됩니다.

import { IsString } from 'class-validator';

export class CreateUserDto {
  @IsString()
  name: string;
}

이렇게 클래스에 @IsString() 같은 데코레이터를 붙여놓으면, NestJS는 ValidationPipe를 통해 자동으로 유효성 검사를 수행할 수 있습니다.

예: ValidationPipe와 함께 쓰기

@Post()
@UsePipes(new ValidationPipe())
create(@Body() createUserDto: CreateUserDto) {
  return this.userService.create(createUserDto);
}