반응형
Notice
Recent Posts
Recent Comments
Link
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
Tags
- 자바스크립트
- nest.js
- 주간회고
- 생각정리
- 회고
- 알고리즘
- MongoDB
- next.js
- react
- 리눅스
- typescript
- mysql
- WIL
- 트러블슈팅
- array
- 기록
- Java
- 피드백
- 생각로그
- til
- javascript
- Grafana
- 생각일기
- Git
- 네트워크
- js
- CS
- mongoose
- 코테
- mongo
Archives
- Today
- Total
코딩일상
[nest.js] NestJS 제공 라이브러리 및 데코레이터 완벽 정리 본문
반응형

1. @nestjs/common - 핵심 라이브러리
1.1 주요 카테고리별 분류표
| 카테고리 | 항목 | 용도 |
| Decorators - Class | @Module, @Controller, @Injectable, @Catch | 클래스 정의 |
| Decorators - Method | @Get, @Post, @Put, @Delete, @Patch, @Options, @Head, @All | HTTP 메서드 |
| Decorators - Parameter | @Body, @Query, @Param, @Headers, @Req, @Res, @Next, @Session, @Ip, @HostParam | 요청 데이터 추출 |
| Decorators - Metadata | @SetMetadata, @UseGuards, @UseInterceptors, @UsePipes, @UseFilters | 메타데이터/미들웨어 적용 |
| Interfaces | NestMiddleware, CanActivate, NestInterceptor, PipeTransform, ExceptionFilter | 구현 인터페이스 |
| Classes | HttpException, BadRequestException, UnauthorizedException, NotFoundException | 예외 클래스 |
| Utilities | Reflector, ModuleRef, HttpService | 유틸리티 |
| Enums | HttpStatus, RequestMethod | 상수 |
2. 전체 구성 요소 도표
@nestjs/common
├─ Decorators (데코레이터)
│ ├─ Class Decorators (클래스 레벨)
│ │ ├─ @Module() // 모듈 정의
│ │ ├─ @Controller() // 컨트롤러 정의
│ │ ├─ @Injectable() // 프로바이더 정의 (DI 가능)
│ │ ├─ @Catch() // 예외 필터 정의
│ │ └─ @Global() // 전역 모듈 정의
│ │
│ ├─ Method Decorators (메서드 레벨)
│ │ ├─ HTTP Methods
│ │ │ ├─ @Get() // GET 요청
│ │ │ ├─ @Post() // POST 요청
│ │ │ ├─ @Put() // PUT 요청
│ │ │ ├─ @Delete() // DELETE 요청
│ │ │ ├─ @Patch() // PATCH 요청
│ │ │ ├─ @Options() // OPTIONS 요청
│ │ │ ├─ @Head() // HEAD 요청
│ │ │ └─ @All() // 모든 HTTP 메서드
│ │ │
│ │ ├─ Middleware Application
│ │ │ ├─ @UseGuards() // Guard 적용
│ │ │ ├─ @UseInterceptors() // Interceptor 적용
│ │ │ ├─ @UsePipes() // Pipe 적용
│ │ │ └─ @UseFilters() // Exception Filter 적용
│ │ │
│ │ ├─ Metadata
│ │ │ ├─ @SetMetadata() // 커스텀 메타데이터
│ │ │ ├─ @HttpCode() // HTTP 상태 코드 설정
│ │ │ ├─ @Header() // 응답 헤더 설정
│ │ │ ├─ @Redirect() // 리다이렉트
│ │ │ └─ @Render() // 뷰 템플릿 렌더링
│ │ │
│ │ └─ Binding
│ │ ├─ @Bind() // 파라미터 바인딩
│ │ └─ @Dependencies() // 의존성 명시
│ │
│ └─ Parameter Decorators (파라미터 레벨)
│ ├─ Request Object
│ │ ├─ @Req() // Express Request 전체
│ │ ├─ @Request() // @Req()의 별칭
│ │ ├─ @Res() // Express Response 전체
│ │ ├─ @Response() // @Res()의 별칭
│ │ └─ @Next() // Express Next 함수
│ │
│ ├─ Request Parts
│ │ ├─ @Body() // Request Body
│ │ ├─ @Query() // Query String
│ │ ├─ @Param() // URL Parameters
│ │ ├─ @Headers() // Request Headers
│ │ ├─ @Session() // Session 객체
│ │ ├─ @Ip() // Client IP
│ │ └─ @HostParam() // Sub-domain 파라미터
│ │
│ └─ Custom
│ └─ @createParamDecorator() // 커스텀 파라미터 데코레이터
│
├─ Interfaces (인터페이스)
│ ├─ Lifecycle
│ │ ├─ NestMiddleware // Middleware 인터페이스
│ │ ├─ CanActivate // Guard 인터페이스
│ │ ├─ NestInterceptor // Interceptor 인터페이스
│ │ ├─ PipeTransform // Pipe 인터페이스
│ │ └─ ExceptionFilter // Exception Filter 인터페이스
│ │
│ ├─ Module
│ │ ├─ DynamicModule // 동적 모듈
│ │ ├─ ModuleMetadata // 모듈 메타데이터
│ │ └─ NestModule // 모듈 설정
│ │
│ └─ Context
│ ├─ ExecutionContext // 실행 컨텍스트
│ ├─ ArgumentsHost // 인자 호스트
│ ├─ HttpArgumentsHost // HTTP 컨텍스트
│ ├─ RpcArgumentsHost // RPC 컨텍스트
│ └─ WsArgumentsHost // WebSocket 컨텍스트
│
├─ Classes (클래스)
│ ├─ Exceptions (예외)
│ │ ├─ HttpException // 기본 HTTP 예외
│ │ ├─ BadRequestException // 400
│ │ ├─ UnauthorizedException // 401
│ │ ├─ NotFoundException // 404
│ │ ├─ ForbiddenException // 403
│ │ ├─ NotAcceptableException // 406
│ │ ├─ RequestTimeoutException // 408
│ │ ├─ ConflictException // 409
│ │ ├─ GoneException // 410
│ │ ├─ PayloadTooLargeException // 413
│ │ ├─ UnsupportedMediaTypeException// 415
│ │ ├─ UnprocessableEntityException // 422
│ │ ├─ InternalServerErrorException // 500
│ │ ├─ NotImplementedException // 501
│ │ ├─ BadGatewayException // 502
│ │ ├─ ServiceUnavailableException // 503
│ │ └─ GatewayTimeoutException // 504
│ │
│ ├─ Pipes (내장 Pipe)
│ │ ├─ ValidationPipe // DTO 검증
│ │ ├─ ParseIntPipe // 정수 변환
│ │ ├─ ParseFloatPipe // 실수 변환
│ │ ├─ ParseBoolPipe // 불린 변환
│ │ ├─ ParseArrayPipe // 배열 파싱
│ │ ├─ ParseUUIDPipe // UUID 검증
│ │ ├─ ParseEnumPipe // Enum 검증
│ │ ├─ DefaultValuePipe // 기본값 설정
│ │ └─ ParseFilePipe // 파일 검증
│ │
│ └─ Others
│ ├─ StreamableFile // 파일 스트리밍
│ └─ Logger // 로거
│
├─ Utilities (유틸리티)
│ ├─ Reflector // 메타데이터 읽기
│ ├─ ModuleRef // 모듈 참조
│ └─ ContextIdFactory // 컨텍스트 ID 생성
│
├─ Enums (열거형)
│ ├─ HttpStatus // HTTP 상태 코드
│ ├─ RequestMethod // HTTP 메서드
│ └─ Scope // Provider 스코프
│
└─ Types (타입)
├─ Type<T> // 클래스 타입
├─ Abstract<T> // 추상 클래스
├─ ArgumentMetadata // 파라미터 메타데이터
└─ CallHandler // Interceptor 핸들러
3.1 Class Decorators (클래스 데코레이터)
// ============================================
// @Module() - 모듈 정의
// ============================================
@Module({
imports: [DatabaseModule], // 다른 모듈 가져오기
controllers: [UsersController], // 컨트롤러 등록
providers: [UsersService], // 프로바이더 등록
exports: [UsersService], // 다른 모듈에 제공
})
export class UsersModule {}
// ============================================
// @Controller() - 컨트롤러 정의
// ============================================
@Controller('users') // 라우트 prefix
export class UsersController {}
@Controller({ host: 'admin.example.com' }) // 서브도메인 라우팅
export class AdminController {}
// ============================================
// @Injectable() - 프로바이더 정의 (DI 가능)
// ============================================
@Injectable()
export class UsersService {}
@Injectable({ scope: Scope.REQUEST }) // 요청마다 새 인스턴스
export class RequestScopedService {}
// ============================================
// @Catch() - 예외 필터 정의
// ============================================
@Catch(HttpException) // 특정 예외만
export class HttpExceptionFilter implements ExceptionFilter {}
@Catch() // 모든 예외
export class AllExceptionsFilter implements ExceptionFilter {}
// ============================================
// @Global() - 전역 모듈
// ============================================
@Global()
@Module({
providers: [ConfigService],
exports: [ConfigService],
})
export class ConfigModule {}
3.2 Method Decorators - HTTP Methods
// ============================================
// HTTP 메서드 데코레이터
// ============================================
@Controller('users')
export class UsersController {
@Get() // GET /users
findAll() {}
@Get(':id') // GET /users/:id
findOne(@Param('id') id: string) {}
@Post() // POST /users
create(@Body() dto: CreateUserDto) {}
@Put(':id') // PUT /users/:id
update(@Param('id') id: string, @Body() dto: UpdateUserDto) {}
@Patch(':id') // PATCH /users/:id
partialUpdate(@Param('id') id: string, @Body() dto: any) {}
@Delete(':id') // DELETE /users/:id
remove(@Param('id') id: string) {}
@Options() // OPTIONS /users
options() {}
@Head() // HEAD /users
head() {}
@All() // 모든 HTTP 메서드
handleAll() {}
}
3.3 Method Decorators - Middleware & Metadata
// ============================================
// Middleware Application
// ============================================
@Controller('users')
@UseGuards(AuthGuard) // 컨트롤러 레벨
export class UsersController {
@Get()
@UseGuards(RolesGuard) // 메서드 레벨
@UseInterceptors(LoggingInterceptor) // Interceptor
@UsePipes(ValidationPipe) // Pipe
@UseFilters(HttpExceptionFilter) // Exception Filter
findAll() {}
}
// ============================================
// Metadata
// ============================================
@Get()
@SetMetadata('roles', ['admin']) // 커스텀 메타데이터
@HttpCode(201) // HTTP 상태 코드
@Header('Cache-Control', 'none') // 응답 헤더
@Redirect('https://nestjs.com', 301) // 리다이렉트
@Render('users') // 뷰 템플릿
findAll() {}
3.4 Parameter Decorators (파라미터 데코레이터)
// ============================================
// Request Object 전체
// ============================================
@Get()
findAll(
@Req() request: Request, // Express Request 전체
@Res() response: Response, // Express Response 전체
@Next() next: NextFunction, // Express Next 함수
) {}
// ============================================
// Request Parts (요청 부분 추출)
// ============================================
@Post()
create(
@Body() createDto: CreateUserDto, // 전체 Body
@Body('name') name: string, // Body의 특정 필드
@Query() query: any, // 전체 Query String
@Query('page') page: number, // 특정 Query 파라미터
@Param() params: any, // 전체 URL 파라미터
@Param('id') id: string, // 특정 URL 파라미터
@Headers() headers: any, // 전체 헤더
@Headers('authorization') auth: string,// 특정 헤더
@Session() session: any, // Session 객체
@Ip() ip: string, // Client IP
@HostParam('account') account: string, // Sub-domain 파라미터
) {}
// ============================================
// 실전 예시
// ============================================
@Get(':vehicleId/history')
getChargingHistory(
@Param('vehicleId') vehicleId: string, // URL에서
@Query('startDate') startDate: string, // Query String에서
@Query('limit', ParseIntPipe) limit: number, // Query + Pipe
@Headers('authorization') token: string, // Header에서
@Req() request: Request, // Request 전체
) {
console.log(request.user); // Middleware에서 추가한 데이터
return this.service.getHistory(vehicleId, { startDate, limit });
}
3.5 Interfaces (구현해야 할 인터페이스들)
// ============================================
// NestMiddleware - Middleware 인터페이스
// ============================================
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
console.log('Request...');
next();
}
}
// ============================================
// CanActivate - Guard 인터페이스
// ============================================
@Injectable()
export class AuthGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean | Promise<boolean> {
const request = context.switchToHttp().getRequest();
return !!request.user;
}
}
// ============================================
// NestInterceptor - Interceptor 인터페이스
// ============================================
@Injectable()
export class LoggingInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
console.log('Before...');
return next.handle().pipe(
tap(() => console.log('After...'))
);
}
}
// ============================================
// PipeTransform - Pipe 인터페이스
// ============================================
@Injectable()
export class ParseIntPipe implements PipeTransform<string, number> {
transform(value: string, metadata: ArgumentMetadata): number {
const val = parseInt(value, 10);
if (isNaN(val)) {
throw new BadRequestException('Validation failed');
}
return val;
}
}
// ============================================
// ExceptionFilter - Exception Filter 인터페이스
// ============================================
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
catch(exception: HttpException, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
const status = exception.getStatus();
response.status(status).json({
statusCode: status,
message: exception.message,
});
}
}
3.6 Exception Classes (예외 클래스들)
// ============================================
// 4xx Client Errors
// ============================================
throw new BadRequestException('Invalid input'); // 400
throw new UnauthorizedException('Invalid credentials'); // 401
throw new ForbiddenException('Access denied'); // 403
throw new NotFoundException('User not found'); // 404
throw new NotAcceptableException('Not acceptable'); // 406
throw new RequestTimeoutException('Request timeout'); // 408
throw new ConflictException('Email already exists'); // 409
throw new GoneException('Resource gone'); // 410
throw new PayloadTooLargeException('File too large'); // 413
throw new UnsupportedMediaTypeException('Unsupported'); // 415
throw new UnprocessableEntityException('Invalid data'); // 422
// ============================================
// 5xx Server Errors
// ============================================
throw new InternalServerErrorException('Server error'); // 500
throw new NotImplementedException('Not implemented'); // 501
throw new BadGatewayException('Bad gateway'); // 502
throw new ServiceUnavailableException('Service down'); // 503
throw new GatewayTimeoutException('Gateway timeout'); // 504
// ============================================
// 커스텀 메시지 및 옵션
// ============================================
throw new BadRequestException({
statusCode: 400,
message: 'Validation failed',
error: 'Bad Request',
details: ['name is required', 'email is invalid'],
});
// ============================================
// 기본 HttpException 사용
// ============================================
throw new HttpException('Custom error', HttpStatus.I_AM_A_TEAPOT);
throw new HttpException({
status: HttpStatus.FORBIDDEN,
error: 'This is a custom message',
}, HttpStatus.FORBIDDEN);
3.7 Built-in Pipes (내장 파이프들)
// ============================================
// ValidationPipe - DTO 검증
// ============================================
@Post()
create(@Body(new ValidationPipe()) dto: CreateUserDto) {}
// 글로벌 적용
app.useGlobalPipes(new ValidationPipe({
whitelist: true, // DTO에 없는 속성 제거
forbidNonWhitelisted: true, // DTO에 없는 속성 있으면 에러
transform: true, // 자동 타입 변환
}));
// ============================================
// ParseIntPipe - 문자열 → 정수
// ============================================
@Get(':id')
findOne(@Param('id', ParseIntPipe) id: number) {}
// ============================================
// ParseFloatPipe - 문자열 → 실수
// ============================================
@Get()
findAll(@Query('price', ParseFloatPipe) price: number) {}
// ============================================
// ParseBoolPipe - 문자열 → 불린
// ============================================
@Get()
findAll(@Query('active', ParseBoolPipe) active: boolean) {}
// ============================================
// ParseArrayPipe - 문자열 → 배열
// ============================================
@Get()
findAll(@Query('ids', new ParseArrayPipe({ items: Number })) ids: number[]) {}
// ============================================
// ParseUUIDPipe - UUID 검증
// ============================================
@Get(':id')
findOne(@Param('id', ParseUUIDPipe) id: string) {}
// ============================================
// ParseEnumPipe - Enum 검증
// ============================================
enum OrderStatus {
PENDING = 'pending',
COMPLETED = 'completed',
}
@Get()
findAll(@Query('status', new ParseEnumPipe(OrderStatus)) status: OrderStatus) {}
// ============================================
// DefaultValuePipe - 기본값 설정
// ============================================
@Get()
findAll(@Query('page', new DefaultValuePipe(1), ParseIntPipe) page: number) {}
// ============================================
// ParseFilePipe - 파일 검증 (파일 업로드)
// ============================================
@Post('upload')
@UseInterceptors(FileInterceptor('file'))
uploadFile(
@UploadedFile(
new ParseFilePipe({
validators: [
new MaxFileSizeValidator({ maxSize: 1000000 }),
new FileTypeValidator({ fileType: 'image/jpeg' }),
],
}),
)
file: Express.Multer.File,
) {}
3.8 Utilities (유틸리티 클래스들)
// ============================================
// Reflector - 메타데이터 읽기
// ============================================
@Injectable()
export class RolesGuard implements CanActivate {
constructor(private reflector: Reflector) {}
canActivate(context: ExecutionContext): boolean {
const roles = this.reflector.get<string[]>('roles', context.getHandler());
const allRoles = this.reflector.getAllAndOverride('roles', [
context.getHandler(),
context.getClass(),
]);
return true;
}
}
// ============================================
// ModuleRef - 동적으로 프로바이더 가져오기
// ============================================
@Injectable()
export class CatsService {
constructor(private moduleRef: ModuleRef) {}
async onModuleInit() {
const service = await this.moduleRef.create(SomeService);
const provider = this.moduleRef.get(SomeProvider);
}
}
// ============================================
// Logger - 내장 로거
// ============================================
@Injectable()
export class AppService {
private readonly logger = new Logger(AppService.name);
someMethod() {
this.logger.log('This is a log message');
this.logger.error('This is an error message');
this.logger.warn('This is a warning message');
this.logger.debug('This is a debug message');
this.logger.verbose('This is a verbose message');
}
}
// ============================================
// StreamableFile - 파일 스트리밍
// ============================================
@Get('file')
getFile(): StreamableFile {
const file = createReadStream(join(process.cwd(), 'package.json'));
return new StreamableFile(file, {
type: 'application/json',
disposition: 'attachment; filename="package.json"',
});
}
3.9 Enums (열거형)
// ============================================
// HttpStatus - HTTP 상태 코드
// ============================================
import { HttpStatus } from '@nestjs/common';
throw new HttpException('Error', HttpStatus.BAD_REQUEST); // 400
throw new HttpException('Error', HttpStatus.UNAUTHORIZED); // 401
throw new HttpException('Error', HttpStatus.FORBIDDEN); // 403
throw new HttpException('Error', HttpStatus.NOT_FOUND); // 404
throw new HttpException('Error', HttpStatus.INTERNAL_SERVER_ERROR); // 500
// ============================================
// RequestMethod - HTTP 메서드
// ============================================
import { RequestMethod } from '@nestjs/common';
consumer
.apply(LoggerMiddleware)
.forRoutes({ path: 'cats', method: RequestMethod.GET });
// ============================================
// Scope - Provider 스코프
// ============================================
import { Scope } from '@nestjs/common';
@Injectable({ scope: Scope.DEFAULT }) // 싱글톤 (기본값)
export class DefaultService {}
@Injectable({ scope: Scope.REQUEST }) // 요청마다 새 인스턴스
export class RequestService {}
@Injectable({ scope: Scope.TRANSIENT }) // 주입될 때마다 새 인스턴스
export class TransientService {}반응형
'개발 공부 > nest.js' 카테고리의 다른 글
| [nest.js] nest.js 뿌수기 공식 docs 모조리 파헤치기[exception-filters] (1) | 2025.12.16 |
|---|---|
| [nest.js] Middleware vs Guards vs Interceptors (0) | 2025.12.14 |
| [nest.js] nest.js 뿌수기 공식 docs 모조리 파헤치기[Middleware] (0) | 2025.12.14 |
| [nest.js] nest.js 뿌수기 공식 docs 모조리 파헤치기[Modules] (0) | 2025.12.11 |
| [nest.js] nest.js 뿌수기 공식 docs 모조리 파헤치기[providers]Constructor-based Injection vs Property-based Injection (0) | 2025.12.11 |
Comments
