nestjs) 미들웨어,가드,필터
항상 nestjs를 사용하면서 이 세가지에 대해 개념이 헷갈리는 경우가 많아서 정리하고자 합니다.
1. Middleware (미들웨어)
Middleware란?
Middleware는 컨트롤러에 도달하기 전에 요청을 가로채서 전처리하는 역할을 합니다.
Express의 미들웨어와 유사하게, 로깅, 인증, 요청 변환, CORS 처리 등의 용도로 사용됩니다.
✅ Middleware 특징
- 요청(Request) → 미들웨어 실행 → 컨트롤러 실행
- next()를 호출해야 다음 미들웨어 또는 컨트롤러로 요청 전달 가능
- 전역(Global), 모듈(Module), 특정 라우트(Route) 단위로 적용 가능
Middleware 예제: 역할(Role) 기반 접근 제한
사용자의 역할(Role)에 따라 특정 API 접근을 제한하는 미들웨어를 만들어보겠습니다.
1: RoleMiddleware 생성
middlewares/role.middleware.ts
import { Injectable, NestMiddleware, ForbiddenException } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
@Injectable()
export class RoleMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
const userRole = req.headers['x-user-role']; // ✅ 헤더에서 역할(Role) 가져오기
if (!userRole) {
throw new ForbiddenException('역할 정보가 필요합니다.');
}
if (req.path.startsWith('/admin') && userRole !== 'admin') {
throw new ForbiddenException('관리자만 접근할 수 있습니다.');
}
next(); // ✅ 유효한 역할이면 컨트롤러로 요청 전달
}
}
2: Middleware를 애플리케이션에 적용
app.module.ts
import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
import { RoleMiddleware } from './middlewares/role.middleware';
@Module({})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(RoleMiddleware).forRoutes('*'); // ✅ 모든 요청에 적용
}
}
이제 /admin 경로는 admin 역할을 가진 사용자만 접근 가능합니다.
2. Filter (필터)
Filter란?
NestJS에서 Filter는 컨트롤러 또는 서비스에서 발생한 예외를 가로채어 처리하는 기능을 합니다.
즉, 발생한 예외를 커스텀 메시지로 변환하여 클라이언트에게 반환할 수 있습니다.
Filter 특징
- 컨트롤러에서 예외 발생 시 실행됨
- HTTP 응답 형식을 통일하여 유지보수를 쉽게 할 수 있음
- @Catch() 데코레이터를 사용하여 특정 예외 유형을 처리 가능
Filter 예제: 예외 응답 형식 커스텀
1: HttpExceptionFilter 생성
filters/http-exception.filter.ts
import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common';
import { Request, Response } from 'express';
@Catch(HttpException) // ✅ HttpException만 잡음
export class HttpExceptionFilter implements ExceptionFilter {
catch(exception: HttpException, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
const request = ctx.getRequest<Request>();
const status = exception.getStatus();
const message = exception.message;
response.status(status).json({
success: false,
code: status,
path: request.url,
timestamp: new Date().toISOString(),
message: message,
});
}
}
2: Filter를 글로벌하게 적용
main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { HttpExceptionFilter } from './filters/http-exception.filter';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalFilters(new HttpExceptionFilter()); // ✅ 글로벌 예외 필터 적용
await app.listen(3000);
}
bootstrap();
이제 예외가 발생하면 일관된 JSON 응답을 반환합니다.
3. Guard (가드)
Guard란?
Guard는 미들웨어와 다르게 컨트롤러 실행 직전에 요청을 차단하거나 허용하는 기능을 합니다.
인증 및 권한(Role) 검증, API 접근 제한 등에 주로 사용됩니다.
Guard 특징
- 컨트롤러 실행 직전에 실행됨
- return true면 요청 허용, false 또는 예외 발생 시 요청 차단
- @UseGuards() 데코레이터를 사용하여 특정 컨트롤러 또는 특정 핸들러에 적용 가능
Guard 예제: 역할(Role) 기반 인증
1: RoleGuard 생성
guards/role.guard.ts
import { CanActivate, ExecutionContext, Injectable, ForbiddenException } from '@nestjs/common';
import { Request } from 'express';
@Injectable()
export class RoleGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean {
const request: Request = context.switchToHttp().getRequest();
const userRole = request.headers['x-user-role']; // ✅ 역할(Role) 정보 가져오기
if (!userRole) {
throw new ForbiddenException('역할 정보가 필요합니다.');
}
if (request.path.startsWith('/admin') && userRole !== 'admin') {
throw new ForbiddenException('관리자만 접근할 수 있습니다.');
}
return true; // ✅ 요청을 허용
}
}
2: Guard를 특정 컨트롤러에 적용
controllers/admin.controller.ts
import { Controller, Get, UseGuards } from '@nestjs/common';
import { RoleGuard } from '../guards/role.guard';
@Controller('admin')
@UseGuards(RoleGuard) // ✅ 이 컨트롤러에만 `RoleGuard` 적용
export class AdminController {
@Get('dashboard')
getAdminDashboard() {
return { success: true, data: 'Admin Dashboard' };
}
}
✅ 이제 /admin 경로는 admin 역할을 가진 사용자만 접근 가능합니다.
미들웨어 vs 필터 vs 가드 차이점 정리
비교 항목 Middleware Filter Guard
역할 | 요청을 가로채서 전처리 | 발생한 예외를 후처리 | 컨트롤러 실행 직전에 요청 차단 |
실행 시점 | 컨트롤러 또는 가드 실행 전에 동작 | 컨트롤러에서 예외 발생 후 실행 | 컨트롤러 실행 직전에 실행 |
주요 목적 | 로깅, 인증, 요청 변환, CORS 처리 | 예외 메시지 변환, 오류 응답 처리 | 인증, 권한 검사, 역할(Role) 기반 접근 제어 |
적용 대상 | 특정 모듈, 특정 경로, 글로벌 적용 가능 | 특정 예외, 컨트롤러, 글로벌 적용 가능 | 특정 컨트롤러 또는 특정 핸들러에 적용 가능 |
✅ Middleware → 모든 요청을 가로채서 전처리 (로그, 인증, 요청 변환)
✅ Filter → 컨트롤러에서 발생한 예외를 가로채어 처리 (커스텀 오류 응답)
✅ Guard → 컨트롤러 실행 직전에 요청을 차단하거나 허용 (인증, 권한 검증)