Nest.js

Nest.js - onModuleInit, onModuleDestroy 서버 실행과 종료시 실행되는 로직 구현

jaewoo 2024. 4. 17. 22:17

 

먼저 프로젝트 세팅으로 시작합니다.

nest new study-nest

 

다 만들어진 이후 해당 프로젝트 디렉토리에 접속하여 설정관련 클래스들을 넣을 모듈을 하나 생성합니다.

nest g module config

 

여기서 구현해볼 상황은 웹서버가 실행되고 난 뒤 계속 지속적인 작업이 필요하고, 서버가 종료될 시 끝내야 할 작업이 필요할 때 상요하면 좋을 것이 OnModuleInit과 OnModuleDestroy 입니다. 두 인터페이스는 Nest.js 에서 지원하는 라이프 사이클 인터페이스 입니다.

 

OnModuleInit

  •  이 인터페이스는 해당 모듈이 초기화될때 실행되는 메서드 onModuleInit 을 구현해야합니다. 이 메서드는 Nest.js가 모듈의 종속성을 모두 해결한 후, 모듈 자체가 초기화될 때 호출됩니다. 따라서 이 시점에서 모든 서비스, 컨트롤러 등이 모두 준비된 상태이며, 초기에 필요한 설정을 추가적으로 할 수 있습니다.
  • 이 메서드는 비동기 로직을 포함할 수 있으며 Nest.js 는 onModuleInit에서 반환되는 프로미스가 완료될때까지 기다립니다. 이를 통해 모듈 초기화 과정 중 필요한 비동기 작업을 보장할 수 있습니다.

OnModuleDestroy

  • OnModuleDestroy 인터페이스는 모듈의 생명주기가 끝날 때, 실행되는 메서드인 onModuleDestroy 를 구현해야합니다. 이 메서드는 애플리케이션이 종료되기 직전에 호출됩니다.
  • onModuleDestroy에서도 비동기 로직을 수행할 수 있으나, Nest.js 가 종료 프로세스 중 비동기 작업의 완료를 보장하지 않습니다.

 

구현코드

config.module.ts 와 같은 경로에 config.service.ts 파일을 생성합니다.

import { Injectable, OnModuleDestroy, OnModuleInit } from '@nestjs/common';

@Injectable()
export class ConfigService implements OnModuleInit, OnModuleDestroy {

	onModuleInit() {
		console.log('모듈 초기화');
    }

	onModuleDestroy() {
		console.log('모듈 종료');	
	}
}

 

그러고 서버를 실행시켜 봅니다.

 

로그를 보면 초기화가 잘 되는 것을 볼 수 있습니다. 하지만 여기서 모듈 초기화는 되었지만 control + c 또는 pm2 일 경우 pm2 stop 하면 모듈 종료는 로그는 보이지 않습니다.

 

Node.js 프로세스는 기본적으로 SIGINT 나 SIGTERM 같은 종료 신호를 받았을 때 바로 프로세스가 종료됩니다. 그렇기 때문에 해당 이벤트로 프로세스에서 받아서 처리하는 로직이 필요합니다.

이렇게 하면 Nest.js 에서 라이프 사이클 훅을 실행하거나 필요한 종료로직을 수행할 수 있습니다. 정상적으로 종료되기 전에 정리 작업을 수행할 수 있습니다.

 

아래코드를 main.ts 에 넣어주면 됩니다. app.listen(3000) 아래 적어주시면 됩니다.

  

process.on('SIGTERM', async () => {
    console.log('SIGTERM received 앱 종료시작');
    await app.close();
});

process.on('SIGINT', async () => {
	console.log('SIGINT received 앱 종료시작');
	await app.close();
});

 

Nest.js 에서 app.close() 메서드를 호출하여 모든 종료 작업을 진행합니다. 이 메서드는 내부적으로 Nest.js 애플리케이션에 등록된 모든 onModuleDestroy 훅을 실행하고, HTTP 서버와 같은 리소스를 정삭정으로 종료합니다.

 

이 과정을 통해 비동기 작업이 진행중일 경우에도 안전하게 작업을 마무리하고, 프로세스를 종료할 수 있습니다.

(메모리 누수나 다른 종류의 리소스 누락 문제를 방지할 수 있습니다)

 

위 코드를 main.ts 반영 한뒤 다시 재실행해보면

 

 

SIGINT 를 받아 처리가 정상적으로 되는것을 확인할 수 있습니다.