NestJS Logger Middleware

Seunghwa's Devlog·2023년 2월 14일
0

NestJs

목록 보기
10/15
post-thumbnail

Express에서 HTTP 요청에 대한 Log를 남겨주는 미들웨어인 Morgan과 같은 미들웨어를 NestJS에서도 구현해보자

Middleware
미들웨어는 클라이언트로부터 들어온 요청을 각 컨트롤러의 요청 핸들러가 처리하기 이전에 코드를 실행할 수 있는 기능입니다. 미들웨어 함수는 애플리케이션의 요청-응답 주기에서 요청(request) 및 응답(response) 객체에 접근할 수 있으며 next()라는 미들웨어 함수를 사용할 수 있습니다

// middlewares/logger.middleware.ts

import { Injectable, Logger, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';

@Injectable()
export class LoggerMiddleware implements NestMiddleware {
  private logger = new Logger('HTTP'); // HTTP(context)의 역할 -> HTTP 관련된 요청에서만 logger가 실행 됨 , express의 debug 라이브러리와 같은 역할

  use(request: Request, response: Response, next: NextFunction): void {
    const { ip, method, originalUrl } = request;
    const userAgent = request.get('user-agent') || ''; // header에서 가져옴

    // 응답이 끝났을 때
    response.on('finish', () => {
      const { statusCode } = response;
      const contentLength = response.get('content-length');
      this.logger.log(
        `${method} ${originalUrl} ${statusCode} ${contentLength} - ${userAgent} ${ip}`,
      );
    });

    next();
  }
}

// middleware 자체는 router 즉, controller보다 먼저 실행됨
// 실행순서
// line 9-10 -> request에 대한 기록을 하고 나서
// line 21 -> router로 이동
// line 13-19 -> router가 finish된 후 실행

구현한 미들웨어를 적용해보자

// app.module.ts
import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { LoggerMiddleware } from './middlewares/logger.middleware';

@Module({
  imports: [
    ConfigModule.forRoot({ isGlobal: true }),
  ],
  controllers: [AppController],
  providers: [AppService, ConfigService],
  // provider의 원형
  // -> providers: [
  //   {
  //     provide: AppService,
  //     useClass: AppService
  //   }
  // ]
})

//implement -> 사용시 아래 코드를 반드시 구현해야하는 강제성이 생김 / 없어도 오류는 나지 않지만, 만약 오타를 작성했을 때 implements를 사용하지 않는다면 에러를 확인하기 어렵지만 implements를 사용하여 강제성이 생김으로써 좀 더 에러를 찾는데 수월함 ( 타입 검사도 용이 )
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer): any {
    consumer.apply(LoggerMiddleware).forRoutes('*');
  }
}

@Module 데코레이터에는 미들웨어를 넣을 부분이 없으므로 대신 미들웨어를 Module 클래스의 configure 메서드를 만들어서 세팅할 수 있다. 미들웨어를 사용하는 모듈들은 NestModule 인터페이스를 implements 해야 한다.

forRoutes(컨트롤러)나 forRoutes(주소)로 특정 주소에만 미들웨어 적용 가능하다. *는 전체에 적용하겠다는 것을 의미한다.

정상적으로 작동하는지 확인해보자

해당 요청을 날렸을 때

위의 middleware에서 구현한 것처럼
${method} ${originalUrl} ${statusCode} ${contentLength} - ${userAgent} ${ip} 가 정상적으로 Log에 찍히는 것을 확인할 수 있다.

참고링크: https://docs.nestjs.com/middleware#middleware

profile
에러와 부딪히고 새로운 것을 배우며 성장해가는 과정을 기록합니다!

0개의 댓글