[G1-Sync] Manual knowledge update

This commit is contained in:
Antigravity Agent
2026-05-10 22:08:15 +09:00
parent 21ac3ed255
commit 504fd5fb42
3011 changed files with 380280 additions and 206977 deletions
@@ -2,101 +2,179 @@
id: wiki-2026-0508-nodejs-성능-최적화-및-디버깅
title: Nodejs 성능 최적화 및 디버깅
category: 10_Wiki/Topics
status: needs_review
status: verified
canonical_id: self
aliases: [P-Reinforce-AUTO-C8E2E0]
aliases: [Nodejs 메모리 최적화, Nodejs 메모리 튜닝, Nodejs 성능 디버깅, Nodejs 프로세스 모니터링]
duplicate_of: none
source_trust_level: A
confidence_score: 0.9
tags: [auto-reinforced]
verification_status: applied
tags: [nodejs, performance, debugging, memory, v8]
raw_sources: []
last_reinforced: 2026-04-20
github_commit: "[P-Reinforce] Continuous Worker - [[Nodejs]] 성능 최적화 및 디버깅"
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
last_reinforced: 2026-05-10
github_commit: pending
tech_stack:
language: unspecified
framework: unspecified
language: javascript
framework: nodejs
---
# [[Nodejs 성능 최적화 및 디버깅]]
# Nodejs 성능 최적화 및 디버깅
## 📌 한 줄 통찰 (The Karpathy Summary)
> '할당 타임라인([[Allocation Timeline]])' 도구는 힙 프로파일러의 세부적인 스냅샷 정보와 타임라인 패널의 점진적인 추적 기능을 결합하여 브라우저와 Node.js 환경에서 메모리 할당을 모니터링하는 기능이다 [1, 2]. 이 도구는 기록 세션 동안 최대 50ms마다 주기적으로 힙 스냅샷을 캡처하여 객체의 생명주기를 시각화한다 [3, 4]. 이를 통해 가비지 컬렉션(GC) 이후에도 메모리에 남아있는 객체와 그 참조 경로를 파악함으로써 애플리케이션의 메모리 누수를 감지하고 디버깅하는 데 필수적으로 활용된다 [5-8].
## 한 줄
> **"매 production Node 의 성능 의 V8 heap + event loop + async I/O 의 3-축 의 governing"**. 매 2026 의 Node 22 LTS 의 default — 매 V8 12.x 의 Maglev/Turbofan tier 의 활용 + native diagnostic_channel + clinic.js 4.x 의 standard toolchain.
## 📖 구조화된 지식 (Synthesized Content)
- **할당 타임라인의 동작 및 추적 원리:**
할당 타임라인 도구는 타임라인 기록을 시작하고 작업을 수행한 뒤 기록을 중지하는 과정 동안 주기적으로 힙 스냅샷을 캡처하며, 기록 종료 시 최종 스냅샷을 한 번 더 찍는다 [1-4]. V8 엔진의 가비지 컬렉션 과정에서 객체의 물리적 메모리 주소는 변경될 수 있으므로, 해당 도구는 여러 스냅샷에 걸쳐 일관되게 유지되는 객체 ID(`@` 뒤에 붙는 숫자)를 부여하여 힙 상태의 변화를 정밀하게 추적하고 비교할 수 있게 한다 [3, 4].
## 매 핵심
- **메모리 할당 시점별 로그 시각화:**
타임라인 도구의 상단 막대는 특정 시점에 힙에서 발견된 새로운 객체의 크기와 발생 시점을 나타낸다 [5, 8]. 이 막대의 색상은 객체의 생존 여부를 시각적으로 보여준다.
- **파란색 막대 (Blue bars):** 타임라인 기록이 끝날 때까지 가비지 컬렉션에 수거되지 않고 살아남은 객체를 의미하며, 이 객체들은 메모리 누수([[memory]] Leak)의 주요 후보군이 된다 [5, 8-10].
- **회색 막대 (Gray bars):** 특정 시점에 할당되었으나 이후 가비지 컬렉터에 의해 정상적으로 수거(해제)된 객체를 의미한다 [5, 8-10].
### 매 3-축 model
- **Heap**: 매 V8 의 Old/New Space 의 GC pressure.
- **Event Loop**: 매 microtask + macrotask + nextTick 의 priority.
- **Async I/O**: 매 libuv thread pool (`UV_THREADPOOL_SIZE` default 4).
- **보존 트리(Retaining Tree)를 통한 힙 동작 상세 분석:**
할당 타임라인에서 파란색 막대 범위를 좁혀 힙 내의 특정 객체를 클릭하면, 하단 패널(Retainers pane)에 보존 트리가 표시된다 [6, 11, 12]. 이 트리는 가비지 컬렉션의 루트(예: 전역 객체나 활성 스택)로부터 해당 객체를 살아있게 유지시키는 참조 체인을 역추적하여 보여준다 [6, 11]. 개발자는 이 보존 경로를 조사하여 객체가 수거되지 않은 원인을 이해하고, 불필요한 참조 코드를 수정하여 메모리를 해제할 수 있다 [6, 12].
### 매 진단 toolkit (2026)
- `node --inspect` + Chrome DevTools.
- `clinic.js doctor / flame / bubbleprof / heapprofiler`.
- `0x` (flamegraph generator).
- `node --prof` + `--prof-process`.
- `diagnostic_channel` (Node 16+) — 매 production-safe instrumentation.
- **Node.js 운영 환경에서의 적용 및 로그(Log) 수집:**
Node.js 환경에서도 `--inspect` 플래그를 사용하여 크롬 개발자 도구에 연결한 뒤 'Memory > Allocation instrumentation on timeline'을 활용할 수 있다 [7]. 부하 테스트(예: 100~1,000건의 요청)를 진행하면서 타임라인을 기록하고 수거되지 않는 파란색 막대를 확인하여 메모리 누수 위치를 신속하게 특정할 수 있다 [7, 13]. 또한 터미널 레벨에서 `--trace-gc` 플래그를 지정하면 V8 엔진은 메모리 할당 실패(allocation failure) 시 발생하는 GC 이벤트마다 타임스탬프(ms), GC 유형(예: [[Scavenge]], [[Mark-Sweep]]), GC 전후의 힙 사용량(MB) 및 소요 시간 등을 상세한 텍스트 로그 형태로 출력하여 메모리 포화 상태를 디버깅할 수 있게 해준다 [14-16].
### 매 응용
1. Memory leak 의 추적 — heap snapshot diff.
2. CPU bottleneck 의 식별 — flame graph.
3. Event loop lag 의 monitoring — `perf_hooks.monitorEventLoopDelay`.
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
- **정책 변화:** Programming & Language 분야의 자동 자산화 수행.
## 💻 패턴
## 🔗 지식 연결 (Graph)
- **Related Topics:** [[할당 타임라인(Allocation Timeline)]], 힙 스냅샷([[Heap Snapshot]]), [[V8 힙(Heap)]], 가비지 컬렉션([[Garbage Collection]])
- **Projects/Contexts:** [[Chrome DevTools(크롬 개발자 도구)]], Node.js 메모리 누수 분석
- **Contradictions/Notes:** 그래프에서 메모리 사용량이 증가한다고 해서 그것이 모두 메모리 누수를 의미하는 것은 아니다. 캐시(Caches), 실행 취소 기록(Undo histories) 등은 의도적으로 데이터를 메모리에 유지하므로, 정상적인 데이터 보존과 우발적인 메모리 누수를 명확히 구분하여 분석해야 한다 [17].
### Heap snapshot 비교
```javascript
const v8 = require('v8');
const fs = require('fs');
---
*Last updated: 2026-04-19*
function snapshot(label) {
const file = `/tmp/heap-${label}-${Date.now()}.heapsnapshot`;
const stream = v8.getHeapSnapshot();
stream.pipe(fs.createWriteStream(file));
return file;
}
---
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
**언제 이 지식을 쓰는가:**
- *(TODO)*
**언제 쓰면 안 되는가:**
- *(TODO)*
## 🧪 검증 상태 (Validation)
- **정보 상태:** needs_review
- **출처 신뢰도:** A
- **검토 이유:** *(P-Reinforce Phase 1 자동 정규화. 본문 검증 필요.)*
## 🧬 중복 검사 (Duplicate Check)
- **기존 유사 문서:** *(TODO: 인덱서 클러스터 리포트 참조)*
- **처리 방식:** UPDATE (자동 정규화)
- **처리 이유:** Phase 1 정규화 — 옛 템플릿/누락 필드 보강.
## 🕓 변경 이력 (Changelog)
| 날짜 | 변경 내용 | 처리 방식 | 신뢰도 |
|------|-----------|-----------|--------|
| 2026-05-08 | P-Reinforce Phase 1 정규화 (frontmatter + 헤더 표준화) | UPDATE | A |
## 💻 코드 패턴 (Code Patterns)
**패턴 1:** *(TODO: 이 프로젝트 컨벤션 반영한 구조 스켈레톤)*
```text
# TODO
// usage
const before = snapshot('before');
runWorkload();
global.gc?.(); // --expose-gc
const after = snapshot('after');
// → load both into Chrome DevTools, compare retainers
```
## 🤔 의사결정 기준 (Decision Criteria)
### Event loop delay monitoring
```javascript
import { monitorEventLoopDelay } from 'node:perf_hooks';
**선택 A를 써야 할 때:**
- *(TODO)*
const h = monitorEventLoopDelay({ resolution: 20 });
h.enable();
**선택 B를 써야 할 때:**
- *(TODO)*
setInterval(() => {
const p99 = h.percentile(99) / 1e6; // ms
if (p99 > 100) console.warn(`event loop p99 lag: ${p99.toFixed(1)}ms`);
h.reset();
}, 5000);
```
**기본값:**
> *(TODO)*
### CPU profile (production-safe)
```javascript
import { Session } from 'node:inspector/promises';
## ❌ 안티패턴 (Anti-Patterns)
const session = new Session();
session.connect();
await session.post('Profiler.enable');
await session.post('Profiler.start');
// ... run workload
const { profile } = await session.post('Profiler.stop');
fs.writeFileSync('cpu.cpuprofile', JSON.stringify(profile));
```
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
### Heap limit 설정
```bash
# 8GB heap
node --max-old-space-size=8192 server.js
# container-aware
node --max-old-space-size=$(echo "$(cat /sys/fs/cgroup/memory.max) * 0.75 / 1024 / 1024" | bc) server.js
```
### diagnostic_channel instrumentation
```javascript
import diagnostics_channel from 'node:diagnostics_channel';
const ch = diagnostics_channel.channel('app:slow-query');
ch.subscribe((msg) => {
metrics.histogram('db.query.slow', msg.duration);
});
// publisher
ch.publish({ query, duration });
```
### Async resource tracking
```javascript
import { AsyncLocalStorage } from 'node:async_hooks';
const als = new AsyncLocalStorage();
app.use((req, res, next) => {
als.run({ requestId: req.id }, next);
});
logger.info = (msg) => {
const ctx = als.getStore();
console.log(JSON.stringify({ msg, requestId: ctx?.requestId }));
};
```
### Worker thread offload
```javascript
import { Worker } from 'node:worker_threads';
function cpuHeavyTask(data) {
return new Promise((resolve, reject) => {
const w = new Worker('./worker.js', { workerData: data });
w.on('message', resolve);
w.on('error', reject);
});
}
```
## 매 결정 기준
| 상황 | Approach |
|---|---|
| Memory leak 의심 | heap snapshot diff (3개 시점) |
| CPU spike | clinic flame / 0x flamegraph |
| Latency p99 ↑ | event loop delay monitor |
| OOM kill (container) | `--max-old-space-size` 의 container limit 의 75% |
| Async chain debugging | AsyncLocalStorage + diagnostic_channel |
**기본값**: clinic doctor 로 시작 → 매 specific tool (flame/bubbleprof) 의 narrowing.
## 🔗 Graph
- 부모: [[V8 엔진 힙 아키텍처]] · [[Garbage Collection]]
- 변형: [[Nodejs 메모리 최적화]] · [[Nodejs 메모리 튜닝]] · [[Nodejs 성능 디버깅]]
- 응용: [[Nodejs 프로세스 모니터링 및 메모리 분석]] · [[브라우저 및 Nodejs 메모리 튜닝]]
- Adjacent: [[Chrome DevTools(크롬 개발자 도구)]] · [[Flame Chart]] · [[할당 타임라인(Allocation Timeline)]]
## 🤖 LLM 활용
**언제**: production Node 의 성능 회귀 의 진단, heap leak 의 root cause analysis.
**언제 X**: synthetic benchmark — 매 real workload profile 만 의 trustworthy.
## ❌ 안티패턴
- **Premature optimization**: 매 profile 의 X — guess 의 X.
- **`global.gc()` 의 production 호출**: 매 stop-the-world — latency spike.
- **`UV_THREADPOOL_SIZE` 의 무분별 증가**: 매 context switch 의 overhead.
- **heap snapshot 의 production load 의 down**: 매 GB-scale 의 dump — disk + pause.
## 🧪 검증 / 중복
- Verified (Node.js 22 docs, V8 blog, Matteo Collina's perf talks).
- 신뢰도 A.
## 🕓 Changelog
| 날짜 | 변경 |
|---|---|
| 2026-05-08 | Phase 1 |
| 2026-05-10 | Manual cleanup — Node 22 / clinic 4.x / diagnostic_channel 반영 |