들어가며
프로그래밍 언어는 코드를 실행하는 방식에 따라 크게 컴파일 언어와 인터프리터 언어로 나뉩니다.
이 글에서는 컴파일 언어가 무엇인지, Java는 어떤 방식으로 동작하는지 함께 정리해보겠습니다.
컴파일 언어란?
컴파일 언어는 소스 코드 전체를 컴파일러(Compiler) 가 한 번에 기계어(Machine Code) 로 번역한 뒤 실행하는 방식입니다.
[컴파일 언어 실행 과정]
소스 코드(.c) ──▶ 컴파일러 ──▶ 실행 파일(.exe) ──▶ 실행
(사람이 작성) (기계어로 번역됨)
대표적인 컴파일 언어로는 C, C++ 이 있습니다.
컴파일 언어의 특징
장점 - 실행 속도가 빠르다
컴파일 시점에 이미 기계어로 번역이 완료되어 있기 때문에, 실행할 때 별도의 번역 과정이 없습니다.
그래서 실행 속도가 매우 빠릅니다.
장점 - 컴파일 시 오류를 미리 확인한다
소스 코드 전체를 번역하는 과정에서 문법 오류, 타입 오류 등을 미리 발견할 수 있습니다.
실행 전에 오류를 잡을 수 있어 안정성이 높습니다.
소스 코드에 오류 있음
↓
컴파일 시도
↓
컴파일 오류 발생! ← 실행 전에 오류 확인 가능
↓
오류 수정 후 재컴파일
단점 - OS마다 실행 파일을 따로 만들어야 한다
컴파일된 기계어는 특정 운영체제(OS)와 CPU에 맞게 번역됩니다.
Windows에서 컴파일한 파일은 Linux나 Mac에서 실행할 수 없습니다.
플랫폼마다 별도로 컴파일해야 하는 불편함이 있습니다.
같은 소스 코드라도:
소스 코드
├── Windows용 컴파일 ──▶ .exe 파일 (Windows에서만 실행)
├── Linux용 컴파일 ──▶ 실행 파일 (Linux에서만 실행)
└── Mac용 컴파일 ──▶ 실행 파일 (Mac에서만 실행)
인터프리터 언어와의 비교
| 항목 | 컴파일 언어 | 인터프리터 언어 |
|---|---|---|
| 번역 방식 | 전체를 한 번에 기계어로 번역 | 한 줄씩 번역하며 실행 |
| 실행 속도 | 빠름 | 상대적으로 느림 |
| 오류 확인 | 실행 전 컴파일 시 확인 | 실행 중 해당 줄에서 확인 |
| 플랫폼 이식성 | 낮음 (OS마다 재컴파일 필요) | 높음 |
| 대표 언어 | C, C++ | Python, JavaScript |
Java는 어떤 방식일까?
Java는 순수한 컴파일 언어도, 순수한 인터프리터 언어도 아닙니다.
컴파일과 인터프리터를 혼합한 방식으로 동작합니다.
[Java 실행 과정]
소스 코드(.java)
↓
javac 컴파일러
↓
바이트코드(.class) ← 기계어가 아닌 중간 언어
↓
JVM (Java Virtual Machine)
↓
각 OS에 맞게 실행
Java는 기계어 대신 바이트코드(Bytecode) 로 컴파일합니다.
바이트코드는 특정 OS에 종속되지 않은 중간 언어입니다.
이 바이트코드를 각 OS에 설치된 JVM(Java Virtual Machine) 이 읽어서 실행합니다.
Java의 "Write Once, Run Anywhere"
Java의 가장 큰 특징은 한 번 작성하면 어디서든 실행된다는 점입니다.
바이트코드는 어떤 OS에서든 동일하고, JVM이 각 환경에 맞게 실행해주기 때문입니다.
같은 바이트코드(.class) 하나로:
바이트코드
├── Windows JVM ──▶ Windows에서 실행
├── Linux JVM ──▶ Linux에서 실행
└── Mac JVM ──▶ Mac에서 실행
C/C++처럼 OS마다 별도로 컴파일할 필요가 없습니다.
Java의 컴파일 오류 확인
Java도 컴파일 언어의 장점인 컴파일 시 오류 확인을 그대로 가집니다.javac로 컴파일할 때 문법 오류, 타입 오류 등을 미리 잡아줍니다.
// 타입 오류 - 컴파일 시 발견
int number = "hello"; // 컴파일 오류! int에 String 대입 불가
// 문법 오류 - 컴파일 시 발견
public void greet() {
System.out.println("안녕하세요") // 컴파일 오류! 세미콜론 없음
}
이처럼 실행 전에 오류를 발견할 수 있어 Python 같은 순수 인터프리터 언어보다 안정성이 높습니다.
JVM 덕분에 생기는 추가 장점
JVM은 단순히 바이트코드를 실행하는 것 외에도 여러 기능을 제공합니다.
JVM의 역할:
바이트코드 실행
+
메모리 관리 (가비지 컬렉터) ← 사용하지 않는 객체 자동 제거
+
JIT 컴파일러 ← 자주 실행되는 코드를 기계어로 캐싱해 속도 향상
+
플랫폼 독립성 보장
특히 JIT(Just-In-Time) 컴파일러 덕분에 초기에는 인터프리터 방식으로 실행하다가, 자주 호출되는 코드는 기계어로 변환해 캐싱합니다. 이 때문에 Java의 실행 속도는 순수 인터프리터 언어보다 훨씬 빠릅니다.
정리
- 컴파일 언어는 소스 코드 전체를 기계어로 번역한 뒤 실행하는 방식이다.
- 실행 속도가 빠르고 컴파일 시 오류를 미리 확인할 수 있다는 장점이 있다.
- OS마다 별도의 실행 파일을 만들어야 하는 이식성 문제가 있다.
- Java는 컴파일과 인터프리터를 혼합한 방식으로, 소스 코드를 기계어가 아닌 바이트코드로 컴파일한다.
- JVM이 바이트코드를 읽어 실행하기 때문에 OS에 상관없이 동일한 코드를 실행할 수 있다.
- JIT 컴파일러 덕분에 인터프리터 언어보다 빠른 실행 속도를 유지한다.
'-- 오늘 있었던 개발 일기' 카테고리의 다른 글
| 호이스팅(Hoisting)이란? (1) | 2026.04.15 |
|---|---|
| 인터프리터 언어란? (0) | 2026.04.13 |
| 매개변수(Parameter)란? (1) | 2026.04.11 |
| static 메서드란? - 객체 생성 없이 바로 호출 (0) | 2026.04.09 |
| 참조변수는 주소를 가져야 한다! (0) | 2026.04.08 |