최근에 Nest.js 라이프사이클에 대한 질문을 받은 적이 있었다. 런타임 때나 통신이 일어날 때 타이밍에 맞는 라이프사이클이 있다는 것은 알고 있었지만 제대로 정리해 본 적이 없어 정리된 대답을 하지 못했다. 그래서 개념을 다시 정리하려고 한다.
1. Lifecycle
먼저 Nest.js documentation 을 보면 아래와 같은 그림이 나와있다.
제일 위부터 보면 Bootstrapping starts에서 런타임이 시작되고 아래 여러 가지 이벤트를 지나서 Application is running에 도달해서 서비스가 돌아가기 시작한다.
onModuleDestroy부터는 서비스를 종료한다는 신호를 보냈을 때 일어나는 이벤트 들이다.
1-1. Lifecycle Events
위 그림에서 검은색 바로 되어있는 이벤트들은 Nest.js에서 제공하는 내장 메서드이다. 하나하나 살펴보면
- onModuleInit() : 호스트 모듈의 종속성이 해결되면 호출되는 메서드
- onApplicationBootstrap() : 모든 모듈이 초기화된 후 연결을 수신 대기하기 전에 호출되는 메서드
- onModuleDestroy() : 종료 신호가 수신된 후 호출되는 메서드
- beforeApplicationShutdown() : 모든 onModuleDestroy() 가 완료된 후 호출되는 메서드
- on ApplicationShutdown() : 연결 종료 후 호출되는 메서드
1-2. 사용 예시
import { Injectable, OnApplicationBootstrap } from '@nestjs/common';
@Injectable()
export class testService implements OnApplicationBootstrap {
constructor(1) {}
onApplicationBootstrap() {
console.log('onApplicationBootstrap 입니다');
}
}
onApplicationBootstrap 입니다
[Nest] 76463 - 06/20/2023, 9:02:12 AM LOG [NestFactory] Starting Nest application...
[Nest] 76463 - 06/20/2023, 9:02:12 AM LOG [InstanceLoader] TypeOrmModule dependencies initialized +0ms
[Nest] 76463 - 06/20/2023, 9:02:12 AM LOG [InstanceLoader] ConfigHostModule dependencies initialized +0ms
[Nest] 76463 - 06/20/2023, 9:02:12 AM LOG [InstanceLoader] AppModule dependencies initialized +0ms
[Nest] 76463 - 06/20/2023, 9:02:12 AM LOG [InstanceLoader] ConfigModule dependencies initialized +0ms
먼저 class에 implements로 원하는 이벤트를 넣어주고 추상화 계층이름과 같은 이름으로 메서드를 만들어준다. 이후 실행해 보면 아랫부분과 같이 연결을 수신하기 전에 onApplicationBootstrap 메서드가 실행되는 것을 볼 수 있다.
만약 서비스 종료할 때 실행되는 이벤트를 구현하려면 main.ts에 enableShutdownHooks 메서드를 추가해주고 위와 동일한 방식으로 구현하면 된다.
// main.ts
import { NestFactory } from '@nestjs/core';
import { HttpExceptionFilter } from 'src/httpException.filter';
import { AppModule } from './app.module';
import { NestExpressApplication } from '@nestjs/platform-express';
async function bootstrap() {
const app = await NestFactory.create<NestExpressApplication>(AppModule, {
bufferLogs: true,
});
app.enableShutdownHooks();
app.useGlobalFilters(new HttpExceptionFilter());
await app.listen(3000);
}
bootstrap();
2. Request lifecycle
Nest.js 의 Request lifecycle (요청 수명 주기) 는 결국 미들웨어에 대한 내용이다. 미들웨어는 특정 순서대로 실행되는데 먼저 전역적으로 바인딩된 미들웨어가 먼저 실행된다. (Express에서 사용하듯이 app.use 방식으로 사용되는 미들웨어)
2-1. Nest.js 내장 미들웨어
Nest.js에는 guard, interceptor, pipe, filter 4개의 내장 미들웨어가 있다. 해당 미들웨어들은 요청 주기 내에 각각의 순번이 있다.
간단히 말하면 Request -> Middleware -> guard -> interceptor -> pipe -> controller, service -> interceptor -> Response 의 순서이고, Filter의 경우 요청이 들어오고나서 모든 경로에 바인딩되어 사용되고 마지막에 전역으로 사용하게 된다.
자세히 살펴보면 아래 그림과 같다.
여기에 중간중간 전역, 모듈에 의존적인 미들웨어들을 껴넣으면서 더 복잡한 사이클을 갖게 할 수 있지만 큰 틀에서 보면 이런 순서다. 모든 미들웨어들은 전역으로 바인딩된 것을 먼저 확인하는데 Filter의 경우 전역을 먼저 확인하지 않는다. (모든 경로에 바인딩필터로 먼저 시작함)
'NestJS' 카테고리의 다른 글
모듈 간의 순환참조 (1) | 2023.06.27 |
---|---|
Express에서 DI 프레임워크 만들어보기 (0) | 2023.05.04 |
Nest.js에서 모듈간의 의존성 관리하기 (0) | 2023.04.19 |
AuthGuard 예외처리 조건 만들기 (0) | 2023.04.19 |
Nest.js 에서 역직렬화 하기 (0) | 2023.03.14 |