✍ 우리는 C언어로 컴퓨터 안에서 우리가 힘들게 만든 작품을 눈으로 보기 위해 코드 에디터에서 컴파일이라는 과정을 거치게 된다. 어떻게 고작 문자 몇줄이 이렇게 복잡한 컴퓨터 안에서 우리가 원하는 주문을 하나도 빠뜨리지 않고 정확하게 표현이 가능한걸까?

⛳컴파일이란?
인간이 이해 가능한 언어로 작성된 코드를 컴퓨터(CPU)가 이해할 수 있는 언어로 번역하는 작업
가장 많이 혼동될 수 있는 것이 컴파일과 빌드인데, 컴파일은 소스코드를 바이너리 파일로 만드는 행위 자체를 말하는 것이고, 빌드는 소스코드로 실행 파일을 만드는 과정 전체를 포괄하는 개념이다.
⛳ Frist, 전처리(Preprocessing) 과정
소스 코드 파일(.c | .cpp)을 전처리된 소스코드 파일(*.i)로 변환하는 과정
해당 작업에서의 대표적인 역할로는 헤더 파일에 있는 내용들을 현재 우리 소스코드에 들어오게 한다. 대표적인 전처리기 명령어는 #include와 #define이 있는데, #include는 영어 뜻 그대로 헤더 파일을 우리 소스 코드에 포함 시킬 때 사용하고, #define은 상수나 함수를 문자로 정의시킬 때 사용한다. 또한 프로그램 실행과 상관없는 주석을 제거한다.
전처리 과정을 하나 예로 들자면 우리가 C언어로 코드를 작성할 때, #include <stdio.h> 로 stdio.h 라는 헤더 파일을 정의한다. 여기서 stdio.h에 있는 함수들을 우리 소스 코드 파일로 불러오는 전처리 과정을 하는 것이다
⛳Second, 컴파일(Compile) 과정
전처리된 소스코드 파일을 컴파일러를 이용하여 어셈블리어 파일(*.s)로 변환하는 과정
여기서부터 본격적으로 고급 언어를 저급 언어(기계어)로 변환 시키는 역할을 시작하게 된다.
- 어휘 분석 (Lexical Analysis)
- 소스코드를 의미 있는 최소 단위인 토큰(Token)으로 쪼갠다.
- 예를 들어 int a = 10; 이라는 코드가 있다면 int(키워드), a(식별자), =(연산자) 등으로 각각 분리한다.
- 구문 분석 (Systax Analysis)
- 쪼개진 토큰들이 문법적으로 맞게 배열되었는지 확인한다.
- 여기서 추상 구문 트리(AST, Abstract Syntax Tree) 자료 구조를 생성하여 이 명령어가 실행 가능한 구조인지 판단한다.
- "Syntex Error" 는 여기서 발생한다.
- 의미 분석 (Semantic Analysis)
- 타입 체크를 통해 의미상 오류가 없는지 확인한다.
- 필요하다면 암시적 형 변환을 처리한다.
- 중간 코드 생성 (Intermedia Code Generation)
- CPU 아키택처에 종속되지 않는 중간 형태의 코드(IR) 을 생성한다.
- 수월한 최적화를 위해 중간 코드를 거쳐서 어셈블리어로 변환한다.
- 최적화 및 코드 생성 (Optimization & Code Generation)
- 쓰이지 않는 변수를 제거하거나, 반복문 안의 계산을 밖으로 빼는 등 효율성을 높인다.
- 최종적으로 타겟 CPU가 이해할 수 있는 어셈블리어로 변환
⛳Third, 어셈블리(Assembly) 과정
어셈블리어 파일(.s)를 오브젝트 파일(.o)로 변환하는 과정
여기서 오브젝트 파일(Object File)이란 어셈블리 코드를 더 이상 사람이 알아볼 수 없는 기계어로 변환시켜 만들어진 파일을 말한다. 이 파일은 어셈블리 코드의 명령어(Instruction)와 데이터(Data)가 들어있는데, 윈도우의 경우 PE 포맷, 리눅스의 경우 ELF 바이너리 포맷의 구조체를 갖게 된다.
해당 과정은 4번째 과정인 링킹 과정에서 명령어와 데이터를 구분시켜 효과적으로 각 바이너리 정보를 파악하기 위해서 하는 것이다.
⛳Fourth, 링킹(Linking) 과정
링커를 통해 오브젝트 파일들이나 라이브러리를 모두 묶어 연결하여 실행 파일로 만드는 과정
어셈블리 과정에서 만들어진 포맷 구조를 바탕으로 미리 컴파일 되있는 라이브러리 파일이나 오브젝트 파일을 모두 링크(Link) 시킨다. 이제 이 덩어리를 실행파일(*.exe)로 만들어 우리의 작품이 완성되는 것이다.
링킹을 하는 방식으로는 정적 링킹과 동적 링킹으로 나눠질 수 있다.
- 정적 링킹 (Static Linking) : 링커가 프로그램에서 필요로 하는 기능을 라이브러리에서 찾아 실행 파일에 복사하는 방식이다.
- 동적 링킹(Dynamic Linking) : 해당 내용의 주소만 가지고 있다가 런타임에 해당 주소의 필요한 내용만 가져오는 방식이다.
- 목시적 링킹 (Implicit Linking) : 실행 파일 자체에서 DLL의 어떤 함수를 사용하겠다는 정보를 포함시키며, 프로그램 실행 시 해당 함수를 초기화하여 이용
- 명시적 링킹 (Explicit Linking) : 프로그램이 실행 중일 때 DLL 파일이 있는지 검사하고 동적으로 원하는 함수만 호출하여 사용
'IT Dictionary > Software' 카테고리의 다른 글
| 부동 소수점(Floating Point) 표현 (0) | 2026.03.29 |
|---|---|
| 리엑트(React)란? (2) | 2023.05.02 |
| 브라우저 렌더링 과정, 자바스크립트(JS) 작동 원리 (0) | 2023.04.29 |
| 자바 컴파일 과정(Java Compile Process) (0) | 2023.04.28 |
| 메모리 영역과 메모리 구조 (0) | 2023.04.28 |
