[CS] 컴파일러, 인터프리터, 가상머신
[CS] 컴파일러, 인터프리터, 가상머신
컴파일러와 프로그램 생성 과정
컴파일러는 고급 프로그래밍 언어로 작성된 소스 코드를 기계어 또는 중간 코드로 변환하는 소프트웨어입니다.
컴파일러의 주된 역할은 코드 변환, 최적화, 오류 검출 등을 통해 컴퓨터가 실행할 수 있는 프로그램을 생성하는 것입니다.
컴파일러란?
컴파일러(Compiler) 는 소스 코드를 기계어로 변환하여 실행 파일을 생성하는 프로그램입니다.
- 사람 친화적인 고급 언어를 컴퓨터 친화적인 저급 언어로 변환합니다.
- 주로 C, C++, Rust, Fortran 같은 언어에서 사용됩니다.
컴파일러의 역할
- 코드 변환: 고급 언어를 저급 언어(기계어, 어셈블리어 등)로 변환합니다.
- 코드 최적화: 코드 실행 속도와 메모리 사용 효율을 개선합니다.
- 오류 검출: 구문 오류나 타입 오류를 컴파일 시점에 감지합니다.
- 이식성 확보: 소스 코드를 다양한 플랫폼에서 사용할 수 있도록 변환합니다.
인터프리터란?
인터프리터(Interpreter) 는 소스 코드를 한 줄씩 읽어서 바로 실행하는 소프트웨어입니다.
- 컴파일러와 달리 기계어로 변환하지 않고 직접 실행합니다.
- 주로 Python, Ruby, JavaScript 같은 스크립트 언어에서 사용됩니다.
인터프리터의 역할
- 실행 시간 해석: 소스 코드를 한 줄씩 해석하여 즉시 실행합니다.
- 즉시 피드백: 코드 변경 후 바로 실행 결과를 확인할 수 있습니다.
- 동적 특성 반영: 런타임에 변수 타입이 결정되므로 유연성이 높습니다.
인터프리터의 특징
- 장점: 코드 수정 후 바로 실행 가능, 디버깅이 용이
- 단점: 실행 속도가 느림, 코드 전체를 미리 분석하지 않음
가상 머신 기반 언어 (C# 등)
C#과 같은 언어는 가상 머신(Virtual Machine) 을 통해 실행됩니다.
가상 머신은 중간 코드(바이트코드) 를 해석하거나 JIT(Just-In-Time) 컴파일로 기계어로 변환하여 실행합니다.
C# 컴파일 과정
- 컴파일: C# 코드를 IL 코드(Intermediate Language) 로 변환
1
csc Program.cs -o Program.exe - JIT 컴파일: 실행 시점에 IL 코드를 기계어로 변환하여 실행
- 런타임 관리: .NET 런타임(CLR)이 메모리 관리, 가비지 컬렉션 등을 처리
가상 머신 기반의 장점
- 플랫폼 독립성: 동일한 바이트코드가 다양한 플랫폼에서 실행 가능
- 런타임 최적화: 실행 중에도 코드 최적화 가능
- 메모리 관리: 가비지 컬렉션을 통해 메모리 누수 방지
단점
- 성능 저하: JIT 컴파일로 인한 초기 지연
- 런타임 의존성: 가상 머신이 설치되어 있어야 실행 가능
컴파일러 vs 인터프리터 vs 가상 머신
| 특성 | 컴파일러 | 인터프리터 | 가상 머신 (JIT) |
|---|---|---|---|
| 실행 속도 | 빠름 (기계어로 변환되어 실행) | 느림 (코드를 한 줄씩 해석하며 실행) | 느림 (JIT 컴파일로 인한 초기 지연) |
| 컴파일 시점 | 빌드 시점에 변환 | 실행 중에 한 줄씩 변환 | 실행 시점에 변환 |
| 플랫폼 독립성 | 플랫폼마다 별도 컴파일 필요 | 플랫폼 독립적 (해석기 필요) | 플랫폼 독립적 (바이트코드 실행) |
| 오류 검출 | 컴파일 시점에 대부분 오류 발견 | 실행 중에 오류 발견 | 실행 중에 오류 발생 가능 |
| 코드 최적화 | 정적 최적화 | 거의 없음 | 동적 최적화 (실행 중에 최적화 가능) |
| 예시 언어 | C, C++, Rust | Python, JavaScript, Ruby | C#, Java |
프로그램 생성 과정 (C/C++ 기준)
- 소스 코드 작성: 코드 작성 (예:
main.cpp) - 전처리: 매크로와 헤더 파일 처리 (파일 확장자:
.i)1
g++ -E main.cpp -o main.i
- 컴파일: 어셈블리 코드로 변환 (파일 확장자:
.s)1
g++ -S main.i -o main.s
- 어셈블: 기계어 코드로 변환 (파일 확장자:
.o)1
g++ -c main.s -o main.o
- 링킹: 라이브러리 결합 후 실행 파일 생성
1
g++ main.o -o main
결론
컴파일러와 인터프리터는 소스 코드를 실행 가능하게 만드는 방식이 다릅니다.
- 컴파일러는 실행 전에 기계어로 변환하여 빠르게 실행되지만, 컴파일 시간이 필요합니다.
- 인터프리터는 한 줄씩 해석하여 즉시 실행할 수 있지만, 속도가 느리고 오류 검출이 늦습니다.
- 가상 머신 기반 언어(C#, Java) 는 중간 코드(바이트코드) 를 생성하고, 실행 시점에 JIT 컴파일하여 실행하므로 동적 최적화가 가능합니다.
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.