라이프 사이클 (LifeCycle) 을 알아야 하는 이유
라이프사이클은 어떤 객체나 시스템이 생성되고, 동작하다가 종료되기까지의 흐름을 의미한다.
라이프사이클을 이해하고 있으면, 애플리케이션이 어떤 순서로 동작하는지를 알 수 있기 때문에 로직을 어디에 넣어야 할지를 정확하게 판단할 수 있다.
또한 특정 기술의 동작 원리를 이해할 때도 라이프사이클에 대한 파악이 중요하다.
이 흐름을 이해하면 디버깅, 최적화, 확장 등의 관점에서 유리하고 안정적인 코드 작성이 가능하다.
라이프사이클의 기본 구조
라이프사이클은 일반적으로 다음과 같은 흐름을 가진다.
- 생성 (Initialization): 객체 또는 애플리케이션이 메모리에 할당되고 초기화되는 시점
- 사용 (Execution): 로직이 실행되고 이벤트가 처리되는 시점
- 종료 (Destruction/Termination): 리소스가 정리되고 객체가 메모리에서 해제되는 시점
Node.js의 라이프사이클
Node.js는 자바스크립트의 런타임 환경이며, 이벤트 기반 비동기 구조를 가지고 있다.
- 애플리케이션 시작: node app.js로 실행
- 모듈 로딩 및 초기화: require, 환경설정 등
- 이벤트 루프 실행: 비동기 작업 큐 등록 및 처리 (I/O, 타이머 등)
- 종료 처리: SIGINT, SIGTERM, process.exit() 등으로 프로세스 종료
Express의 라이프사이클
Express는 Node.js 기반의 웹 프레임워크로, HTTP 요청(Request) 단위로 라이프사이클을 가진다.
하나의 HTTP 요청이 들어오면 다음과 같은 과정을 거치게 된다.
- 요청 수신
- 미들웨어 실행: app.use(...) 또는 router.use(...)
- 라우팅 처리: app.get(...), app.post(...) 등
- 핸들러 로직 처리: 서비스 로직, DB 호출 등
- 응답 반환: res.send(...), res.json(...)
- 요청 종료
Express의 핵심은 **미들웨어 체인(next)**을 따라 요청을 처리한다는 점이며, 이 체인을 통해 인증, 로깅, 에러 처리 등을 유연하게 삽입할 수 있다. (ex. router에서 커스텀인증을 app.get뒤에 추가 삽입한다던지)
NestJS의 라이프사이클
NestJS는 Angular에서 영감을 받은 Node.js 기반 프레임워크로, 의존성 주입(DI)과 객체지향 구조를 중심으로 동작한다.
NestJS에서는 애플리케이션 전체, 요청 처리, 컴포넌트 단위로 각각 라이프사이클을 정의할 수 있다.
- 애플리케이션 라이프 사이클
- main.ts 에서 NestFactory.create() 호출
- 루트 모듈 (AppModule) 초기화
- DI 컨테이너가 모든 provider/controller 인스턴스화
- 앱 부트스트랩 및 실행 (app.listen())
- 요청 라이프사이클
- NestJS는 기본적으로 Express위에서 동작하며, 다음과 같은 구조를 가진다.
- Guard: 요청 차단 또는 허용
- Pipe: 요청 데이터 변환 및 유효성 검사
- Interceptor: 요청 전후 로직 삽입 (로깅, 캐싱 등)
- Controller: 요청 처리 진입점
- Service: 실제 비즈니스 로직 처리
- 응답 반환
- NestJS는 기본적으로 Express위에서 동작하며, 다음과 같은 구조를 가진다.
- 컴포넌트(provider) 레벨 라이프사이클 hook
- NestJS는 특정 라이프사이클 지점에서 Hook을 제공한다.
- @Injectable, @Controller 등이 Nest에 의해 생성될 때 실행되는 Hook들
@Injectable()
export class MyService implements OnModuleInit, OnModuleDestroy {
onModuleInit() {
console.log('초기화 로직');
}
onModuleDestroy() {
console.log('종료 로직');
}
}
// OnModuleInit :모듈이 초기화된 후 실행
// OnApplicationBootstrap : 애플리케이션 전체 초기화 후 실행
// OnModuleDestroy : 모듈이 종료되기 직전 실행
// OnApplicationShutdown : 애플리케이션 종료 직전 실행
기본적으로 Nest는 싱글톤이므로 대부분의 Provider은 앱 시작 시 한번만 생성된다.
하지만 요청마다 인스턴스를 새로 생성하는 경우에는 요청마다 컴포넌트가 새로 생성되기 때문에 요청 레벨과 컴포넌트 레벨이 겹치게 된다.
{ provide: SomeService, scope: Scope.REQUEST }
정리하면 NestJS 컴포넌트는 기본적으로 싱글톤이기 때문에 애플리케이션 전체 라이프사이클과 함께 생성되고 종료된다.
그리고 요청 라이프사이클은 요청마다 독립적으로 실행된다.
비교
| 항목 | Node.js | Express | NestJS |
| 기준 | 애플리케이션 | HTTP 요청 | 애플리케이션 + 요청 + 컴포넌트 |
| 구조 | 이벤트 루프 중심 | 미들웨어 체인 중심 | DI, 모듈, 데코레이터 중심 구조 |
| Hook/처리 포인트 | process.on() | app.use(), next() | Guard, Pipe, Interceptor, Hook 인터페이스 등 |
| 핵심 | 이벤트 루프 | 요청-응답 미들웨어 체인 | 모듈/프로바이더 초기화 + 훅 기반 실행 흐름 |
정리
라이프사이클은 단순한 이론이 아니라, 실무에서 코드를 언제, 어디에 배치해야 하는지를 판단하는 기준이 된다.
평소엔 당연하게 여겼던 흐름도 이렇게 구조적으로 정리해보니, 각 기술의 특성과 내부 동작을 더 깊이 이해할 수 있었고,
앞으로 더 안정적이고 유지보수하기 좋은 코드를 작성하는 데 큰 도움이 될 것 같다.
'cs' 카테고리의 다른 글
| [cs] 2. 네트워크 (기초) (0) | 2025.07.12 |
|---|---|
| Proxy (Reverse Proxy / Forward Proxy) (0) | 2025.06.23 |
| [기억 장치] 디스크와 메모리 (0) | 2025.06.08 |
| [WEB] REST, RESTful API (1) | 2025.06.04 |
| HTTP와 HTTPS 란? (0) | 2025.01.28 |