애플리케이션을 안전하게 종료하는 프로세스
반대되는 개념으로는 Hard Shutdown: 종료 시그널과 동시에 모든 작업 중단
Graceful Shtudown은 하고 있던 작업을 적절히 마무리한 뒤 종료되는 것
대부분 웹 프레임워크에서 시그널 처리로 graceful shutdown 구현
코어 덤프: 현재의 메모리 상태를 파일로 저장
SIGINT가 일반적으로 프로그램 안전하게 중지시키는 데 사용되며, 사용자가 의도적으로 프로그램 실행 중단을 원할 때 발생
SIGQUIT는 디버깅 목적으로 사용.
process.on('SIGTERM', () => {
console.log('SIGTERM received. Shutting down gracefully.');
server.close(() => {
console.log('HTTP server closed.');
// 데이터베이스 연결 해제, 필요한 정리 수행
database.close(() => {
console.log('Database connection closed.');
process.exit(0);
});
});
});
process.on('SIGINT', () => {
console.log('SIGINT received. Shutting down gracefully.');
// 비슷한 종료 절차 수행
process.exit(0);
});
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { DataSource } from 'typeorm';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const dataSource = new DataSource(/* configuration */);
const port = process.env.PORT || 3000;
// NestJS 애플리케이션 및 데이터베이스 리스너 시작
await app.listen(port);
console.log(`Application is running on: ${await app.getUrl()}`);
// Graceful shutdown 로직을 통합 관리
// 시그널 핸들러
const shutdown = async () => {
console.log('Shutting down gracefully...');
await dataSource.close(); // 데이터베이스 연결 종료
await app.close(); // NestJS 애플리케이션 종료
console.log('Resources released, application closed.');
process.exit(0); // 프로세스 종료
};
// 시그널 처리 핸들러 등록
process.on('SIGINT', shutdown);
process.on('SIGTERM', shutdown);
}
bootstrap();
이 코드는 typeorm 라이브러리를 사용하여 설정된 데이터베이스 연결을 종료합니다. DataSource 객체는 데이터베이스 연결을 관리하는 주체로, 여기에는 SQL 데이터베이스와의 연결이 포함됩니다. close() 메소드는 다음과 같은 일련의 작업을 수행합니다:
연결 종료: 데이터베이스와의 모든 활성 연결을 안전하게 종료합니다. 이는 현재 진행 중인 모든 쿼리가 완료되거나 시간 초과될 때까지 기다립니다.
리소스 해제: 연결을 통해 사용되는 모든 리소스(메모리, 네트워크 소켓 등)를 해제합니다.
풀(Pool) 닫기: 연결 풀이 사용되는 경우, 풀에 있는 모든 연결을 닫고 관련 리소스를 정리합니다.
이 작업은 데이터베이스 작업을 안전하게 종료하고, 데이터베이스 서버에 대한 불필요한 부하를 방지하며, 데이터 손실의 위험을 최소화하는 데 중요합니다.
app.close() 메소드는 NestJS 애플리케이션을 종료할 때 호출됩니다. NestJS는 Node.js 위에서 동작하는 프레임워크로, app.close() 메소드는 애플리케이션과 관련된 다양한 종료 작업을 수행합니다. 이 메소드의 주요 작업은 다음과 같습니다:
HTTP 서버 종료: NestJS가 사용하는 HTTP 서버 인스턴스를 종료합니다. 이 과정에서 모든 들어오는 요청이 처리 완료되거나 거절됩니다.
이벤트 루프 정리: Node.js의 이벤트 루프에서 NestJS 애플리케이션이 사용하고 있는 모든 비동기 작업이 완료되도록 기다립니다. 이는 메모리 누수를 방지하고, 애플리케이션 종료 시 안정성을 보장합니다.
종속성 주입(Dependency Injection) 시스템 해제: NestJS의 종속성 주입 컨테이너를 해제하고, 관련 서비스와 컨트롤러 인스턴스의 정리 및 종료 로직을 수행합니다.
모듈 해제: 등록된 모든 모듈을 해제하고, 각 모듈에 등록된 프로바이더(서비스, 컨트롤러 등)의 onModuleDestroy 생명주기 이벤트를 호출하여 추가적인 종료 처리를 수행합니다.


import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.enableShutdownHooks(); // Shutdown Hooks 활성화
const port = process.env.PORT || 3000;
await app.listen(port);
}
bootstrap();