미들웨어를 providers에 넣었는데 아무 일도 일어나지 않은 이유
문제 발생
요청 로깅 미들웨어를 만들어 모듈에 등록했는데 한 줄도 찍히지 않았습니다.
@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가 의존성을 넣어줄 방법이 없기 때문입니다(가드·필터에서와 같은 이유입니다).
해결 방안
- 모듈에서
configure()로 붙입니다.
@Module({ controllers: [CatsController], providers: [CatsService] })
export class CatsModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(LoggerMiddleware).forRoutes(CatsController);
}
}forRoutes()에는 경로 문자열, 컨트롤러 클래스, 또는 HTTP 메서드를 포함한 RouteInfo 객체를 넘길 수 있습니다.
- 제외할 경로는
exclude()로 명시합니다. 헬스체크나 정적 파일을 로깅에서 빼는 흔한 요구입니다.
consumer
.apply(LoggerMiddleware)
.exclude({ path: "health", method: RequestMethod.GET })
.forRoutes(CatsController);-
의존성이 없으면 함수형 미들웨어를 씁니다. 문서 권고 그대로 — 미들웨어에 의존성이 필요 없다면 더 단순한 함수형 미들웨어를 고려합니다.
app.use()에 넘길 수 있는 것도 이쪽입니다. -
미들웨어가 정말 맞는 도구인지 확인합니다. 인가는 가드, 응답 변형은 인터셉터, 입력 변환·검증은 파이프가 담당합니다. 미들웨어는 요청이 라우팅되기 전에 필요한 일(로깅, 요청 ID 부여, 원시 body 처리)에 씁니다.
-
여러 개를 붙이는 순서를 인지합니다.
apply()에 나열한 순서대로 실행되고,configure()안의 호출 순서도 그대로 반영됩니다. 요청 ID를 붙이는 미들웨어가 로거보다 먼저여야 로그에 ID가 남습니다.
댓글0
댓글을 남기려면 로그인이 필요해요. 로그인
아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.