프로젝트에서 어떤 요청들이 오고 가는지를 확인하고, 에러가 났을때 확인하기 위해서 로그를 남기기로 했다. 명확하게 어떤 상황에 로그를 남기면 좋을지는 잘 모르겠어서, 우선은 컨트롤러로 오는 요청이 들어올 때, 그 요청이 끝날때, 그리고 에러가 발생했을시 총 3개로 나누어서 로그를 찍기로 했다.

요청에 대한것은 인터셉터를 활용하여 로그를 찍도록하였다. NestJS에서 인터셉터는 request와 response를 수행할시에 중간에서 값을 가져와서 추가적인 로직을 수행할 수 있도록 도와준다.

logging-interceptor.ts

import { CallHandler, ExecutionContext, Injectable, Logger, NestInterceptor } from '@nestjs/common';
import { catchError, from, Observable, tap } from 'rxjs';
import { EMessage } from '../response/ecustom-code.jenum';
import axios from 'axios';

@Injectable()
export class LoggingInterceptor implements NestInterceptor {
  private readonly logger = new Logger(LoggingInterceptor.name);

  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const req = context.switchToHttp().getRequest();
    const { method, url, body, query } = req;
    const errorWebHook: string = process.env.ERR_WEB_HOOK;
    this.logger.log(`[IN] ${method} ${url} ${JSON.stringify(body)} ${JSON.stringify(query)}`);

    return next.handle().pipe(
      tap(), // 응답이 정상적으로 끝나면 tap 안에서 수행되지만, exception 을 날리므로 error 로 처리해야함.
      catchError((exception) => from(this.handleException(exception, method, url, errorWebHook))),
    );
  }

  async handleException(exception, method, url, errorWebHook) {
    if (exception.message !== EMessage.SUCCESS) {
      this.logger.error(`[OUT] ${method} ${url}: ${exception.message}`);
      await axios.post(errorWebHook, {
        embeds: [
          {
            title: `[${method}] ${url}`,
            description: exception.message,
            color: 16711680,
          },
        ],
      });
    } else {
      this.logger.log(`[OUT] ${method} ${url}: ${exception.message}`);
    }
    throw exception;
  }
}

aap.module.ts

providers: [
    AppService,
    {
      provide: APP_INTERCEPTOR,
      useClass: LoggingInterceptor,
    },
  ],

Discord Webhook