0. 개요
🤔 JAVA는 Interpreter를 사용하는 언어라고 하고, C는 Compiler를 사용하는 언어라고 한다.
🤔 그렇다면 컴파일과 인터프리테이션의 차이가 무엇일까?
// 이후 글에서 Compilation과 Interpretation 영어를 그대로 사용하겠다. 한글로 정확한 번역이 어렵다고 생각된다.
1. Compilation vs. Interpretation
- Compilation과 Interpretaion은 서로 반대 개념이 아니다.
- 둘 사이에 명확한 구분을 하기 힘들다.
1-1. Pure Compilation
컴파일러(Compiler)는 high-level의 원본 프로그램을 target program으로 번역하는 역할을 한다.
사용자는 나중에 운영 체제(OS)에게 target program을 실행하도록 지시한다.
컴파일러는 컴파일 중에 주체적으로 동작하며, 번역된 목표 프로그램이 실행될 때는 컴파일러는 관여하지 않는다.
또한 완벽한 컴파일러는 코드의 의미와 의도를 깊이 이해해야 한다.
단순한 패턴 매칭과 전처리만 하는 것이 아니라 코드의 의미를 분석하고 번역해야 한다.
// semantic 문맥 <-> Syntax 문법 ; 즉 문법적으로 맞는 번역뿐만 아니라 문맥으로도 정확한 번역이 필요하다.
* target Program (목표 프로그램) : C, 어셈블리어, 기계어 등. 일반적으로 기계어
1-2. Pure Interpretation
Interpreter는 프로그램의 실행 중에 계속해서 존재한다.
프로그램이 실행될 때 해석기는 제어권(Control)을 가지며 실행을 지속적으로 관리한다.
해석기는 가상 머신처럼 동작하며, 소스 코드를 해석하고 해당 코드를 실행한다.
1-3. 둘의 차이점
Compilation과 Interpretation의 핵심 차이는 "제어권(Control)"이다.
Compiler는 번역 단계에서 제어권을 가지며, 번역된 목표 프로그램이 실행될 때는 제어권을 가지지 않는다.
반면 Interpreter는 실행 중에 계속해서 제어권을 유지하며 소스 코드를 해석하고 실행한다.
2. Interpretation의 특징
- 유연하고 검증(debug) 하기 좋다. / source code가 바로 실행되기 때문
- input data에 따라 타입과 크기가 결정된다.
- Lisp, Prolog등의 언어는 Interpreter가 아니면 구현하기 힘들다.
- run time(실행시점)때 target language(보통 기계어)로 번역
즉, 모든 변수의 타입 확정이 실행시간까지 지연된다는 뜻이다. = 동적 타이핑 (dynamic typing)
-> late Binding
3. Compilation의 특징
- 성능이 훨씬 좋다.
- 번역된 target program을 실행하기만 하면 되기 때문에 실행이 훨씬 빠르다.
4. 오늘날의 언어는 무엇을 많이 사용하는가?
현대의 프로그래밍 언어들은 위의 두 방식을 혼합하여 사용하고,
사실 compilation과 interpretation의 구분도 모호하다.
하지만 명확한 차이점을 보이는 부분이 분명 존재한다.
1. 전반적인 분석 과정
- compilation : 고수준 소스 코드를 목표 프로그램(보통 기계어)으로 번역하는 과정에서 모든 코드를 한 번에 분석.
- interpretation : 소스 코드를 한 줄씩 읽고 실행시킴. 동적으로 분석 / 해석
2. 변환되는 부분
- compilation : 이 변환은 소스 코드와 목표 코드 간에 큰 유사성이 없다. ... 변경되는 부분이 크다.
- interpretation : 명시적인 변환 없이 소스 코드를 실행한다.
5. Preprocessor (전처리기)
전처리기(Preprocessor)는 많은 interpreted language에서 사용되며,
소스 코드를 더 효율적으로 해석하기 위해 초기 변환을 수행하는 도구이다.
// 나중에 더 자세히 배우겠지만 간단히 어떤 역할을 하는지 알아보자.
- 주석 및 공백 제거
- 토큰화(Tokenization) : 문자의 토큰화를 의미한다 ex. 키워드, 식별자, 숫자 및 기호 등이 될 수 있다
- macro assembler 형태로 축약어를 확장.
- 반복문, 서브루틴과 같은 제어 구조 식별 (High-Level Structure Identification)
전처리기는 해석형 언어에서 코드의 초기 처리를 담당하며, 소스 코드를 더 이해하기 쉽고 실행하기 효율적인 형태로 변환한다.
6. Fotran 언어의 구현
Fortran 언어는 pure한 compliation에 가까운 전형적인 언어이다.
Fortran 언어의 구현 방법을 알아보자.
1. Fortran 소스 코드 변환
- 중간 단계의 기계 코드로 번역 (완전한 실행 파일은 아님)
2. 라이브러리 의존성
- 프로그램에 필요한 부분 외에도 수학 함수나 입출력(I/O)과 관련된 서브루틴과 같은 라이브러리를 사용한다.
- 이러한 라이브러리는 원래 프로그램의 일부가 아니며, 컴파일러와 함께 제공된다.
3. 링커 (Linker)
- 링커는 컴파일된 중간 코드와 라이브러리를 병합하여 최종 실행 가능한 프로그램을 생성한다.
_여러 C file을 붙여서 실행 file로 만드는 것과 비슷하다._C언어의 컴파일러
7. C언어 Compiler
Compiler와 Preprocessor(전처리기)가 따로 존재
: 주석 제거, 매크로 확장, 조건부 컴파일 등의 작업을 수행한다.
7-1. conditional compilation(전처리문 예시)
/* #define ADD 1 */
#define MIN 0
int main(void) {
int num1, num2;
printf("두 개의 정수 입력: ");
scanf("%d %d", &num1, &num2);
#ifdef ADD /* ADD가 정의되었다면 */
printf("%d + %d = %d\n", num1, num2, num1 + num2);
#endif
#ifdef MIN /* MIN이 정의되었다면 */
printf("%d - %d = %d\n", num1, num2, num1 - num2); #endif
return 0;
}
제공된 코드 예제는 ADD
와 MIN
매크로를 정의하고 해당 매크로의 정의 여부에 따라 코드 블록을 컴파일하거나 제외하는 방법을 보여준다. 각 매크로는 0 또는 1의 값을 가지고 있으며, 이 값은 해당 코드 블록의 컴파일 여부를 결정한다.
ADD
매크로가 정의되어 있지 않으므로#ifdef ADD
블록은 컴파일되지 않는다.MIN
매크로는 0으로 정의되어 있으므로#ifdef MIN
블록은 컴파일된다.
따라서 위의 코드는 MIN
블록만 컴파일되고 실행된다.
8. 인터프리트 언어의 컴파일
컴파일러는 소스 코드를 번역하면서 실행 시간에 결정되는 여러 가정(assumptions)을 사용하며,
이러한 가정이 실행 시간에 유효한 경우에는 빠른 실행이 가능하고,
그렇지 않은 경우에는 동적 검사를 통해 가정을 확인하게 된다. (dynamic check가 interpreter로 돌아간다)
9. Dynamic and Just-in-Time 컴파일
프로그래밍 시스템 중 컴파일을 가능한 한 미루는 경우가 있다. ex. Java or C#
프로그램을 실행하는 시점(runtime)에 필요한 부분을 실시간으로 컴파일 하는 방법이다. (Dynamic Compilation)
예를 들어, Lisp나 Prolog은 코드를 최적화하거나 새로 생성된 소스 코드를 머신 코드로 번역하기 위해 컴파일러를 필요할 때 호출할 수 있다.
이 컴파일러는 똑같은 코드를 매번 해석하지 않고,
처음 실행시 자주 쓰이는 코드를 cache에 넣어 놓은 후, 이 cache code를 사용하기 때문에 더욱 빠른 실행이 가능하다.
10. Java Compiler
자바 언어는 머신에 독립적인 중간 형태로 "바이트 코드(byte code)"를 정의한다.
초기 자바 구현은 byte-code interpretes를 사용했지만,
최근에는 프로그램 실행 직전에 bytecode를 machine language로 즉시 번역하는 "Just-in-Time 컴파일러"를 사용한다.
11. 마이크로코드(microcode)
기계어를 상대적으로 쉽게 추가하도록 만들어주는 방식.
하드웨어 실행되는 low-level 명령어 집합이다.
12. 비전통적인 컴파일러
1. 텍스트 포매터 (Text Formatters) ex. TeX, troff, Postscript (마크다운, 엑셀 등도 하나의 언어로 보는 이유이다.)
2. 실리콘 컴파일러 (Silicon Compilers)
3. 쿼리 언어 프로세서 (Query Language Processors) : SQL과 같은 데이터베이스 쿼리 언어를 파일에 대한 기본 작업으로 변환