Node

Nestjs Request Lifecycle

5linesys 2024. 11. 24. 18:41

Nestjs Request Lifecycle

1. Middleware (미들웨어)

  • 위치: 요청 처리의 가장 첫 단계
  • 역할: HTTP 요청/응답을 가로채어 수정하거나 처리 여부를 결정
  • 주요 기능:
    • 요청 로깅
    • 헤더 조작
    • 요청 본문 파싱
    • CORS 설정
// Interceptor 구현
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: NextFunction) {
    console.log(`Request ${req.method} ${req.url}`);
    next();
  }
}

// Interceptor 적용
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { LoggerMiddleware } from './common/middleware/logger.middleware';
import { CatsModule } from './cats/cats.module';

@Module({
  imports: [CatsModule],
})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(LoggerMiddleware)
      .forRoutes('cats');
  }
}

2. Guards(가드)

  • 위치: 미들웨어 다음, 라우트 핸들러 이전
  • 역할: 인증/인가 등 요청의 실행 허가 여부를 결정
  • 주요 기능:
    • 인증 상태 확인
    • 권한 체크
    • 접근 제어
    • IP 기반 필터링
@Injectable()
export class AuthGuard implements CanActivate {
  canActivate(context: ExecutionContext): boolean {
    const request = context.switchToHttp().getRequest();
    return !!request.headers.authorization;
  }
}

3. Interceptors (인터셉터)

  • 위치: 가드 다음, 라우트 핸들러 전후
  • 역할: 요청/응답 변환, 추가 로직 실행
  • 주요 기능:
    • 응답 데이터 변환
    • 성능 모니터링
    • 캐시 처리
    • 로깅
@Injectable()
export class TimingInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const start = Date.now();
    return next.handle().pipe(
      tap(() => console.log(`Request took ${Date.now() - start}ms`))
    );
  }
}

4. Pipes (파이프)

  • 위치: 인터셉터와 라우트 핸들러 사이
  • 역할: 데이터 변환 및 유효성 검사
  • 주요 기능:
    • 입력 데이터 유효성 검사
    • 데이터 타입 변환
    • DTO 검증
    • 기본값 설정
@Post()
createUser(@Body(new ValidationPipe()) createUserDto: CreateUserDto) {
  return this.usersService.create(createUserDto);
}

5. Controller (컨트롤러)

  • 위치: 파이프 다음, 비즈니스 로직 이전
  • 역할: 요청 라우팅 및 요청/응답 처리
  • 주요 기능:
    • 요청 경로 매핑
    • 요청 파라미터 추출
    • 서비스 계층 호출
@Controller('users')
export class UsersController {
  @Get(':id')
  findOne(@Param('id') id: string) {
    return this.usersService.findOne(id);
  }
}

6. Service (서비스)

  • 위치: 컨트롤러 다음
  • 역할: 비즈니스 로직 실행
  • 주요 기능:
    • 데이터 처리
    • 외부 서비스 통신
    • 데이터베이스 작업
@Injectable()
export class UsersService {
  async findOne(id: string): Promise<User> {
    return this.usersRepository.findOne(id);
  }
}

7. Exception Filters (예외 필터)

  • 위치: 전체 요청/응답 사이클에서 예외 발생 시
  • 역할: 예외 처리 및 에러 응답 생성
  • 주요 기능:
    • 에러 로깅
    • 사용자 정의 에러 응답
    • 예외 변환
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse();
    const status = exception.getStatus();

    response.status(status).json({
      statusCode: status,
      timestamp: new Date().toISOString(),
      message: exception.message,
    });
  }
}

 

통합 사용 예시

@UseGuards(AuthGuard)
@UseInterceptors(LoggingInterceptor)
@UseFilters(HttpExceptionFilter)
@Controller('users')
export class UsersController {
  @Post()
  @UsePipes(ValidationPipe)
  create(@Body() createUserDto: CreateUserDto) {
    return this.usersService.create(createUserDto);
  }
}