티스토리 뷰

WEB2.0/프로그래밍

nestjs 12 릴리즈

나를찾는아이 2026. 9. 9. 12:50
728x90
반응형

 

NestJS 12가 조용히(?) 2026년 8월 27일 공개되었습니다

 

한줄로 요약하자면 nestjs의 핵심 패키지들이 ESM으로 전환되었고, Zod, Valibot, ArkType 같은 스키마 라이브러리를 프레임워크 차원에서 지원합니다

 

ESM 전환, 하지만 강제는 아닙니다

Nest의 핵심 패키지들이 ESM으로 배포됩니다 하지만 대부분의 CommonJS 앱은 코드 수정 없이도 동작합니다

 

nest new는 이제 프로젝트를 CommonJS로 만들지 ESM으로 만들지 물어봅니다

 

새 프로젝트를 시작한다면 ESM을 고르는 것이 자연스러운 선택이 되었습니다

 

nestjs esm을 사용하는 팀이라면 앞으로 esm의 활용이 더욱 높아질것 같습니다

 

 

Standard Schema: Zod를 DTO 자리에

NestJS는 오랫동안 class-validator + class-transformer 조합의 클래스 기반 DTO가 표준이었습니다

 

v12는 여기에 Standard Schema 호환 라이브러리(Zod, Valibot, ArkType 등)를 같은 레벨로 올렸습니다

검증단계

@Body(), @Query(), @Param(), @RawBody() 데코레이터에 schema 옵션이 추가되었습니다

@Post()
create(@Body({ schema: createUserSchema }) body: CreateUserDto) {
  return this.usersService.create(body);
}

@Get(':id')
findOne(@Param('id', { schema: z.coerce.number().int().positive() }) id: number) {
  return this.usersService.findOne(id);
}

데코레이터는 메타데이터만 붙이고, 실제 검증은 새 파이프가 담당합니다

app.useGlobalPipes(new StandardSchemaValidationPipe());

같은 스키마가 OpenAPI 문서 생성에도 그대로 쓰입니다

 

스키마 하나로 타입, 검증, 문서를 모두 얻었습니다

 

기존 class-validator 워크플로는 계속 지원되며, 제거 계획도 없다고 하네요

 

직렬화

응답 쪽에도 대응하는 인터셉터가 생겼습니다. ClassSerializerInterceptor의 Standard Schema 버전이라고 보면 됩니다

@UseInterceptors(StandardSchemaSerializerInterceptor)
@SerializeOptions({ schema: userResponseSchema })
@Get(':id')
findOne(@Param('id') id: string) {
  return this.usersService.findOne(id);
}

Config 모듈

@nestjs/config의 validationSchema도 Joi 전용에서 Standard Schema로 바뀌었습니다

 

이제 환경변수 검증을 Zod로 쓸 수 있습니다

ConfigModule.forRoot({
  validationSchema: z.object({
    NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),
    PORT: z.coerce.number().default(3000),
  }),
});

 

@nestjs/observe

공식 NestJS Observe SDK가 등장했습니다

export const { ObserveModule, ObserveInstrument } = createObserveModule();

const app = await NestFactory.create(AppModule, {
  instrument: ObserveInstrument,
});

 

HTTP, GraphQL, gRPC, 마이크로서비스 트랜스포트, 큐 컨슈머, 크론 실행까지 자동 계측합니다

 

 

작지만 반가운 코어 개선

라우트 충돌 진단

라우트는 선언 순서대로 등록되기 때문에 @Get(':id')가 뒤에 선언된 @Get('me')를 조용히 가리는 사고가 흔했습니다

 

두 가지 옵트인 옵션으로 이를 잡아낼 수 있습니다.

 

const app = await NestFactory.create(AppModule, {
  routeConflictPolicy: { duplicate: 'error', shadow: 'warn' },
  routeResolutionStrategy: 'specificity',
});

기본값은 기존 동작이라 설정하지 않으면 아무것도 바뀌지 않습니다

 

에러 코드

내장 exception 에 대해서 기존에는 메시지만 넣을수 있었습니다

 

그래서 기존 exception을 그대로 사용하는 경우라면

 

클라이언트에서는 서버의 에러 메시지 문자열을 파싱하는 방식으로 이후 로직의 분기를 하여야했는데요

 

errorCode라는 공식 옵션이 생겼습니다

 

이를 이용하여 로직의 분기를 수행할 수 있습니다

 

throw new BadRequestException('Password is too weak', { errorCode: 'WEAK_PASSWORD' });

 

 

 

대대적인 홍보(?)는 없었지만 esm으로 전환하는 매우 의미있는 nestjs 12릴리즈 소식을 전합니다

728x90
반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/10   »
일 월 화 수 목 금 토
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함