stack-analysis
CHAPTER 97 / 120
읽기 약 2분
FUNCTION
메모리 관리: 프로파일링 + 누수 탐지
핵심 개념
heap snapshot·closure leak·event listener·React leak — 메모리 폭주 방지.
본문
Node.js 메모리 모니터링
// 주기적 메모리 보고
setInterval(() => {
const mem = process.memoryUsage();
console.log({
rss: `${Math.round(mem.rss / 1024 / 1024)}MB`, // 전체 RAM
heapTotal: `${Math.round(mem.heapTotal / 1024 / 1024)}MB`,
heapUsed: `${Math.round(mem.heapUsed / 1024 / 1024)}MB`,
external: `${Math.round(mem.external / 1024 / 1024)}MB`,
});
}, 60000);
// Sentry 자동 전송
import * as Sentry from '@sentry/node';
setInterval(() => {
Sentry.metrics.gauge('memory.heap_used', process.memoryUsage().heapUsed);
}, 30000);메모리 누수 패턴 5가지
// 1. 글로벌 변수 누적
const cache = {}; // ❌ 무한 성장
// ✅ 제한된 캐시 (LRU)
import LRU from 'lru-cache';
const cache = new LRU({ max: 1000, ttl: 1000 * 60 * 5 });
// 2. Event Listener 누수
const listener = () => doSomething();
emitter.on('event', listener);
// ❌ 제거 안 함
// ✅
emitter.off('event', listener);
// 3. Closure 누수
function makeHandler() {
const big = new Array(1000000); // 큰 객체
return function() {
return 'small'; // big 참조 안 하지만 closure에 잡힘
};
}
// ✅
function makeHandler() {
return function() {
return 'small';
};
}
// 4. setInterval 누수
const interval = setInterval(work, 1000);
// ❌ clearInterval 안 하면 GC 안 됨
// ✅
clearInterval(interval);
// 5. Stream 미닫기
const stream = fs.createReadStream(file);
// ❌ 에러 시 close 안 함
// ✅
stream.on('error', () => stream.destroy());
stream.on('end', () => stream.destroy());Heap Snapshot (Chrome DevTools)
# Node.js 헤프 덤프
node --inspect server.js
# → chrome://inspect → Memory 탭 → Heap Snapshot
# 또는 v8.writeHeapSnapshot
import v8 from 'v8';
process.on('SIGUSR2', () => {
const file = `heap-${Date.now()}.heapsnapshot`;
v8.writeHeapSnapshot(file);
console.log(`Snapshot: ${file}`);
});
# 트리거
kill -SIGUSR2 <pid>React 메모리 누수
// ❌ unmount 후 setState
function Component() {
const [data, setData] = useState();
useEffect(() => {
fetch('/api').then(r => r.json()).then(setData); // unmount 후 호출 가능
}, []);
}
// ✅ AbortController + cleanup
function Component() {
const [data, setData] = useState();
useEffect(() => {
const controller = new AbortController();
fetch('/api', { signal: controller.signal })
.then(r => r.json())
.then(setData)
.catch(err => {
if (err.name === 'AbortError') return;
// ...
});
return () => controller.abort();
}, []);
}
// ❌ subscription 누수
useEffect(() => {
socket.on('event', handler);
// cleanup 누락
}, []);
// ✅
useEffect(() => {
socket.on('event', handler);
return () => { socket.off('event', handler); };
}, []);Stream 메모리
// ❌ 큰 파일 전체 로드
import fs from 'fs/promises';
const content = await fs.readFile('big.csv'); // 1GB → 1GB 메모리
// ✅ Stream
import { createReadStream } from 'fs';
import { parse } from 'csv-parse';
const parser = createReadStream('big.csv').pipe(parse({ columns: true }));
for await (const row of parser) {
await processRow(row); // 한 줄씩
}
// → 메모리 KB 수준
// ❌ JSON.stringify 큰 배열
const json = JSON.stringify(millionItems); // OOM
// ✅ JSONStream
import JSONStream from 'JSONStream';
const stream = JSONStream.stringify('[\n', ',\n', '\n]');
items.forEach(item => stream.write(item));
stream.end();메모리 한계 + Restart
// PM2 설정 — max_memory_restart
module.exports = {
apps: [{
name: 'api',
script: 'server.js',
instances: 4,
max_memory_restart: '500M', // 500MB 초과 시 재시작
}],
};
// Kubernetes
resources:
limits:
memory: 512Mi
requests:
memory: 256Mi
// → OOM 방지 + 자동 복구clinic.js (Node.js 프로파일러)
pnpm dlx clinic doctor -- node server.js
# → 부하 줘서 진단
pnpm dlx clinic heap-profile -- node server.js
# → 메모리 분석
pnpm dlx clinic flame -- node server.js
# → CPU 핫스팟다음 챕터
CH.98 "네트워크 최적화: HTTP/3 + 압축 + prefetch".
AI 프롬프트
🤖 AI에게 잘 물어보는 법 — 모델·전략별 프롬프트
Claude
무료: Sonnet 4.6 / Pro $20/mo: Opus 4.6
내 코드의 메모리 관리 부분을 분석해서 실전 분석 + 개선 우선순위를 알려줘.
ChatGPT
무료: GPT-5.5 / Plus $20/mo: GPT-5.5 Pro
메모리 관리 관련 베스트 프랙티스 5가지를 비교 분석해서 패턴 추출를 알려줘.
Gemini
무료: 2.5 Flash / Pro $19.99/mo: 3.1 Pro
내 프로젝트 전체에서 메모리 관리 최적화 가능 위치를 보고해줘.
Grok
무료: Grok 4.1 / SuperGrok $30/mo
2026년 한국 시장의 메모리 관리 트렌드를 솔직히 알려줘.
⭐ 이것만 기억하세요
메모리 관리: 프로파일링 + 누수 탐지는 이 3가지만 확실히 잡으세요
1.Node.js 메모리는 RSS·Heap 모니터링 + PM2 max_memory_restart
2.React useEffect cleanup으로 listener·subscription 정리
3.Stream 처리로 큰 파일·데이터 OOM 방지
공유하기
진행도 97 / 120