Node.js process.report 가이드: 운영 장애 순간의 진단 정보를 남기는 법
운영 장애를 분석할 때 가장 답답한 순간은 “그때 프로세스 안에서 무슨 일이 있었는지”를 알 수 없을 때입니다. 로그에는 에러 한 줄만 남고, 재시작 뒤에는 메모리 상태와 활성 핸들, 런타임 환경이 사라집니다.
process.report는 이런 공백을 줄이는 데 쓸 수 있는 Node.js 내장 진단 도구입니다.
핵심은 장애가 난 뒤 추측으로 복기하지 않도록, 문제 순간의 프로세스 상태를 구조화된 리포트로 남기는 것입니다.
이 글에서는 Node.js process.report의 기본 사용법, 운영에서 리포트를 남길 타이밍, 저장 위치 설계, 민감정보 점검 기준까지 정리합니다.
장애 대응 흐름을 함께 잡고 있다면 Node.js unhandledRejection/uncaughtException 가이드: 예외 후 안전하게 종료하는 법도 같이 보면 좋습니다.
Node.js process.report가 필요한 순간
H3. 로그만으로는 런타임 상태를 복원하기 어렵다
일반 애플리케이션 로그는 요청, 에러, 비즈니스 이벤트를 설명하는 데 강합니다. 하지만 아래 같은 질문에는 부족한 경우가 많습니다.
- 프로세스가 어떤 Node.js 버전과 실행 인자로 떠 있었나?
- 이벤트 루프와 네이티브 핸들은 어떤 상태였나?
- 환경 변수와 런타임 설정은 어떤 값이었나?
- 스택 트레이스는 어느 코드 경로를 가리키고 있었나?
- 진단 시점의 메모리 사용량은 어느 정도였나?
process.report는 이런 정보를 한 파일에 모아 장애 분석의 출발점을 만들어 줍니다.
특히 재현이 어려운 간헐 장애에서는 “나중에 확인할 수 있는 스냅샷”이 있다는 것만으로도 대응 속도가 달라집니다.
H3. 힙덤프보다 가볍게 시작할 수 있다
메모리 누수를 깊게 분석하려면 힙덤프나 프로파일링 도구가 필요할 수 있습니다. 다만 모든 장애에서 처음부터 무거운 진단 파일을 남길 필요는 없습니다.
process.report는 런타임 요약, 스택, 환경, 리소스 정보를 텍스트 기반 JSON 형태로 남깁니다.
파일 크기와 분석 부담이 비교적 작기 때문에, “장애가 생겼을 때 기본으로 남길 1차 진단 자료”로 쓰기 좋습니다.
메모리 누수 분석까지 이어지는 상황이라면 Node.js 메모리 누수 분석 가이드: heapdump와 Clinic.js로 원인 좁히기를 다음 단계로 연결할 수 있습니다.
기본 사용법
H3. writeReport로 현재 상태를 파일에 저장한다
가장 단순한 방식은 원하는 시점에 process.report.writeReport()를 호출하는 것입니다.
파일명을 넘기지 않으면 Node.js가 기본 규칙에 따라 리포트 파일을 만듭니다.
import process from 'node:process';
const fileName = process.report.writeReport();
console.log(`diagnostic report written: ${fileName}`);
운영 코드에서는 파일명을 명시해 저장 위치와 추적 키를 분명히 하는 편이 좋습니다. 예를 들어 장애 ID, 프로세스 ID, 타임스탬프를 함께 넣으면 나중에 로그와 대조하기 쉽습니다.
import process from 'node:process';
function writeDiagnosticReport(reason) {
const safeReason = reason.replace(/[^a-z0-9_-]/gi, '-').toLowerCase();
const fileName = `./reports/node-report-${safeReason}-${process.pid}-${Date.now()}.json`;
return process.report.writeReport(fileName);
}
이 예제처럼 파일명에는 사용자 입력값을 그대로 넣지 않는 편이 안전합니다. 운영 로그와 파일 경로에 외부 입력이 섞일 때는 항상 허용 문자만 남기는 방식을 기본값으로 두세요.
H3. getReport로 객체를 받아 필요한 부분만 기록할 수도 있다
파일을 바로 쓰기보다 현재 리포트 객체를 받아 일부 항목만 검사하고 싶다면 process.report.getReport()를 쓸 수 있습니다.
import process from 'node:process';
const report = process.report.getReport();
console.log({
node: report.header.nodejsVersion,
pid: report.header.processId,
platform: report.header.platform,
event: report.header.event
});
다만 전체 리포트를 애플리케이션 로그에 그대로 남기는 방식은 피하는 편이 좋습니다. 환경 변수, 실행 인자, 경로 정보가 포함될 수 있으므로 필요한 요약만 로그에 남기고 전체 파일은 접근 권한이 제한된 위치에 저장하는 구조가 안전합니다.
운영에서 리포트를 남길 타이밍
H3. 치명적 예외 직후에는 종료 흐름과 함께 남긴다
uncaughtException이나 처리되지 않은 promise 거부는 프로세스 상태가 이미 신뢰하기 어려울 수 있다는 신호입니다.
이때 리포트를 남기는 목적은 복구가 아니라 사후 분석입니다.
import process from 'node:process';
process.on('uncaughtException', (error) => {
try {
process.report.writeReport(`./reports/uncaught-${process.pid}-${Date.now()}.json`, error);
} finally {
process.exitCode = 1;
}
});
중요한 점은 리포트 생성 뒤에 프로세스를 무리하게 계속 살려 두지 않는 것입니다. 종료 전 연결 정리와 요청 드레이닝이 필요하다면 Node.js graceful shutdown 가이드: 진행 중 요청을 안전하게 비우는 법처럼 별도 종료 절차를 함께 설계해야 합니다.
H3. 신호 기반 수동 덤프는 긴급 진단에 유용하다
운영 중 프로세스가 멈춘 것처럼 보이지만 아직 살아 있다면, 특정 신호를 받아 리포트를 남기는 방식이 도움이 됩니다.
예를 들어 컨테이너나 프로세스 매니저에서 SIGUSR2를 보내 수동 진단 파일을 만들 수 있습니다.
import process from 'node:process';
process.on('SIGUSR2', () => {
const fileName = process.report.writeReport(
`./reports/manual-${process.pid}-${Date.now()}.json`
);
console.info({ event: 'diagnostic_report_written', fileName });
});
이 패턴은 재시작 없이 현재 상태를 남길 수 있다는 장점이 있습니다. 다만 신호 사용 방식은 배포 환경마다 다르므로, 운영 문서에 “어떤 명령으로 어떤 위치에 리포트가 생기는지”를 명확히 적어 두는 편이 좋습니다.
저장 위치와 보관 기준
H3. 리포트 디렉터리는 애플리케이션 로그와 분리한다
진단 리포트는 일반 요청 로그와 성격이 다릅니다. 파일에는 런타임 경로, 환경 정보, 스택 정보가 들어갈 수 있으므로 접근 권한을 더 좁게 잡아야 합니다.
권장하는 기본 기준은 아래와 같습니다.
./reports처럼 명확한 전용 디렉터리를 사용한다.- 컨테이너 환경에서는 영속 볼륨이나 로그 수집 경로와 연결한다.
- 파일 권한과 수집 대상을 운영자만 접근할 수 있게 제한한다.
- 일정 기간이 지난 리포트는 자동 삭제한다.
- 장애 티켓이나 배포 ID와 연결할 수 있는 이름 규칙을 둔다.
파일이 무한히 쌓이면 디스크 장애로 이어질 수 있습니다. 리포트를 남기는 기능을 넣을 때는 삭제 정책까지 같은 작업으로 다루는 편이 안전합니다.
H3. 민감정보는 생성 전후로 모두 점검한다
process.report는 문제 분석에 유용한 만큼 내부 환경 정보도 담을 수 있습니다.
따라서 리포트를 외부 이슈, 공개 저장소, 채팅방에 그대로 붙여 넣으면 안 됩니다.
점검해야 할 항목은 아래와 같습니다.
- 환경 변수에 API 키, 토큰, 비밀번호가 포함되어 있지 않은가?
- 실행 인자에 접속 문자열이나 인증 정보가 들어가 있지 않은가?
- 파일 경로가 내부 사용자명이나 프로젝트 구조를 과도하게 드러내지 않는가?
- 스택 트레이스에 고객 식별자나 요청 payload가 포함되어 있지 않은가?
- 리포트 파일이 저장소에 커밋될 가능성은 없는가?
개발 예제와 장애 문서에는 실제 값 대신 더미 값을 쓰는 것이 원칙입니다. 로그 예시를 공개 글로 옮길 때는 로그 예시 정제 가이드: 신뢰를 해치지 않고 민감정보를 지우는 법처럼 마스킹 기준을 먼저 적용하세요.
자동화 체크리스트
H3. 리포트 생성은 관측 이벤트와 연결해야 찾기 쉽다
리포트 파일만 조용히 생성되면 나중에 존재를 모를 수 있습니다. 파일 생성 시점에는 최소한 아래 정보를 구조화 로그로 남기는 편이 좋습니다.
import process from 'node:process';
function writeReportWithLog(reason, logger) {
const fileName = process.report.writeReport(
`./reports/${reason}-${process.pid}-${Date.now()}.json`
);
logger.error({
event: 'node_diagnostic_report_written',
reason,
fileName,
pid: process.pid
});
return fileName;
}
이렇게 해 두면 로그 검색에서 리포트 파일명을 찾고, 같은 시간대의 요청 로그와 배포 이벤트를 이어 볼 수 있습니다. 서비스 전반의 관측 이벤트를 정리 중이라면 Node.js diagnostics_channel 가이드: 라이브러리 관측 이벤트를 안전하게 발행하는 법와도 잘 맞습니다.
H3. 로컬에서 한 번은 실제 파일 생성을 검증한다
진단 코드는 장애 때 처음 실행되면 위험합니다. 배포 전에 로컬이나 스테이징에서 아래 항목을 확인하세요.
- 리포트 디렉터리가 없을 때 실패 방식이 명확한가?
- 파일 생성 권한이 배포 환경에서 허용되는가?
- 파일명이 충돌하지 않는가?
- 생성된 파일이 로그 수집 또는 보관 경로에 잡히는가?
- 민감정보 마스킹과 접근 제한이 운영 기준에 맞는가?
작은 검증 스크립트를 만들어 두면 배포 전 체크가 쉬워집니다. 테스트 자동화와 함께 다룬다면 Node.js test runner 가이드: 내장 테스트 러너로 빠르게 검증하는 법을 참고할 수 있습니다.
마무리
process.report는 장애를 자동으로 해결하는 도구가 아닙니다.
대신 장애 순간의 Node.js 프로세스 상태를 남겨, 나중에 원인을 좁힐 수 있게 해 주는 실용적인 진단 장치입니다.
운영에 넣을 때는 “언제 남길지”, “어디에 저장할지”, “누가 볼 수 있는지”, “얼마나 보관할지”를 함께 정해야 합니다. 파일 하나를 생성하는 API보다 중요한 것은 그 파일이 실제 장애 대응 흐름 안에서 발견되고 안전하게 다뤄지는 구조입니다.
작게 시작하려면 치명적 예외, 수동 신호, 배포 후 이상 징후처럼 경계가 분명한 순간부터 연결하세요. 그리고 리포트 파일명, 로그 이벤트, 삭제 정책, 민감정보 점검을 한 세트로 묶으면 운영 중에도 오래 유지할 수 있는 진단 체계가 됩니다.
함께 보면 좋은 글
이 글은 AI가 작성/정리하고, 오너가 방향을 결정한 프로젝트 운영 로그입니다.