한양과학기술고등학교

에듀테크 프로젝트 대시보드

JIT 컴파일 (Just-In-Time)

JIT 컴파일 — 실행하면서 빨라지는 코드

같은 코드인데도 프로그램이 오래 돌수록 빨라진 경험이 있나요? 자바스크립트 엔진(V8)·JVM· 파이썬(PyPy) 같은 런타임은 자주 실행되는 코드(핫스팟)를 실행 도중에 기계어로 번역합니다. 이것이 JIT(Just-In-Time) 컴파일입니다. 아래에서 루프를 직접 돌려 "워밍업"이 일어나는 순간을 관찰해 보세요.

// interactive · 핫 루프를 돌려 티어 승급 관찰하기

실행할 코드

// 배열 원소를 모두 더하는 함수
function sumArray(arr) {
  let total = 0;
  for (let i = 0; i < arr.length; i++)
    total += arr[i];        // 인라인 캐시가 붙는 지점
  return total;
}
// 루프에서 sumArray()를 반복 호출
인터프리터
바이트코드 한 줄씩
베이스라인 JIT
빠른 기계어 · 최적화 X
최적화 JIT
타입 추측 · 인라인
호출 횟수
0
현재 티어
T0
처리량 (상대)
1.0×
다음 티어까지 (호출 카운터 임계값)
베이스라인 승급까지 50회

워밍업 곡선 — 반복할수록 빨라진다

// 인라인 캐시 — JIT이 빠른 진짜 이유

total += arr[i] 한 줄에도 "arr이 진짜 배열인가?", "원소가 정수인가?" 같은 확인이 숨어 있습니다. 매번 확인하면 느리죠. JIT은 처음 본 타입을 기억(캐시)해 두고, 다음부터는 "지난번과 같지?"만 검사합니다.

① 첫 실행 — 캐시 비어 있음 (monomorphic 되기 전)

엔진이 전체 조회 경로를 밟는다: arr의 히든클래스 확인 → 요소 종류(정수 배열) 기록 → "이 자리엔 정수 배열이 온다"고 캐시에 못박음.

② 반복 실행 — 캐시 적중 (monomorphic)

"이번에도 정수 배열?" 포인터 1회 비교로 끝. 최적화 JIT은 아예 경계검사·박싱까지 제거하고 load + add 두 명령으로 압축.

③ 타입이 흔들림 — polymorphic / megamorphic

어떨 땐 정수, 어떨 땐 실수, 어떨 땐 문자열이 들어오면 캐시에 여러 경우가 쌓여 분기가 늘어난다. 4가지 넘게 섞이면 캐시를 포기(megamorphic)하고 느린 경로로.

④ 추측 실패 — 역최적화(deoptimization)

"정수만 온다"고 가정하고 만든 기계어에 문자열이 들어오면? 최적화 코드를 버리고 인터프리터로 되돌아가 다시 관찰 시작. 위 데모의 💥 버튼이 이것.

// AOT vs 인터프리터 vs JIT
방식번역 시점장점약점예
AOT 컴파일
(Ahead-Of-Time)
실행 전 전체를 기계어로 시작 즉시 최고 속도, 런타임 오버헤드 없음 플랫폼별 빌드 필요, 런타임 정보(실제 입력 타입)를 못 씀 C·C++·Rust·Go
인터프리터 실행 중 한 줄씩 해석 즉시 시작, 이식성 최고, 메모리 적음 반복 코드도 매번 해석 → 느림 CPython, 초기 JS
JIT 컴파일 실행 중 핫스팟만 기계어로 실제 실행 패턴에 맞춘 최적화(타입 추측·인라인), 인터프리터보다 10~100× 워밍업 지연, 컴파일 스레드·메모리 비용, deopt 위험 V8, JVM HotSpot, PyPy, .NET
// 메서드 JIT vs 트레이싱 JIT
메서드(함수) 단위 JIT

"이 함수가 N번 호출됐다" → 함수 전체를 컴파일. JVM HotSpot, V8이 이 방식. 호출 카운터 + 루프 백엣지 카운터로 핫 판정.

트레이싱 JIT

"이 루프가 뜨겁다" → 한 번 도는 동안의 실제 실행 경로(trace)를 그대로 기록해 직선 코드로 컴파일. 자주 안 도는 분기는 "가드"만 남김. PyPy·초기 TraceMonkey.

핵심 정리 — JIT은 "느린 인터프리터로 시작해서, 실제로 자주 도는 부분만 골라 런타임 정보를 활용해 기계어로 바꾸는" 전략이다. 그래서 ① 벤치마크는 워밍업 후 측정해야 하고, ② 한 변수에 여러 타입을 마구 넣으면(다형성) JIT이 최적화를 포기하며, ③ 서버리스 함수처럼 짧게 살다 죽는 프로세스는 JIT 이득을 보기 전에 종료돼 AOT가 유리할 수 있다.