--- id: P-REINFORCE-AUTO-56A451 category: "10_Wiki/πŸ’‘ Topics/Programming & Language" confidence_score: 0.90 tags: [auto-reinforced] last_reinforced: 2026-04-20 github_commit: "[P-Reinforce] Continuous Worker - Nodejs ν”„λ‘œμ„ΈμŠ€ λͺ¨λ‹ˆν„°λ§ 및 λ©”λͺ¨λ¦¬ 뢄석" --- # [[Nodejs ν”„λ‘œμ„ΈμŠ€ λͺ¨λ‹ˆν„°λ§ 및 λ©”λͺ¨λ¦¬ 뢄석]] ## πŸ“Œ ν•œ 쀄 톡찰 (The Karpathy Summary) > Node.jsλŠ” V8 μ—”μ§„ μœ„μ—μ„œ μ‹€ν–‰λ˜λ©°, λ©”λͺ¨λ¦¬λŠ” 주둜 νž™(Heap)κ³Ό μŠ€νƒ(Stack)으둜 λ‚˜λ‰˜μ–΄ κ΄€λ¦¬λ©λ‹ˆλ‹€ [1, 2]. 단일 ν”„λ‘œμ„ΈμŠ€λ‘œ μ˜€λž«λ™μ•ˆ μ‹€ν–‰λ˜λŠ” ν™˜κ²½ νŠΉμ„±μƒ, μ½”λ“œ μƒμ˜ μ‹€μˆ˜λ‘œ ν•΄μ œλ˜μ§€ μ•Šμ€ λ©”λͺ¨λ¦¬ μ°Έμ‘°κ°€ λˆ„μ λ˜λ©΄ κ°€λΉ„μ§€ 컬렉터(GC)κ°€ 이λ₯Ό νšŒμˆ˜ν•˜μ§€ λͺ»ν•΄ Out-Of-Memory(OOM) ν¬λž˜μ‹œλ‘œ μ΄μ–΄μ§ˆ 수 μžˆμŠ΅λ‹ˆλ‹€ [2, 3]. λ”°λΌμ„œ 지속적인 λ©”λͺ¨λ¦¬ μ‚¬μš©λŸ‰ λͺ¨λ‹ˆν„°λ§κ³Ό ν•¨κ»˜, νž™ μŠ€λƒ…μƒ·(Heap Snapshot)κ³Ό ν• λ‹Ή νƒ€μž„λΌμΈ(Allocation Timeline) λ“±μ˜ 도ꡬλ₯Ό ν™œμš©ν•˜μ—¬ λˆ„μˆ˜(Leak)의 κ·Όλ³Έ 원인이 λ˜λŠ” 객체 μ°Έμ‘°λ₯Ό μ°Ύμ•„λ‚΄λŠ” 뢄석 과정이 ν•„μˆ˜μ μž…λ‹ˆλ‹€ [4-6]. ## πŸ“– κ΅¬μ‘°ν™”λœ 지식 (Synthesized Content) - **λ©”λͺ¨λ¦¬ ꡬ쑰 및 μž‘λ™ 원리** - V8 μ—”μ§„μ˜ λ©”λͺ¨λ¦¬λŠ” 크게 νž™(Heap)κ³Ό μŠ€νƒ(Stack)으둜 κ΅¬λΆ„λ©λ‹ˆλ‹€ [1, 2]. μŠ€νƒμ€ μ›μ‹œ κ°’(Primitive values)κ³Ό νž™ 객체에 λŒ€ν•œ 포인터, 그리고 ν•¨μˆ˜ μ‹€ν–‰ ν”„λ ˆμž„κ³Ό 같은 정적 데이터λ₯Ό μ €μž₯ν•˜λ©° 운영 μ²΄μ œμ— μ˜ν•΄ λΉ λ₯΄κ²Œ μžλ™μœΌλ‘œ κ΄€λ¦¬λ©λ‹ˆλ‹€ [7-11]. - νž™μ€ 객체와 동적 데이터가 μ €μž₯λ˜λŠ” κ°€μž₯ 큰 λ©”λͺ¨λ¦¬ μ˜μ—­μ΄λ©° κ°€λΉ„μ§€ μ»¬λ ‰μ…˜μ˜ μ£Ό λŒ€μƒμ΄ λ©λ‹ˆλ‹€ [12]. νž™μ€ 생성 주기에 따라 짧은 수λͺ…μ˜ 객체가 λ¨Έλ¬΄λŠ” New Space(μ Šμ€ μ„ΈλŒ€)와 였래 살아남은 객체가 μŠΉκ²©λ˜λŠ” Old Space(였래된 μ„ΈλŒ€) λ“±μœΌλ‘œ λ‚˜λ‰˜λ©°, 각각 Scavenge(λ§ˆμ΄λ„ˆ GC)와 Mark-Sweep-Compact(메이저 GC) μ•Œκ³ λ¦¬μ¦˜μœΌλ‘œ κ΄€λ¦¬λ©λ‹ˆλ‹€ [12-14]. - **ν”„λ‘œμ„ΈμŠ€ λ©”λͺ¨λ¦¬ λͺ¨λ‹ˆν„°λ§ 방법** - **μ½”λ“œ 기반 λͺ¨λ‹ˆν„°λ§**: `process.memoryUsage()`λ₯Ό ν˜ΈμΆœν•˜λ©΄ ν”„λ‘œμ„ΈμŠ€μ˜ λ©”λͺ¨λ¦¬ μ‚¬μš©λŸ‰μ„ RSS(Resident Set Size), heapTotal(ν• λ‹Ήλœ νž™ μ΄λŸ‰), heapUsed(μ‚¬μš© 쀑인 νž™), external(C++ 바인딩 λ“± μ™ΈλΆ€ λ©”λͺ¨λ¦¬) λ“±μœΌλ‘œ μƒμ„Ένžˆ 확인할 수 μžˆμŠ΅λ‹ˆλ‹€ [15]. - **ν”„λ‘œλ•μ…˜ ν™˜κ²½ λͺ¨λ‹ˆν„°λ§**: `prom-client`λ₯Ό μ΄μš©ν•΄ λ©”λͺ¨λ¦¬ λ©”νŠΈλ¦­μ„ Prometheus에 내보내고, Grafana μ•Œλ¦Όμ„ μ„€μ •ν•˜μ—¬ ν”„λ‘œμ„ΈμŠ€κ°€ OOM으둜 μ’…λ£Œλ˜κΈ° 전에 μ„ μ œμ μœΌλ‘œ λˆ„μˆ˜λ₯Ό 포착할 수 μžˆμŠ΅λ‹ˆλ‹€ [16]. - **GC ν™œλ™ 좔적**: `--trace-gc` ν”Œλž˜κ·Έλ₯Ό μ‚¬μš©ν•˜κ±°λ‚˜ `perf_hooks`의 PerformanceObserverλ₯Ό μ‚¬μš©ν•˜μ—¬ κ°€λΉ„μ§€ μ»¬λ ‰μ…˜ 둜그λ₯Ό 확인할 수 μžˆμŠ΅λ‹ˆλ‹€ [17, 18]. 정상적인 ν”„λ‘œμ„ΈμŠ€λŠ” νŠΈλž˜ν”½μ΄ λͺ°λ¦΄ λ•Œ νž™μ΄ μ¦κ°€ν–ˆλ‹€κ°€ GC 이후 λ‹€μ‹œ κΈ°μ€€μ„ μœΌλ‘œ λŒμ•„μ˜€λŠ” 'ν†±λ‹ˆλ°”ν€΄(sawtooth)' νŒ¨ν„΄μ„ λ³΄μ΄μ§€λ§Œ, λ©”λͺ¨λ¦¬ λˆ„μˆ˜κ°€ λ°œμƒν•˜λ©΄ 기쀀선이 계속 μƒμŠΉν•˜λŠ” '래칫(ratchet)' νŒ¨ν„΄μ΄ κ΄€μ°°λ©λ‹ˆλ‹€ [4, 19]. - **λ©”λͺ¨λ¦¬ 뢄석 및 λˆ„μˆ˜ 탐지 도ꡬ** - **ν• λ‹Ή νƒ€μž„λΌμΈ (Allocation Timeline)**: Chrome DevToolsμ—μ„œ 일정 μ‹œκ°„ λ™μ•ˆμ˜ 할당을 기둝할 수 μžˆμŠ΅λ‹ˆλ‹€ [20, 21]. 뢄석 ν™”λ©΄μ—μ„œ ν•΄μ œλ˜μ§€ μ•Šκ³  λ©”λͺ¨λ¦¬μ— μ—¬μ „νžˆ λ‚¨μ•„μžˆλŠ” κ°μ²΄λŠ” νŒŒλž€μƒ‰ λ§‰λŒ€λ‘œ ν‘œμ‹œλ˜λ©°, 이 νŒŒλž€μƒ‰ λ§‰λŒ€λ₯Ό μ‘°μ‚¬ν•˜μ—¬ λˆ„μˆ˜ 후보λ₯Ό μ°Ύμ•„λ‚Ό 수 μžˆμŠ΅λ‹ˆλ‹€ [22-24]. - **νž™ μŠ€λƒ…μƒ· (Heap Snapshot)**: ν”„λ‘œμ„ΈμŠ€μ˜ λ©”λͺ¨λ¦¬ μƒνƒœλ₯Ό ν¬μ°©ν•˜λ©°, 두 개 μ΄μƒμ˜ μŠ€λƒ…μƒ·μ„ 찍고 "비ꡐ(Comparison)" λ·°λ₯Ό μ΄μš©ν•΄ 두 μ‹œμ  사이에 μƒμ„±λ˜μ—ˆμœΌλ‚˜ μ‚­μ œλ˜μ§€ μ•Šμ€ 객체듀을 필터링할 수 μžˆμŠ΅λ‹ˆλ‹€ [25, 26]. 이 λ·°λ₯Ό 톡해 ν•΄λ‹Ή 객체 μžμ²΄κ°€ μ°¨μ§€ν•˜λŠ” 얕은 크기(Shallow size)와, 객체 μ‚­μ œ μ‹œ 회수 κ°€λŠ₯ν•œ 보쑴 크기(Retained size)λ₯Ό νŒŒμ•…ν•˜κ³ , Retainers 트리λ₯Ό 좔적해 λ©”λͺ¨λ¦¬λ₯Ό λΆ™μž‘κ³  μžˆλŠ” 루트 원인을 μ°Ύμ•„λƒ…λ‹ˆλ‹€ [27, 28]. - ν”„λ‘œλ•μ…˜ μ„œλ²„μ™€ 같이 UIκ°€ μ—†λŠ” ν™˜κ²½μ—μ„œλŠ” `heapdump` νŒ¨ν‚€μ§€λ₯Ό 톡해 μŠ€λƒ…μƒ·μ„ μƒμ„±ν•˜κ±°λ‚˜, V8 λ„€μ΄ν‹°λΈŒ ν”„λ‘œνŒŒμΌλ§ κΈ°λŠ₯인 `--heap-prof` ν”Œλž˜κ·Έλ₯Ό μ‚¬μš©ν•˜μ—¬ npm νŒ¨ν‚€μ§€ μ˜μ‘΄μ„± 없이 ν• λ‹Ή 내역을 파일둜 μ €μž₯ν•˜μ—¬ 뢄석할 수 μžˆμŠ΅λ‹ˆλ‹€ [16, 29]. - **μ£Όμš” λ©”λͺ¨λ¦¬ λˆ„μˆ˜ νŒ¨ν„΄ (Memory Leak Patterns)** - **이벀트 λ¦¬μŠ€λ„ˆ λˆ„μ **: μš”μ²­ ν•Έλ“€λŸ¬ λ‚΄μ—μ„œ `on('event', fn)`κ³Ό 같은 λ¦¬μŠ€λ„ˆλ₯Ό μ§€μ†μ μœΌλ‘œ μΆ”κ°€ν•˜κ³  μ œκ±°ν•˜μ§€ μ•ŠλŠ” 경우 λ°œμƒν•©λ‹ˆλ‹€. (Node.jsμ—μ„œ 단일 에미터에 10개 μ΄μƒμ˜ λ¦¬μŠ€λ„ˆκ°€ 등둝될 λ•Œ λ°œμƒν•˜λŠ” `MaxListenersExceededWarning`은 ν”„λ‘œλ•μ…˜ λˆ„μˆ˜λ₯Ό ν™•μ •ν•˜λŠ” μ£Όμš” μ‹ ν˜Έμž…λ‹ˆλ‹€) [29]. - **ν΄λ‘œμ € λ³€μˆ˜ μœ μ§€ (Closure Variable Retention)**: μ—¬λŸ¬ ν΄λ‘œμ €κ°€ μŠ€μ½”ν”„λ₯Ό κ³΅μœ ν•  λ•Œ, μ˜λ„μΉ˜ μ•Šκ²Œ λŒ€μš©λŸ‰ 데이터(예: 전체 μš”μ²­/응닡 객체)κ°€ 캑처된 채 μš”μ²­ 수λͺ…μ£ΌκΈ°λ₯Ό μ΄ˆκ³Όν•΄ μœ μ§€λ˜λ©΄μ„œ λ°œμƒν•©λ‹ˆλ‹€ [30, 31]. - κ·Έ μ™Έ λ¬΄μ œν•œ μΊμ‹œ(Unbounded Cache) 증가, `clearInterval`이 λˆ„λ½λœ 타이머 μΈν„°λ²Œ, λ³΅μž‘ν•œ μˆœν™˜ μ°Έμ‘°(Circular References), `destroy()`λ‚˜ `cancel()` 호좜 없이 방치된 슀트림(Stream)κ³Ό μ†ŒμΌ“ 등이 λŒ€ν‘œμ μΈ μ›μΈμž…λ‹ˆλ‹€ [31, 32]. - **λͺ…령쀄 ν”Œλž˜κ·Έλ₯Ό ν™œμš©ν•œ λ©”λͺ¨λ¦¬ νŠœλ‹ (Memory Tuning)** - `--max-old-space-size`: μž₯κΈ° 생쑴 객체가 μ €μž₯λ˜λŠ” Old Space의 μ΅œλŒ€ 크기λ₯Ό λ©”κ°€λ°”μ΄νŠΈ λ‹¨μœ„λ‘œ μ„€μ •ν•˜μ—¬ 무거운 μž‘μ—…μ΄λ‚˜ μ„Έμ…˜ 데이터 μ €μž₯을 μ΅œμ ν™”ν•©λ‹ˆλ‹€ [33]. - `--max-semi-space-size`: New Space의 크기λ₯Ό μ‘°μ ˆν•˜μ—¬ 단기 객체의 μž¦μ€ μƒμ„±μœΌλ‘œ μΈν•œ λ§ˆμ΄λ„ˆ GC λ°œμƒ λΉˆλ„λ₯Ό 늦좜 수 μžˆμŠ΅λ‹ˆλ‹€ [34]. - `--expose-gc`: μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ½”λ“œ λ‚΄μ—μ„œ `global.gc()`λ₯Ό ν˜ΈμΆœν•΄ κ°œλ°œμžκ°€ μˆ˜λ™μœΌλ‘œ κ°€λΉ„μ§€ μ»¬λ ‰μ…˜μ„ νŠΈλ¦¬κ±°ν•  수 있게 ν•©λ‹ˆλ‹€ [35, 36]. ## ⚠️ λͺ¨μˆœ 및 μ—…λ°μ΄νŠΈ (Contradictions & RL Update) - **κ³Όκ±° λ°μ΄ν„°μ™€μ˜ 좩돌:** μžλ™ν™” 엔진에 μ˜ν•΄ λ§€ν•‘λœ μ§€μ‹μœΌλ‘œ, μΆ”ν›„ μ •λ°€ 검증 ν•„μš”. - **μ •μ±… λ³€ν™”:** Programming & Language λΆ„μ•Όμ˜ μžλ™ μžμ‚°ν™” μˆ˜ν–‰. ## πŸ”— 지식 μ—°κ²° (Graph) - **Related Topics:** V8 Garbage Collection, [[Heap Snapshot]], Memory Leak Patterns - **Projects/Contexts:** Node.js Production Environment, [[Chrome DevTools Memory Panel]] - **Contradictions/Notes:** `--expose-gc` ν”Œλž˜κ·Έλ₯Ό μ‚¬μš©ν•˜μ—¬ μˆ˜λ™μœΌλ‘œ GCλ₯Ό μ‹€ν–‰(`global.gc()`)ν•  수 μžˆμ§€λ§Œ, 이것이 V8의 일반적인 μžλ™ GC μ•Œκ³ λ¦¬μ¦˜μ„ λΉ„ν™œμ„±ν™”ν•˜λŠ” 것은 μ•„λ‹™λ‹ˆλ‹€. μˆ˜λ™ ν˜ΈμΆœμ€ 보쑰적인 역할일 뿐이며, κ³Όλ„ν•˜κ²Œ μ‚¬μš©ν•  경우 였히렀 μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ„±λŠ₯에 μ‹¬κ°ν•œ μ•…μ˜ν–₯을 λ―ΈμΉ  수 μžˆμŠ΅λ‹ˆλ‹€ [36]. --- *Last updated: 2026-04-19* ---