컴파일 언어와 인터프리터 언어란?
컴파일 언어(Compiled Language)
- 특징:
- 소스코드를 한 번에 전체를 기계어(목적 코드)로 번역 (컴파일러)
- 결과물이 독립적인 실행 파일(exe, out, etc)
- 장점:
- 실행 속도 빠름(이미 기계어로 변환됨)
- 코드 보안성↑ (소스 노출 없음)
- 예시: C, C++, Go, Rust
인터프리터 언어(Interpreted Language)
- 특징:
- 소스코드를 한 줄씩 또는 한 명령씩 읽고 즉시 실행 (인터프리터)
- 결과물이 별도의 목적 파일 없이 바로 실행
- 장점:
- 개발/테스트가 편리함(즉각적 실행, REPL 지원)
- 플랫폼 독립성(인터프리터만 있으면 어디서나 실행)
- 예시: Python, Ruby, JavaScript
차이 요약표
| 항목 | 컴파일 언어 | 인터프리터 언어 |
|---|
| 실행 전 처리 | 전체 코드 컴파일 (번역) | 한 줄씩 바로 실행 |
| 산출물 | 바이너리(exe 등) 생성됨 | 없음 (소스 코드 직접 실행) |
| 실행 속도 | 보통 더 빠름 ⚡ | 보통 느림 🐢 |
| 에러 발견 시점 | 컴파일 시 | 실행 중 |
| 예시 | C, C++, Java (→ 바이트코드로 컴파일됨) | Python, JavaScript, Ruby |
"한 줄씩 실행"의 의미: 해석주의 오해
컴파일 언어도 런타임에는 결국 한 줄씩 실행되긴 한다.
- 하지만 그건 CPU가 기계어 명령어를 처리할 때 얘기고,
- 컴파일러는 전체 코드를 미리 분석해서 바이너리로 바꿔놓습니다.
- 따라서 실행 시점엔 "해석"이 아니라 "실행만" 합니다.
한 줄 요약
컴파일 언어는 미리 전체를 번역해서 "기계어 코드"로 실행하고,
인터프리터 언어는 코드 한 줄 한 줄을 실행 시점에서 "즉석 번역"해서 수행합니다.
둘 다 최종적으로는 "한 줄씩 CPU가 실행"하지만 준비 방식과 실행 주체가 다릅니다.
Java의 컴파일러적 + 인터프리터적 특성
Java의 “컴파일” 과정
- Java는 소스코드(.java)를 작성하면,
→ javac(컴파일러)가 바이트코드(.class)로 변환합니다.
- 이 과정에서 모든 소스코드가 한 번에 변환되므로,
→ 컴파일 언어의 특성을 가집니다.
Java의 “인터프리터”적 실행
- 실행 시, JVM이 바이트코드(.class)를
→ 한 줄씩 읽어서 실행(인터프리터 방식)합니다.
- 즉, 바이트코드는 OS별 기계어가 아니고, JVM만 읽을 수 있음
- 이 때문에 플랫폼 독립성이 확보됨 (WORA, Write Once Run Anywhere)
JIT(Just-In-Time) 컴파일러
- 성능 향상을 위해, JVM은 실행 중(런타임에) 자주 실행되는 바이트코드(핫스팟)를
→ JIT 컴파일러로 즉시 기계어로 변환하여 캐시하고,
→ 이후에는 네이티브 기계어로 빠르게 실행함
- 즉, 실행 시에는 인터프리터+컴파일 언어의 하이브리드가 됨
Java의 특성: 컴파일 언어 vs 인터프리터 언어
| 항목 | Java의 특성 |
|---|
| 소스코드 변환 방식 | 컴파일러(javac)로 바이트코드(.class) 생성 |
| 실행 방식 | JVM이 바이트코드를 인터프리트, JIT로 컴파일 |
| 플랫폼 독립성 | 바이트코드 + JVM 조합으로 OS 무관 실행 |
| 성능 | 인터프리트보다 빠름, 네이티브만큼 빠르기도 함 |
| 보안성 | 소스노출 X, 바이트코드 리버싱은 가능 |
| 즉시 실행/테스트 | 일부 REPL(Java 9 jshell), 주로 전체 컴파일 필요 |