[Java] 자바는 왜 컴파일과 인터프리터를 함께 사용할까?

Woomin Wang ·2025년 3월 24일

[Java]

목록 보기
5/10
post-thumbnail

프로그래밍 언어로 작성된 소스 코드는 컴퓨터가 직접 이해할 수 없기 때문에 기계어로 변환해야 한다. 이 변환 과정에서 사용되는 방식이 컴파일러(Compiler)인터프리터(Interpreter) 두 가지다.

컴파일러는 전체 코드를 한 번에 번역하는 방식이고, 인터프리터는 한 줄씩 즉시 변환하여 실행하는 방식이다. 쉽게 비유하면, 컴파일러는 문서를 번역하는 번역가, 인터프리터는 실시간으로 말을 통역하는 통역사와 비슷하다.

컴파일러(compiler)

  • 전체 소스 코드를 한 번에 기계어로 변환하여 실행 파일을 생성
  • 변환이 끝난 후 실행되므로 실행 속도가 빠름
  • 대표적인 언어: C, C++ 등

인터프리터(interpreter)

  • 소스 코드를 한 줄씩 즉시 변환하여 실행
  • 실행 도중에 변환이 이루어져 유연하지만 실행 속도가 느림
  • 대표적인 언어: Python, JavaScript 등

자바와의 연관성

자바는 컴파일러와 인터프리터의 특징을 모두 가지는 하이브리드 방식을 사용한다.

자바의 실행 과정

  1. 컴파일 단계
    자바 소스 코드(.java)javac(자바 컴파일러)를 사용하여 바이트코드(.class)로 변환한다. 하지만 이 바이트코드는 운영체제가 직접 실행할 수 없으며, JVM이 해석해야 한다.

  2. 인터프리터 단계 + JIT 컴파일
    JVM은 변환된 바이트코드를 한 줄씩 읽으며 실행한다.
    즉, 이 단계에서 JVM이 인터프리터 방식으로 코드를 실행한다.

하지만 바이트코드를 한 줄씩 해석하면 속도가 느려지므로, JVM은 JIT(Just-In-Time) 컴파일러를 함께 사용해 실행 속도를 최적화한다. JIT 컴파일러는 반복 실행되는 코드를 기계어로 변환하여 캐싱하고, 이후에 컴파일된 기계어를 직접 실행한다.

JVM이 인터프리터 방식을 사용하는 이유

1. 운영체제의 독립성 유지

C언어의 경우, 소스 코드를 gcc로 컴파일하여 OS에 맞는 실행 파일을 생성한다. 예를 들어, 리눅스에서는 .out, 윈도우에서는 .exe 파일이 만들어진다. 즉, OS마다 별도의 빌드 작업이 필요하며, 한 번 작성한 코드라도 다른 OS에서 실행하려면 다시 컴파일해야 한다.

반면, Java는 Write Once, Run Anywhere를 목표로 하기 때문에, 바이트코드가 어떤 운영체제에서도 실행될 수 있어야한다. 즉, 운영체제와 관계 없이 실행할 수 있도록, JVM이 바이트코드를 각 OS에 맞게 해석하여 실행한다. JVM이 실행 파일을 컴파일하여 미리 만들면, 각 OS에 맞는 별도의 실행 파일을 만들어야 하고, 그럴 경우 자바 프로그램은 OS에 종속적이게 되어, 자바의 운영체제 독립성을 유지할 수 없게 된다.

2. 실행 중 동적 로딩 및 유연한 실행 환경 제공

자바는 실행 중에 필요한 클래스만 동적으로 로딩하는 방식을 사용한다. 만약 JVM이 전체 코드를 한 번에 기계어로 변환하면, 사용되지 않는 코드까지 미리 변환해야 하므로 메모리 낭비가 발생하고, 실행 중 동적 로딩도 불가능해진다.

3. 즉각적인 실행 가능

컴파일 방식은 전체 코드를 변환한 후 실행 하므로, 실행 파일을 생성할 때 시간이 오래 걸린다. 하지만, 인터프리터 방식은 소스 코드를 미리 모두 변환하지 않고 실행 시점에 한 줄씩 해석하기 때문에, 프로그램을 빠르게 실행할 수 있다.

4. JIT 컴파일러와 함께 사용하여 성능 최적화

JVM은 초반에는 인터프리터 방식으로 빠르게 실행하고, 반복 실행되는 코드만 JIT 컴파일러가 기계어로 변환하여 최적의 성능을 낼 수 있도록 한다.

profile
Backend Developer

0개의 댓글