컴파일러란?

컴파일러란 무엇일까?
컴파일러는 개발자라면 무조건 들어봤을 용어이다. 컴파일러를 단순히 실행 코드를 만들어주는 프로그램이라고 이때까지 생각했었다. 하지만 컴파일러를 더욱 정확하게 말한다면 다음과 같이 설명할 수 있다.
컴파일러(Compiler)란 개발자가 작성한 고급 언어(C, Java, Python 등) 로 된 프로그램을 컴퓨터가 이해할 수 있는 저급 언어(기계어 또는 어셈블리어) 로 번역(translate) 해주는 프로그램이다.
개발자가 작성한 코드는 그대로는 컴퓨터가 이해하지 못한다. 그래서 컴파일러가 이 코드를 읽고, 구문 분석(syntax analysis) 과 의미 분석(semantic analysis) 등을 거쳐 기계어 코드로 변환한다. 이때 컴파일러는 단순히 코드를 변환하는 것에 그치지 않고, 프로그램의 문법 오류를 검사하고, 최적화 과정을 거쳐 실행 효율을 높인 목적 코드를 생성하기도 한다.
즉, 컴파일러는 개발자가 작성한 인간 친화적인 언어를 컴퓨터 친화적인 언어로 바꾸어 프로그램이 실제로 동작할 수 있도록 해주는 중간 다리 역할을 수행한다고 볼 수 있다.
이렇게 만들어진 결과물(보통 실행 파일)은 이후 운영체제에서 바로 실행 가능하다.
// hello.c
#include <stdio.h>
int main() {
printf("Hello, world!");
return 0;
}
- 컴파일러(gcc, clang, javac 등)가 이 코드를 읽고 번역하면 hello.exe 같은 실행 가능한 기계어 프로그램이 생성된다.
컴파일러 정리
- 프로그램 전체를 읽고 분석한다
- 컴파일러는 한 줄씩 실행하지 않고, 소스 코드 전체를 한 번에 분석한다.
- 컴파일러는 한 줄씩 실행하지 않고, 소스 코드 전체를 한 번에 분석한다.
- 의미적으로 동등한(sementically equivalent) 프로그램을 다른 언어(보통 기계어) 로 변환(translate) 한다.
- 즉, 프로그램의 동작은 같지만 컴퓨터가 이해하고 실행할 수 있는 형태로 바꾼다.
- 즉, 프로그램의 동작은 같지만 컴퓨터가 이해하고 실행할 수 있는 형태로 바꾼다.
- 이렇게 변환된 프로그램은 더 쉽게 실행되거나, 더 효율적으로 동작하도록 만들어진다.
- 예를 들어, 속도를 높이거나 메모리 사용량을 줄이는 등 성능을 개선한다.
- 예를 들어, 속도를 높이거나 메모리 사용량을 줄이는 등 성능을 개선한다.
- 따라서 컴파일러는 단순한 번역기가 아니라, 프로그램을 “개선(improve)”하는 역할도 한다.
- 컴파일은 오프라인(offline) 과정이다. → 즉, 프로그램을 실행하기 전에 미리 컴파일 과정을 거친다.
- 마지막으로, 트레이드오프(trade-off) 가 존재한다. → 컴파일 과정에서 시간이 오래 걸릴 수 있지만(compile time overhead), 그 대신 실제 실행 시에는 훨씬 빠르고 효율적으로 동작한다(execution performance).
컴파일러 vs 인터프리터

그렇다면 인터프리터란 무엇일까?
인터프리터는 소스 코드를 한 줄씩 읽고, 즉시 해석하여 실행하는 프로그램이다. 즉, 컴파일러처럼 미리 전체 코드를 기계어로 변환해 실행 파일을 만드는 것이 아니라, 프로그램을 실행할 때마다 코드를 실시간으로 번역하고 수행한다.
이 때문에 실행 속도는 컴파일 방식보다 느릴 수 있지만, 코드를 수정하고 바로 실행해볼 수 있다는 장점이 있다.
대표적인 인터프리터 언어로는 Python, JavaScript, Ruby 등이 있다.
🌟정리🌟
Interpreter (인터프리터)
소스 프로그램을 읽어서, 그 프로그램을 즉시 실행하고 결과를 출력하는 프로그램이다. 즉, 한 줄 한 줄 해석하면서 바로 실행하는 방식이다.
Compiler (컴파일러)
한 언어(소스 언어)로 작성된 프로그램을 다른 언어(목표 언어)로 번역하는 프로그램이다.
| 구분 | 정적 스코프 (Static Scope) | 동적 스코프 (Dynamic Scope) |
| 결정 시점 | 컴파일 타임 | 실행 타임 |
| 기준 | 함수 정의 위치 | 함수 호출 위치 |
| 참조 방식 | 코드 구조(Lexical Structure) 기반 | 실행 순서(Call Stack) 기반 |
| 장점 | 예측 가능, 유지보수 용이 | 유연하지만 예측 어려움 |
| 대표 언어 | C, Java, Python, JavaScript | Lisp(초기), Bash, Perl(일부) |
| 예시 결과 | 항상 동일한 변수 참조 | 호출 위치에 따라 달라짐 |
컴파일러 구조 (Compiler Structure)

Scanner (어휘 분석기 / Lexical Analyzer)
- 소스 코드(Source Code) 를 문자 단위로 읽어서 토큰(Token) 으로 분리한다.
- 키워드(if, for), 식별자(x, num), 상수(42), 연산자(+, =) 등을 인식한다.
- 코드를 단어 단위로 쪼개는 단계라고 할 수 있다.
Parser (구문 분석기 / Syntax Analyzer)
- Scanner가 만든 토큰들의 구조를 검사하여 문법(Syntax) 이 맞는지 확인한다.
- 구문 트리(Syntax Tree)를 만들어 프로그램의 계층적 구조를 표현한다.
- if (x > 0) 형태가 올바른 문법인지 판별하는 것도 Parser의 역할이다.
Semantic Analyzer (의미 분석기)
- 문법적으로 맞더라도 의미가 맞는지 검사한다.
- 변수 타입, 선언 여부, 연산 가능 여부 등을 체크.
- int x;
- x = true; → 문법은 맞지만 타입이 달라 오류 발생한다.
Intermediate Code Generator (중간 코드 생성기)
- 의미 분석이 끝난 프로그램을 중간 코드(Intermediate Code) 형태로 변환한다.
- 기계에 독립적인 형태(3주소 코드, 중간 표현 IR)로 만들어 이식성을 높인다.
Optimizer (최적화기)
- 중간 코드를 더 효율적으로 개선(Optimization) 한다.
- 불필요한 연산을 제거하거나, 실행 속도를 빠르게 하는 방향으로 수정.
- x = x + 0 → x = x 로 단순화.
Code Generator (코드 생성기)
- 최적화된 중간 코드를 기계어(Object Code) 로 변환.
- 실제 컴퓨터에서 실행 가능한 저수준 명령어를 생성한다.
이렇게 만들어진 기계어(Object Code) 는 컴퓨터의 운영체제나 하드웨어가 직접 이해하고 실행할 수 있는 형태의 코드이다.
보통 이 단계에서 생성된 코드는 목적 파일(Object File) 로 저장되며, 이후 링커(Linker) 와 로더(Loader) 과정을 거쳐
하나의 완전한 실행 파일(Executable File) 로 만들어진다.
🔗참고 문헌: Compilers - Principles, Techniques, and Tools-Pearson_Addison Wesley (2006)
'{Lecture} > Compiler' 카테고리의 다른 글
| [컴파일러] 촘스키 언어 계층 정리 - 문법 정리 (0) | 2025.10.23 |
|---|---|
| [컴파일러] 컴파일러의 구조 (Front-End와 Back-End 구성과 역할) (0) | 2025.10.23 |
| [컴파일러] NFA -> DFA 변환 (0) | 2025.10.23 |
| [컴파일러] 3주차 Grammar Basic (0) | 2025.09.16 |
| [컴파일러] Programming Language Basics (0) | 2025.09.11 |