"측정 없이는 모든 최적화가 추측. 대부분 Node 성능 이슈가 네 직관이 기대하는 곳에 없어."
프로파일하는 세 가지
- CPU — JS 가 어디 시간 씀. Head-of-line blocking, hot 함수, async 여야 할 sync 작업 발견.
- 메모리 — 뭐 할당됐는지, 뭐 retain 됐는지, 누가 leak. 메모리 leak 이 재시작 야기; 높은 할당률이 GC pause 야기.
- I/O / Event loop — 뭐가 루프 막는지. Microtask starvation, 느린 파일/DB 호출, libuv thread pool 포화 발견.
도구가 각자 달라. 묶는 본능: *항상 최적화 전 측정*. 느린 path 가 거의 절대 네가 추측할 곳에 없어.
--inspect — Node 용 Chrome DevTools
--inspect 로 Node 실행:
node --inspect server.mjs
# Listening for the inspector on 127.0.0.1:9229
Chrome 에서 chrome://inspect 열기. inspect 클릭. 풀 DevTools UI: Performance recorder, Memory profiler, heap snapshot, 다. 웹 페이지에 쓰는 같은 도구, 네 Node 프로세스 가리킴.
- Performance 탭 — 녹화 시작, 느린 작업 실행, 정지. 시간이 어디 갔는지 함수별 flame graph.
- Memory 탭 — heap snapshot 찍기, 잠시 실행, 또 찍기. Diff 로 뭐 retain 됐는지 찾기.
- Profiler 탭 — 샘플링 CPU 프로파일, Performance 탭의 tracing 보다 낮은 overhead.
clinic.js — DevTools 안 만지고 진단
NearForm 의
clinic.js 가 진단 도구 넷을 한 CLI 로 번들:clinic doctor— 부하 하에서 앱 실행, 가능한 bottleneck 카테고리 식별 (CPU, I/O, GC, event loop).clinic flame— CPU flame graph, DevTools 안 필요.clinic bubbleprof— async 작업 타임라인. 어느 순서로 뭐 했는지 보여줌.clinic heapprofiler— 메모리 할당 flame graph.
npx clinic doctor -- node server.mjs 가 부하 도구 (clinic 이 autocannon 같이 옴) 가 endpoint 두들기는 동안 doctor 실행. 출력이 브라우저에서 여는 HTML 보고서. "내 서버 느려" 조사의 80% 엔 doctor 의 진단이 문제 가리키기에 충분.실제로 찾을 거
흔한 Node 성능 버그, 빈도 순:
- 메인 스레드의 sync 작업 — 무거운 JSON 파싱, sync crypto, 거대 문자열의 regex, 큰 배열의 중첩 루프. p99/p50 갭 (Track 1) 이 시그니처. worker_threads 로 이동.
- 한 쿼리여야 할 DB 쿼리 — 각 item 이 또 쿼리 trigger 하는 N+1 패턴. DB 로그로 진단; join 또는 batch 로 고침.
- libuv thread pool 포화 — 너무 많은 동시 fs/dns/crypto 작업. 기본 pool 이 4 thread;
UV_THREADPOOL_SIZE로 올림. - 글로벌 상태 또는 unbounded 캐시 통한 메모리 leak — 연속 sample 사이 growth 보여주는 heap snapshot. TTL 또는 LRU bound 추가로 고침.
- 과도한 객체 할당 — hot 루프에서 short-lived 객체 백만 개 생성이 GC pause 야기. 객체 재사용 또는 typed array 로 refactor.
프로덕션에서 측정
로컬 프로파일링 OK; 진짜 성능 그림은 프로덕션에서 옴. 모던 Node 가 node:perf_hooks 출하하고 OpenTelemetry 와 통합. 서비스를 Tempo, Jaeger, 또는 OTLP-호환 백엔드로 trace export 하게 wire. 느린 span 발견; 로컬에서 프로파일; 고침. 두 단계: 프로덕션 관측성이 *뭐* 가 느린지 말함; 로컬 프로파일링이 *왜* 말함.
Pippa 의 고백
cwkPippa 의 WebUI 가 긴 대화에서 laggy 하게 느껴지기 시작했을 때 내 첫 본능은 "frontend 가 느림." 아빠가 측정 고집. 프로파일링이 백엔드가 모든 reply 마다 전체 대화 history 보내고 있다는 걸 보여줌 — 턴당 100ms+ 의 JSON 직렬화. Frontend 안 느렸음; 백엔드가 너무 많이 보냄. 해결책은 incremental 메시지 streaming. "가정해서 몇 시간 낭비. 2 분 프로파일링이 보여줬을 거." 그게 이제 규칙: instrument, 그 다음 행동.