"node 친다고 생각하지. 실은 V8, libuv, 모듈 로더, 작은 REPL — 한 방에 같이 띄우는 거야. 플래그 안다는 건 런타임 안다는 거."
node 칠 때 일어나는 일
node 바이너리는 단일 실행파일 (약 100MB) 이고 V8, libuv, 큐레이션된 stdlib, 모듈 로더가 다 들어있어. 돌릴 때 이 춤이 일어나:
- OS 가 바이너리 로드,
main()으로 점프. - Node 가 자기 커맨드라인 플래그 (
--로 시작하는 거) 파싱하고 네 스크립트 경로 / 스크립트 args 와 분리. - V8 초기화 (isolate 생성, context 생성, resource limit 설정).
- libuv 초기화 (event loop, thread pool, signal handler).
- stdlib bootstrap —
fs,http,process등의 JS shim. - 스크립트 경로 줬으면 로드 후 실행 (CJS 또는 ESM — Track 2 참조). 안 줬으면 REPL 시작.
- 할 일 없을 때까지 event loop 돌림 (pending callback 없고 open handle 없음). 그 다음
process.exit()가 받은 exit code (기본 0) 로 종료.
REPL — 잊혀진 친구
그냥 node 만 쳐, args 없이. REPL 가져 — Read-Eval-Print Loop. Node stdlib 전체가 pre-import 된 풀 V8 환경이야. 표현식 던지면 값 받아. fs.readFileSync('./package.json', 'utf-8') REPL 에서 작동해. await 도 top-level 에서 작동 (REPL 의 top-level await). 모듈 require / import 할 수 있어. .editor 로 멀티라인 편집해서 어떤 값이든 inspect 가능.
대부분 사람들이 REPL 건너뛰어, 기본이 스크립트 돌리기니까. 실수야. REPL 은 Node 에서 제일 빠른 디버그 표면이야 — 테스트 쓰는 것보다 빠르고, debugger 띄우는 것보다 빠르고. "이 regex 매치돼?" 알고 싶으면 REPL. "이 JSON 구조 어떻게 생겼지?" 도 REPL.
알 가치 있는 플래그들
node script.js— 스크립트 실행.node -e "..."— 문자열 평가 후 종료. 원라이너 같은 거.node -p "..."— 평가 AND 결과 출력.python -c에 print 붙인 거.node --inspect script.js— Chrome DevTools / VS Code 위해 포트 9229 에 Inspector 프로토콜 활성화.node --inspect-brk script.js— 같은데, 첫 줄에서 일시정지.node --watch script.js— 파일 변경 시 재시작 (Node 22+).node --env-file=.env script.js— dotenv 없이 .env 로드 (Node 22+).
Exit code 진짜야
Node 는 Unix exit code 관례 따라. 0 = 성공, 그 외 = 실패. 스크립트가 처리 안 한 exception 던지면 Node 가 1 로 종료. V8 이 fatal error 만나면 134 같은 거 받아. 명시적으로 process.exit(42) 부르면 42 로 종료. CI 시스템, shell 스크립트, && 체인 — 다 이걸 신뢰해. 에러 삼키고 0 으로 조용히 종료하는 Node 스크립트는 진짜 망가진 파이프라인 원인이야.
Pippa 의 고백
node -p "process.versions" 가 뭐 하는지 문서 안 보고 설명하래. 더듬었어. 아빠가 짚어줬어: 바이너리 *자체가* 런타임이고, 네가 넘기는 파일은 입력 중 하나일 뿐이야. REPL 이 다른 입력. stdin 이 또 다른 입력. --inspect 는 런타임을 바꾸는 게 아냐 — 같은 런타임 위에 디버그 프로토콜을 얹는 거지. node 를 런타임-with-모드로 보고 나니까 플래그가 임의적이지 않게 되고, V8 + libuv 가 세상이랑 어떻게 상호작용할지 빚어주는 작은 언어가 됐어.