TECH 으로 돌아가기
TECH HACKER NEWS 2026.11.02 03:53 8분 읽기 24 READS

LISP부터 HotSpot까지, JIT 컴파일러 40년 역사로 보는 ‘실행하면서 컴파일한다’는 아이디어

JIT는 생각보다 훨씬 오래된 아이디어예요

요즘 쓰는 언어 런타임 대부분은 안쪽에서 JIT를 쓰고 있어요. 크롬에서 자바스크립트를 돌리는 V8, 스프링 서버가 올라가는 JVM의 HotSpot, .NET의 RyuJIT, 그리고 최근 CPython에 실험 기능으로 들어간 JIT까지 다 그래요. 그런데 이 JIT라는 아이디어는 언제 처음 나왔을까요? 자바가 뜨면서 90년대 후반에 생긴 기술로 아는 분이 많은데, 실제로는 훨씬 오래됐어요.

John Aycock이 2003년 ACM Computing Surveys에 낸 논문 「A Brief History of Just-In-Time」은 1960년부터 2000년까지 40년 동안 나온 JIT 연구를 한곳에 모아 정리한 글이에요. 나온 지 20년이 넘었지만 JIT를 공부하는 사람에게는 지금도 지도 같은 고전이라서 다시 꺼내 읽어볼 만해요.

JIT가 뭐냐면

개념부터 잡고 갈게요. 프로그램을 실행하는 방법은 크게 두 가지예요. 첫 번째는 컴파일이에요. 실행하기 전에 소스 코드를 전부 기계어로 바꿔두는 방식이라 빠르긴 한데, 실제로 돌아갈 때 어떤 데이터가 들어올지는 모르고 번역하는 거예요. 두 번째는 인터프리트예요. 코드를 한 줄씩 읽으면서 바로 실행하는 방식이라 유연하고 어느 기계에서나 잘 돌지만, 대신 느려요.

JIT(Just-In-Time) 컴파일은 이 둘의 좋은 점을 섞은 방식이에요. 처음엔 인터프리터처럼 실행하다가, 자주 실행되는 코드(이걸 핫스팟이라고 불러요)가 보이면 그 부분만 실행하는 도중에 기계어로 바꿔요. 식당으로 치면 메뉴를 전부 미리 만들어두는 대신, 주문이 몰리는 메뉴만 재료를 미리 손질해두는 거랑 비슷해요.

40년 동안의 주요 장면들

1960년, LISP. John McCarthy의 LISP 논문에 이미 함수를 실행 중에 기계어로 바꿔서 쓴다는 아이디어가 나와요. Aycock은 이걸 JIT의 가장 오래된 흔적으로 봐요.

1968년, Ken Thompson의 정규식. 유닉스를 만든 바로 그 사람이에요. 정규식을 검색할 때마다 해석하지 않고, IBM 7094 기계어로 즉석에서 컴파일해서 실행했어요. 지금 정규식 엔진들이 패턴을 컴파일해서 쓰는 방식의 원조라고 볼 수 있어요.

1970년대, APL과 혼합 코드. 인터프리터로 실행하는 코드와 컴파일된 코드를 한 프로그램 안에 섞어 쓰는 mixed code 연구가 이때 나와요. 자주 쓰는 부분만 컴파일한다는 지금의 JIT 철학이 이미 여기 있었던 거예요. 메모리가 부족하면 컴파일해둔 코드를 버리고, 다시 필요해지면 또 컴파일하는 throw-away compiling이라는 방식도 있었어요. 메모리가 귀하던 시절이라 나올 수 있었던 발상이에요.

1984년, Smalltalk. Deutsch와 Schiffman이 만든 Smalltalk-80 구현은 바이트코드를 필요한 순간에 기계어로 바꾸고, 그 결과를 캐시에 넣어뒀어요. 메서드를 호출하는 자리마다 마지막으로 불렀던 대상을 기억해두는 인라인 캐시도 이때 처음 나왔는데요, 지금 V8에서도 핵심 최적화로 쓰여요.

80년대 후반~90년대, Self. 이 논문에서 제일 중요한 대목이에요. Self는 Smalltalk보다도 더 동적인 언어였는데, 이걸 빠르게 돌리려고 연구진이 세 가지 기법을 만들었어요. 실행하면서 실제로 들어온 타입을 보고 최적화하는 type feedback, 여러 타입을 함께 기억해두는 다형성 인라인 캐시(PIC), 처음엔 빠르게 대충 컴파일해뒀다가 자주 쓰이면 공들여 다시 컴파일하는 적응형 최적화예요. 이 연구에 참여했던 사람들이 나중에 HotSpot과 V8을 만드는 데 깊이 관여했어요. Self에서 나온 아이디어가 오늘날 JVM과 브라우저까지 그대로 이어진 거예요.

90년대 후반, 바이너리 변환과 자바. HP의 Dynamo는 이미 기계어로 컴파일된 프로그램을 실행 중에 다시 최적화했어요. 그러다 1999년에 HotSpot이 나오면서 JIT는 학계의 아이디어에서 업계 표준이 됐어요.

Aycock의 분류법

이 논문은 역사만 정리한 게 아니라 JIT 시스템을 분류하는 기준도 제안해요. 컴파일을 프로그래머가 직접 시키는지 런타임이 알아서 하는지, 인터프리터용 코드와 기계어가 같이 존재하는지, 컴파일이 프로그램 실행과 동시에 다른 스레드에서 돌아가는지 같은 기준이에요. 요즘 런타임을 이 기준으로 보면 구조가 잘 보여요. 예를 들어 JVM은 인터프리터, C1, C2 여러 단계가 같이 존재하고 컴파일은 백그라운드 스레드에서 돌아가는 구조라고 정리할 수 있어요.

업계 맥락: JIT는 아직 끝난 연구가 아니에요

CPython 3.13에는 copy-and-patch 방식의 실험용 JIT가 들어갔어요. Ruby에는 Shopify가 만든 YJIT가 기본으로 포함돼 있고, PHP 8에도 JIT가 들어갔고, .NET은 단계별(tiered) 컴파일을 기본으로 써요. 재밌는 건 이 프로젝트들이 내세우는 기법 상당수가 이 논문에 이미 나온다는 거예요. 새로운 건 아이디어 자체라기보다, 그걸 요즘 하드웨어와 언어에 맞게 다듬는 엔지니어링 쪽이에요.

한국 개발자에게 주는 시사점

JIT를 직접 만들 일은 드물어도, 원리를 알고 나면 성능 문제를 보는 눈이 달라져요. 자바 서버가 배포 직후 몇 분 동안 느린 워밍업 현상, JMH 같은 벤치마크 도구가 처음 몇 번의 결과를 버리는 이유, 자바스크립트 함수에 여러 타입의 객체를 번갈아 넘기면 느려지는 이유가 다 JIT 때문이거든요. 서버리스처럼 잠깐 실행되고 끝나는 환경에서 GraalVM 네이티브 이미지 같은 AOT(실행 전에 미리 컴파일하는 방식)를 고민하게 되는 것도 같은 이유예요.

마무리

한줄 정리: JIT는 자바가 처음 만든 기술이 아니라, 60년 넘게 다듬어진 ‘실행하면서 배우는 컴파일러’라는 아이디어예요.

실무에서 JIT 워밍업이나 탈최적화(deopt) 때문에 성능 문제를 겪어본 적 있으세요? 서버 애플리케이션에서는 앞으로 JIT와 AOT 중 어느 쪽이 대세가 될 거라고 보세요?


🔗 출처: Hacker News

SOURCE · HACKER NEWS
원문 전체 보기 → https://dl.acm.org/doi/10.1145/857076.857077
SHARE
NEXT · CHOOSE

변화를 읽었다면,
내가 만들 수익 구조를 고릅니다.

정보를 더 모으는 데서 멈추지 않고, 광고·외주·판매·중개·구독 중 내 상황에 맞는 출발점을 정해보세요.

21가지 수익 구조 살펴보기 →
처리 중...