본문으로 건너뛰기
개발 머꼬
개발 노트NestJS
hohyeon.dev20

미들웨어를 providers에 넣었는데 아무 일도 일어나지 않은 이유

  • #Common Pitfall
  • #Engineering Note
  • #NestJS

문제 발생

요청 로깅 미들웨어를 만들어 모듈에 등록했는데 한 줄도 찍히지 않았습니다.

@Module({
  providers: [LoggerMiddleware],   // 아무 효과 없음
  controllers: [CatsController],
})
export class CatsModule {}

main.ts에서 app.use(new LoggerMiddleware())로 바꾸자 동작은 했지만, 이번에는 미들웨어 안에서 주입받으려던 서비스가 undefined였습니다.

원인 분석

등록 지점이 다릅니다. NestJS 문서가 그대로 적습니다 — @Module() 데코레이터에는 미들웨어를 위한 자리가 없습니다. 대신 모듈 클래스의 configure() 메서드로 설정합니다.

providers는 DI 컨테이너에 등록하는 목록일 뿐이라, 넣어두면 인스턴스는 만들어질 수 있어도 요청 파이프라인에 연결되지는 않습니다.

두 번째 시도의 문제도 문서에 있습니다 — 전역 미들웨어에서는 DI 컨테이너에 접근할 수 없습니다. app.use()를 쓸 때는 함수형 미들웨어를 사용하십시오. 직접 new로 만든 인스턴스에 Nest가 의존성을 넣어줄 방법이 없기 때문입니다(가드·필터에서와 같은 이유입니다).

해결 방안

  1. 모듈에서 configure()로 붙입니다.
@Module({ controllers: [CatsController], providers: [CatsService] })
export class CatsModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer.apply(LoggerMiddleware).forRoutes(CatsController);
  }
}

forRoutes()에는 경로 문자열, 컨트롤러 클래스, 또는 HTTP 메서드를 포함한 RouteInfo 객체를 넘길 수 있습니다.

  1. 제외할 경로는 exclude()로 명시합니다. 헬스체크나 정적 파일을 로깅에서 빼는 흔한 요구입니다.
consumer
  .apply(LoggerMiddleware)
  .exclude({ path: "health", method: RequestMethod.GET })
  .forRoutes(CatsController);
  1. 의존성이 없으면 함수형 미들웨어를 씁니다. 문서 권고 그대로 — 미들웨어에 의존성이 필요 없다면 더 단순한 함수형 미들웨어를 고려합니다. app.use()에 넘길 수 있는 것도 이쪽입니다.

  2. 미들웨어가 정말 맞는 도구인지 확인합니다. 인가는 가드, 응답 변형은 인터셉터, 입력 변환·검증은 파이프가 담당합니다. 미들웨어는 요청이 라우팅되기 전에 필요한 일(로깅, 요청 ID 부여, 원시 body 처리)에 씁니다.

  3. 여러 개를 붙이는 순서를 인지합니다. apply()에 나열한 순서대로 실행되고, configure() 안의 호출 순서도 그대로 반영됩니다. 요청 ID를 붙이는 미들웨어가 로거보다 먼저여야 로그에 ID가 남습니다.

공식 문서

마지막 수정

좋아요북마크

댓글0

아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.