JIT 컴파일러와 일반 컴파일러의 차이를 알아보자

2025. 11. 14. 19:59·자바

0. 들어가며

최근 자바 공부를 하면서 JIT 컴파일러와  일반 컴파일러의 차이가  문득 궁금해졌습니다.

처음에는 단순히 실행 속도를 조금 더 빠르게 해주는정도로만 생각했지만 JVM 내부 구조와 JIT의 동작 원리를 이해하면 일반 컴파일러와의 차이가 훨씬 명확해진다는 것을 알게 되었습니다.
이번 글에서는 일반 컴파일러와 JIT 컴파일러의 차이, JIT의 동작 과정, 장점과 느낀 점까지  정리해보겠습니다.


1. 일반 컴파일러: 정적 최적화의 구조

C나 C++ 같은 전통적인 언어의 컴파일러는 소스 코드를 실행 전에 한 번에 기계어로 변환합니다.
즉  프로그램이 실행되기 전에 이미 CPU가 이해할 수 있는 형태로 변환되기 때문에 초기 실행 속도는 빠릅니다.

하지만 단점도 있습니다. 실행 환경에서 실제 코드가 어떻게 쓰이는지는 알 수 없기 때문에 조건문 분기나 반복문의 실제 실행 패턴을 반영한 최적화는 어렵습니다.

일반 컴파일러는 코드 구조와 흐름을 분석해 정적 최적화를 수행합니다. 예를 들어 인라인 처리, 루프 언롤링, 불필요한 코드 제거 같은 최적화는 가능하지만 실행 중 데이터 패턴을 기반으로 한 최적화는 불가능합니다.


2. JIT 컴파일러: 런타임 최적화

자바는 먼저 소스 코드를 바이트코드(.class 파일)로 변환한 후 JVM 위에서 실행됩니다.
여기서 JIT 컴파일러가 등장합니다. JIT는 실행 중인 바이트코드를 분석하여 필요한 부분만 기계어로 변환하고  런타임 정보를 기반으로 최적화를 수행합니다.

JIT는 초기에는 인터프리터처럼 바이트코드를 바로 실행하며 동시에 각 코드의 실행 경로와 호출 빈도를 수집합니다. 반복적으로 호출되는 메서드나 루프는 JIT가 자동으로 “핫스팟”으로 식별하고 그 부분을 기계어로 변환하여 성능을 높입니다. 필요하다면 최적화 과정을 반복하며 점점 더 효율적인 실행 코드를 만들어갑니다.

이 과정 덕분에 JIT는 단순히 정적 분석만으로는 얻을 수 없는 동적 최적화를 수행할 수 있습니다. 


3. 구조적·철학적 차이

일반 컴파일러는 실행 전에 가능한 모든 정보를 분석해 코드를 준비하는 정적 최적화에 초점을 둡니다. 반면 JIT는 실행 환경을 관찰하며 필요한 부분만 최적화하는 동적 최적화를 지향합니다.

이 철학의 차이는 기계어 코드 생성 방식에서도 나타납니다. 일반 컴파일러는 전체 프로그램을 기계어로 변환해 실행 파일을 만들지만 JIT는 처음에는 인터프리터로 실행하다가 실제로 자주 쓰이는 코드만 기계어로 변환하여 CPU 캐시에 적재합니다. 필요 없는 코드는 변환하지 않으며 오래된 코드나 잘 사용되지 않는 코드는 GC로 정리하기도 합니다. 이런 방식 덕분에 JIT는 메모리 효율까지 고려할 수 있습니다.

또한, 실행 모델 자체가 다릅니다. 일반 컴파일러는 완성된 실행 파일을 OS가 그대로 실행하는 구조(Ahead-of-Time)인 반면, JIT는 인터프리터가 먼저 실행하고 런타임 데이터를 수집하며, 그 정보를 바탕으로 기계어를 생성하고 최적화를 반복하는 구조입니다. 


4. 마치며

처음에는 JIT를 단순히 실행 속도를 높이는 도구 정도로 생각했지만 공부하면서 그 역할이 훨씬 더 정교하다는 것을 알게 되었습니다.

특히 반복해서 실행되는 코드를 스스로 찾아서 최적화한다는 점이 인상깊었습니다. 사실 성능 문제나 JVM 최적화라는 건 먼 이야기 같았는데 JIT를 이해하고 나니까 “아, 프로그램이 실행될 때 JVM이 이렇게 코드를 관리하고 있구나”라는 감이 조금 잡히더라고요.

저작자표시 비영리 (새창열림)

'자바' 카테고리의 다른 글

[JVM 완전정복 #3] Runtime Data Area 완전분석: 메모리 구조와 각 영역 역할  (0) 2025.11.17
[JVM 완전정복 #2] 자바 프로그램의 첫 관문 - 클래스로더  (0) 2025.11.17
Java Class 하위에 변수를 몇개까지 선언할 수 있을까?  (0) 2025.11.11
[JVM 완전정복 #1] JVM 구성요소 총정리: 가상 머신이 자바 코드를 실행하는 비밀  (0) 2025.11.11
프로그래밍 언어의 시작 – 고급어와 저급어의 이해  (0) 2025.11.04
'자바' 카테고리의 다른 글
  • [JVM 완전정복 #3] Runtime Data Area 완전분석: 메모리 구조와 각 영역 역할
  • [JVM 완전정복 #2] 자바 프로그램의 첫 관문 - 클래스로더
  • Java Class 하위에 변수를 몇개까지 선언할 수 있을까?
  • [JVM 완전정복 #1] JVM 구성요소 총정리: 가상 머신이 자바 코드를 실행하는 비밀
깊은바다속꼬북이
깊은바다속꼬북이
  • 깊은바다속꼬북이
    CodeBlossom
    깊은바다속꼬북이
  • 전체
    오늘
    어제
    • 분류 전체보기 (53) N
      • 라이징 캠프 (4)
      • 객채지향 개발론 (3)
      • 스프링 (10) N
      • 네트워크 (2)
      • 자바 (16)
      • 자료구조 (3)
      • 운영체제 (0)
      • 데이터베이스 (4)
      • 디자인패턴 (7)
      • JSP (1)
      • 개발 알쓸신잡 (2)
      • 일반 교양 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    자바 Socket 클래스
    MySQL 옵티마이저
    JVM
    어댑터 패턴(Adapter Pattern)
    템플릿 메서드 패턴(Template Method Pattern)
    mockito라이브러리
    자료구조
    전략 패턴(Strategy Pattern)
    GC
    디자인 패턴
    프로그램밍 언어
    개발 교훈
    객체지향
    java 버전별 특징
    백엔드
    MySQL 파서
    디자인패턴
    한국어 검색
    개발자 철학
    spring
    java
    스프링
    jvm 클래스 로더
    jit-compiler
    junnit5프레임워크
    JUnnit5
    java data area
    트랜잭션 전파레벨
    싱글턴 패턴(Singleton Pattern)
    개발 철학
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
깊은바다속꼬북이
JIT 컴파일러와 일반 컴파일러의 차이를 알아보자
상단으로

티스토리툴바