낙서장이자 오답 노트이자 컨닝 페이퍼
패스트캠퍼스 환급챌린지 6일차 : 코드팩토리의 백엔드 아카데미 : 한 번에 끝내는 NestJS 패키지 - 기초부터 MSA까지 강의 후기 본문
패스트캠퍼스 환급챌린지 6일차 : 코드팩토리의 백엔드 아카데미 : 한 번에 끝내는 NestJS 패키지 - 기초부터 MSA까지 강의 후기
NangIn 2025. 4. 6. 20:49본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성하였습니다.
강의 내용 정리
dto 소개 및 사용해보기
DTO (Data Transfer Object)란?
- Controller에서 Body 데이터를 구조화하여 받기 위한 클래스
- 매번 @Body('title'), @Body('genre')처럼 받지 않고,
- 하나의 클래스로 타입 정의 후 통째로 받음
왜 DTO를 써야 하나?
- 코드 재사용
- 같은 구조의 요청이 여러 곳에 필요할 경우 DTO 클래스를 재활용 가능
- 유지보수 편의
- 필드가 추가되거나 바뀌어도 DTO만 수정하면 반영됨
- 가독성 향상
- controller에서 인자 나열 없이 .title, .genre로 바로 접근 가능
DTO 파일 생성 흐름
- createMovie.dto.ts
export class CreateMovieDto {
title: string;
genre: string;
}
- updateMovie.dto.ts
- update는 일부만 수정하므로 optional(?) 처리
export class UpdateMovieDto {
title?: string;
genre?: string;
}
서비스 메서드에 DTO 적용
// Before
createMovie(title: string, genre: string) { ... }
// After
createMovie(dto: CreateMovieDto) {
const movie = { ...dto, id: this.idCounter++ };
...
}
updateMovie(id: number, dto: UpdateMovieDto) {
const movie = this.findMovie(id);
Object.assign(movie, dto);
...
}
컨트롤러에 DTO 적용
@Post()
create(@Body() body: CreateMovieDto) {
return this.movieService.createMovie(body);
}
@Patch(':id')
update(@Param('id') id: string, @Body() body: UpdateMovieDto) {
return this.movieService.updateMovie(+id, body);
}
결과적으로 얻는 장점
- 인자 수 줄어들고, 스프레드 연산자로 유연하게 처리
- 바디 데이터에 대한 정의/검증의 기반을 마련
- class-validator와 함께 쓰면 유효성 검사도 가능해짐
Class Validator 소개
왜 Class Validator가 필요한가?
- NestJS에서 API를 만들 때, 타입만 선언해도 자동으로 유효성 검사가 될 거라 착각하기 쉬움
- 하지만 실제로는 title, genre와 같은 필드를 비워서 요청해도 정상 응답됨 → 이는 타입스크립트 타입만으로는 런타임 유효성 검사가 안 되기 때문임
- → 그래서 클래스 밸리데이터(Class-validator)가 필요함
Class-validator란?
- 타입스크립트 데코레이터를 활용해 클래스 속성에 유효성 규칙을 선언 (Validate)
- 비동기 및 동기 방식 모두 지원
- 기본 제공되는 Validator가 다양 (예: @IsNotEmpty, @IsEmail, @IsOptional)
- 커스텀 Validator& 에러 메시지도 가능
어떻게 사용하나?
- DTO 클래스에서 각 필드 위에 데코레이터 선언
import { IsNotEmpty, IsEmail } from 'class-validator';
export class CreateUserDto {
@IsNotEmpty({ message: '이름을 입력해 주세요.' })
name: string;
@IsEmail({}, { message: '정확한 이메일 주소를 입력해 주세요.' })
email: string;
}
기본 제공 Class Validator구분 Validator 종류
| 공통 Validator | @IsDefined, @IsOptional, @Equals, @NotEquals, @IsEmpty, @IsNotEmpty, @IsIn, @IsNotIn |
| 타입 Validator | @IsBoolean, @IsDate, @IsString, @IsNumber, @IsInt, @IsArray, @IsEnum |
| 숫자 Validator | @IsDivisibleBy, @IsPositive, @IsNegative, @Min, @Max |
| 문자 Validator | @Contains, @NotContains, @IsAlphanumeric, @IsCreditCard, @IsHexColor, @MaxLength, @MinLength, @IsUUID, @IsLatLng |
검증 실패 시 반환 에러 구조
{
target: Object;
property: string;
value: any;
constraints?: {
[type: string]: string;
};
children?: ValidationError[];
}
- target: 검증한 전체 객체
- property: 검증 실패한 프로퍼티
- value: 검증 실패한 값
- constraints: 검증 실패한 제약 조건 (isNotEmpty, isEmail 등)
- children: 프로퍼티의 모든 검증 실패 제약 조건
커스텀 에러 메세지
class User {
@IsNotEmpty({
message: '이름을 입력해주세요!'
})
name: string;
@IsEmail({}, {
message: '정확한 주소를 입력해주세요!'
})
email: string;
}
- Decorator의 message 프로퍼티에 검증 실패했을 때의 에러 메세지를 입력해주면 된다.
핵심 요약
- 타입만 선언한다고 런타임 유효성 검사가 되는 게 아님
- class-validator를 통해 요청 데이터의 유효성 보장
- 데코레이터 기반 선언식 문법으로 가독성 및 재사용성 향상
- NestJS + DTO + class-validator 조합 → 견고한 API 구성 가능
Class Validator 프로젝트에 적용하기
설치 및 환경 설정
pnpm add class-validator class-transformer
- class-validator: 유효성 검사 라이브러리
- class-transformer: 이후 DTO 변환 시 함께 사용됨
- main.ts 설정:
import { ValidationPipe } from '@nestjs/common';
app.useGlobalPipes(new ValidationPipe());
- ValidationPipe를 전역에 등록해야 DTO 유효성 검사가 동작함
DTO에 유효성 검사 데코레이터 추가
- 예시: create-movie.dto.ts
import { IsNotEmpty } from 'class-validator';
export class CreateMovieDto {
@IsNotEmpty()
title: string;
@IsNotEmpty()
genre: string;
}
- @IsNotEmpty() → 해당 필드는 빈 값이면 안 됨
Controller에 DTO 적용
@Post()
create(@Body() body: CreateMovieDto) {
return this.movieService.create(body);
}
- 바디를 DTO 클래스로 받으면, 유효성 검사가 자동으로 실행됨
PATCH처럼 선택적 필드 처리
- 예시: update-movie.dto.ts
import { IsOptional, IsNotEmpty } from 'class-validator';
export class UpdateMovieDto {
@IsOptional()
@IsNotEmpty()
title?: string;
@IsOptional()
@IsNotEmpty()
genre?: string;
}
- @IsOptional() → 해당 필드를 아예 안 보내도 에러가 나지 않음
- 조건부 유효성 검사가 가능해짐 (값이 있으면 유효성 검사, 없으면 스킵)
핵심 요약
- class-validator는 런타임 유효성 검사를 위한 핵심 도구
- DTO에 데코레이터만 붙이면 코드 분리 + 가독성 + 재사용성 향상
- @IsNotEmpty, @IsOptional 등으로 API의 입력 검증을 간단하고 안전하게 구현 가능
- 실수로 잘못된 데이터를 보내더라도 백엔드에서 방어 가능
학습 후기
NestJS에서 DTO와 class-validator를 함께 사용하는 방식은 단순히 코드 구조를 깔끔하게 만들 뿐 아니라, 실질적인 런타임 안정성까지 제공해준다는 점에서 매우 인상 깊었습니다. 이전까지는 타입스크립트의 타입만으로도 어느 정도 검증이 된다고 착각했지만, 실제로는 런타임에서는 타입이 무의미하다는 것을 직접 테스트를 통해 깨달을 수 있었습니다. 특히 필드를 비워서 요청해도 아무 문제없이 넘어가는 상황을 보며, class-validator의 필요성을 실감했습니다.
DTO를 통해 요청 body를 구조화해 전달받으니 컨트롤러 코드가 훨씬 간결해졌고, 인자 나열 없이도 .title, .genre처럼 접근이 가능해져 가독성이 좋아졌습니다. 또한 update 요청처럼 일부 필드만 받을 수 있는 상황에서 @IsOptional()과 @IsNotEmpty()를 조합해 조건부 검증을 구현하는 방식은 매우 직관적이면서도 유연했습니다. 이러한 구문이 단 몇 줄의 데코레이터로 구현된다는 것이 놀라웠습니다.
또한 class-transformer의 @Type()과 @Transform() 기능 덕분에 중첩 객체나 커스텀 값 변환도 간편하게 처리할 수 있어, 단순한 데이터 전달을 넘어서 실제로 필요한 형태로 데이터를 다듬어 전달할 수 있었습니다. validation과 transformation이 각각의 역할을 분담하며 유기적으로 동작하는 구조는 NestJS의 설계 철학이 잘 드러나는 부분이라고 생각했습니다.
결론적으로 DTO + class-validator 조합은 견고한 API를 구축하기 위한 핵심 기반이 되었으며, 앞으로의 모든 NestJS 프로젝트에서 필수적으로 사용해야 할 요소라고 느꼈습니다.
학습 인증샷




https://abit.ly/lisbva
Abit.ly 다운받기
abit.ly