컴파일 언어는 보통 source code를 실행 전에 machine code나 bytecode 같은 형태로 번역합니다. 인터프리터 언어는 실행 시점에 코드를 읽고 해석하면서 실행하는 방식에 가깝습니다.
다만 현실의 언어 구현은 섞여 있는 경우가 많습니다. Python도 .py를 bytecode로 컴파일한 뒤 VM이 실행하고, JavaScript engine도 JIT compilation을 사용합니다. 그래서 언어 자체보다 구현 방식과 실행 모델을 함께 보는 것이 정확합니다.
Bytecode는 source code와 machine code 사이의 중간 표현입니다. Python이나 Java처럼 VM이 실행하는 형태로 만들면 platform 차이를 어느 정도 숨기고 실행할 수 있습니다.
컴파일러와 인터프리터의 핵심 차이는?
컴파일러는 source code 전체를 다른 형태로 번역한 결과물을 먼저 만들고, 이후 그 결과물을 실행합니다. 인터프리터는 source code나 중간 표현을 줄 단위로 읽고 즉시 실행합니다. 번역과 실행을 분리하느냐, 동시에 하느냐의 차이입니다.
JIT는 무엇인가요?
Just-In-Time compilation은 실행 중에 자주 실행되는 코드를 native code로 컴파일해 성능을 높이는 기법입니다.
컴파일 언어가 항상 더 빠른가요?
항상 그렇지는 않습니다. 컴파일 최적화가 유리한 경우가 많지만, JIT, runtime 최적화, I/O 병목, 구현 품질에 따라 실제 성능은 달라집니다.
AOT vs JIT의 차이는?
AOT(Ahead-Of-Time)는 실행 전에 미리 native code로 컴파일합니다. 시작 속도가 빠르고 예측 가능한 성능을 냅니다. JIT(Just-In-Time)는 실행 중 자주 실행되는 코드를 런타임에 컴파일해 최적화합니다. 런타임 정보를 활용한 최적화가 가능하지만 워밍업 시간이 있습니다.
V8 엔진은 어떻게 JavaScript를 실행하나요?
V8은 JavaScript를 파싱해 AST를 만들고, Ignition 인터프리터가 bytecode를 생성해 실행합니다. 자주 실행되는 함수는 TurboFan JIT 컴파일러가 최적화된 machine code로 컴파일합니다. 실행 중 타입 정보가 바뀌면 deoptimization이 일어나 다시 bytecode로 되돌아갑니다.
Java의 JVM은 컴파일러인가요, 인터프리터인가요?
둘 다입니다. javac가 .java를 bytecode(.class)로 컴파일합니다. JVM은 처음에는 bytecode를 인터프리터로 실행하고, 자주 실행되는 코드는 JIT 컴파일러(HotSpot)가 native code로 컴파일합니다. 컴파일과 인터프리터 방식이 혼합된 대표적 예시입니다.
부가 설명
컴파일 방식은 초기 번역 비용이 있지만 실행 최적화에 유리할 수 있습니다. 인터프리터 방식은 실행과 실험이 편하지만 runtime overhead가 있을 수 있습니다.
현대 런타임은 단순히 “C는 컴파일, Python은 인터프리터”로만 나뉘지 않습니다. bytecode, VM, JIT처럼 중간 형태와 최적화 단계가 섞이는 경우가 많습니다.
한 줄 정리
컴파일 방식은 실행 전에 코드를 다른 형태로 번역하고, 인터프리터 방식은 실행 시점에 코드를 해석하며 실행합니다.