이번 글에서는 타입스크립트 백엔드 프레임워크인 Nest.js에서 POST나 PUT과 데이터 요청이 들어왔을때 그 데이터가 적절한 데이터인지 확인하는 validation과
GET을 했을때 서버 데이터에서 가지고 있는 raw데이터 형식이 아니라 중간에서 Interceptor하여 다른 형태의 데이터로 변환 시켜 줄 수 있는 transform을 한번 해보려고 한다.
먼저 테스트 하기 위한 데이터를 ts파일에서 넣는다.
typescriptexport type ReportType = 'income'
NestJS에서 ValidationPipe로 요청을 역직렬화하고 ClassSerializerInterceptor로 응답을 직렬화하는 방법을 정리합니다.
2026. 3. 28.BackendNestJS Pipe로 입력 데이터를 변환하고 검증하는 방법을 내장 파이프, DTO 기반 ValidationPipe, 커스텀 파이프로 정리합니다.
2026. 3. 29.BackendNestJS에서 DTO 패턴과 class-validator, class-transformer로 클라이언트 요청을 안전하게 검증하고 변환하는 방법을 정리합니다.
2026. 3. 28.데이터 구조는 아래와 같이 이루어져있고, POST를 통해 데이터를 삽입하는 것으로 예시를 들어보겠다.
typescript@Post() createReport(@Param('type') pType: ReportType, @Body() body: Report) { return this.appService.createReport(pType, body); }
typescriptcreateReport(pType: ReportType, body: Report) { if (!isDataType(pType)) { return { message: '잘못된 타입' }; } const newReport: Reports['reports'][number] = { id: uuid(), created_at: new Date(), updated_at: new Date(), type: pType, ...body, }; data.reports.push(newReport); return data; }
위와 같은 형식으로 컨트롤러를 처리하면 아직 validation이 안되는 상태이기때문에 잘못된 데이터가 들어와도 에러가 발생하지 않고 컨트롤러 진입하게된다.

typescript{ "reports": [ { "id": "uuid", "source": "Salary", "amount": 7500, "created_at": "2022-05-22T02:07:35.647Z", "updated_at": "2022-05-22T02:07:35.647Z", "type": "income" }, { "id": "uuid232", "source": "Salary", "amount": 7500, "created_at": "2022-05-22T02:07:35.647Z", "updated_at": "2022-05-22T02:07:35.647Z", "type": "income" }, { "id": "uuid2", "source": "Youtube", "amount": 300, "created_at": "2022-05-22T02:07:35.647Z", "updated_at": "2022-05-22T02:07:35.647Z", "type": "expense" }, { "id": "uuid3", "source": "Facebook", "amount": 7500, "created_at": "2022-05-22T02:07:35.647Z", "updated_at": "2022-05-22T02:07:35.647Z", "type": "expense" }, { "id": "d283f562-7598-41ab-8321-4a3ce28c0b7b", "created_at": "2022-05-22T02:07:40.157Z", "updated_at": "2022-05-22T02:07:40.157Z", "type": "income", "amount": -1, "source": "" } ] }
만약 오로지 양수인 amount와 반드시 입력된 source가 있는 데이터를 받고 그 외 데이터가 들어오면 오류를 발생시키려면 어떻게 해야할까?
src → dto → report.dto 생성 후 아래와 같이 입력
typescriptimport { IsNotEmpty, IsNumber, IsPositive, IsString, } from 'class-validator'; export class CreateReportDto { @IsNumber() @IsPositive() amount: number; @IsString() @IsNotEmpty() source: string; }
IsNumber → 오직 숫자만
IsPositive → 오직 양수만
IsString → 오직 문자만
IsNotEmpty → 무조건 값이 필요
body타입에 해당 Dto 인스턴스 타입을 넣어준다
typescript@Post() createReport( @Param('type') pType: ReportType, @Body() body: CreateReportDto, ) { return this.appService.createReport(pType, body); }

요청이 들어오고 응답을 Interceptor하여 변형된 응답값을 리턴해주고 싶을땐 어떻게 해야할까?
typescript@Get(':id') getReportById(@Param('type') pType: ReportType, @Param('id') pId: string) { return this.appService.getReportById(pType, pId); }
typescriptgetReportById(pType: ReportType, pId: string): ReportResponseDto { const result = data.reports .filter(({ type }) => type === pType) .find(({ id }) => id === pId); return result; }

만약 위 처럼 서버에 저장되어있는 데이터 형태 그대로 말고 좀 다르게 변형된 형태로 return 해주고 싶으면 어떻게 해야할까?
예를들어 updated_at이라는 데이터는 응답이 안내려가고 created_at이라는 키는 camel case로 createdAt으로 내려주고 싶다면 말이다.
이것또한 Dto를 사용하여 만들어 줄 수 있다.
typescriptexport class ReportResponseDto { id: string; source: string; amount: number; @Expose({ name: 'createdAt' }) created_at: Date; @Exclude() updated_at: Date; type: ReportType; constructor(partial: Partial<ReportResponseDto>) { Object.assign(this, partial); } }
typescriptgetReportById(pType: ReportType, pId: string): ReportResponseDto { const result = data.reports .filter(({ type }) => type === pType) .find(({ id }) => id === pId); return new ReportResponseDto(result); }
typescriptimport { ValidationPipe } from '@nestjs/common'; import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; async function bootstrap() { const app = await NestFactory.create(AppModule); app.useGlobalPipes( new ValidationPipe({ transform: true, transformOptions: { enableImplicitConversion: true, }, }), ); await app.listen(3000); } bootstrap();
typescriptimport { ClassSerializerInterceptor, Module } from '@nestjs/common'; import { APP_INTERCEPTOR } from '@nestjs/core'; import { AppController } from './app.controller'; import { AppService } from './app.service'; @Module({ imports: [], controllers: [AppController], providers: [ AppService, { provide: APP_INTERCEPTOR, useClass: ClassSerializerInterceptor, }, ], }) export class AppModule {}
이상 Dto의 개념과 dto를 사용하여 validation과 transform 작업을 하는 방법을 알아보았다.