Files
2026-06-11 18:19:26 +09:00

4.2 KiB

description
description
NestJS 백엔드 개발 규칙

이 파일은 .claude/commands/nestjs.md에 위치한다. 사용법: /nestjs [요청 내용]


아키텍처 원칙

관심사 분리 (Separation of Concerns)

Controller  →  HTTP 라우팅, 요청/응답 파싱만 담당
Service     →  모든 비즈니스 로직 처리
Repository  →  데이터 접근 계층 (TypeORM)
DTO         →  요청/응답 데이터 형식 정의 및 검증
  • Controller에 비즈니스 로직 작성 금지
  • new 키워드로 수동 객체 생성 지양 → 의존성 주입(DI) 활용

모듈 구조

src/
├── modules/
│   └── user/
│       ├── user.module.ts
│       ├── user.controller.ts
│       ├── user.service.ts
│       ├── user.repository.ts      ← 커스텀 Repository (선택)
│       └── dto/
│           ├── create-user.dto.ts
│           └── update-user.dto.ts
├── common/
│   ├── interceptors/               ← 응답 래핑, 에러 처리
│   ├── filters/                    ← 전역 Exception Filter
│   ├── guards/                     ← 인증/권한 Guard
│   ├── decorators/                 ← 커스텀 데코레이터
│   └── pipes/                      ← 전역 Validation Pipe
└── shared/
    └── utils/                      ← 순수 유틸 함수

DTO 작성 규칙

import { IsString, IsEmail, IsNotEmpty, MinLength } from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';

export class CreateUserDto {
  @ApiProperty({ description: '사용자 이메일', example: 'user@example.com' })
  @IsEmail({}, { message: '올바른 이메일 형식을 입력해 주세요.' })
  @IsNotEmpty()
  email: string;

  @ApiProperty({ description: '비밀번호 (최소 8자)', example: 'password123' })
  @IsString()
  @MinLength(8, { message: '비밀번호는 최소 8자 이상이어야 합니다.' })
  password: string;
}
  • 모든 DTO는 class-validator + class-transformer 사용
  • 에러 메시지는 한국어로 작성
  • @ApiProperty() 반드시 포함 (Swagger 명세용)

표준 응답 인터셉터

// common/interceptors/response.interceptor.ts
@Injectable()
export class ResponseInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    return next.handle().pipe(
      map((data) => ({
        success: true,
        data,
      })),
    );
  }
}
  • main.ts에서 전역 등록: app.useGlobalInterceptors(new ResponseInterceptor())

전역 Exception Filter

// common/filters/http-exception.filter.ts
@Catch()
export class AllExceptionsFilter implements ExceptionFilter {
  catch(exception: unknown, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();

    // 에러 코드 매핑 로직 포함
    // SYS_001 / AUTH_001 / VAL_001 등 CLAUDE.md 에러 맵 참조
  }
}

Swagger 필수 적용

// main.ts
const config = new DocumentBuilder()
  .setTitle('API 문서')
  .setDescription('프로젝트 API 명세서')
  .setVersion('1.0')
  .addBearerAuth()
  .build();

const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('api-docs', app, document);
  • 모든 Controller에 @ApiTags() 적용
  • 모든 엔드포인트에 @ApiOperation(), @ApiResponse() 작성
  • 모든 DTO에 @ApiProperty() 작성

인증 (JWT)

  • Access Token: 만료 시간 짧게 (15분 ~ 1시간)
  • Refresh Token: HttpOnly Secure 쿠키로 전달
  • @nestjs/jwt + @nestjs/passport 사용
  • Guard를 통한 라우트 보호

성능 & 최신 트렌드 추가 규칙

  • 캐싱: 자주 조회되는 데이터는 @nestjs/cache-manager (Redis) 활용 고려
  • Rate Limiting: @nestjs/throttler로 API 남용 방지
  • Pagination: 목록 API는 반드시 커서 기반 또는 오프셋 페이지네이션 적용
  • Logging: winston 또는 @nestjs/common Logger 사용, console.log 지양
  • Health Check: @nestjs/terminus/health 엔드포인트 구성 권장
  • Versioning: API 버전 관리 (/v1/, /v2/) 적용 고려