C

C언어를 가르칩니다.

C C언어를 가르칩니다.

프로그램이 만들어지는 과정-컴파일링과 링킹

소스코드가 실행 파일이 되는 과정을 간단히 알아봅니다.

완전 생 입문자들이 보기에는 좀 어려운 내용입니다. 나중에 읽어도 상관 없습니다.

 

흔히 소스코드를 실행 파일로 만드는 과정을 컴파일링(Compiling, 또는 컴파일)이라고 합니다. 그러나 엄밀히 말하면 컴파일링만으로는 실행 파일을 만들 수 없습니다. 소스코드는 실행 파일이 되기 위해 '컴파일링'과 '링킹'(Linking)이라는 과정을 거쳐야 합니다. 다른 언어에서도 똑같은 과정을 거치지만, 보통 이 두 가지를 구분하지 않고 합쳐 그냥 '빌드'(Build)한다고 합니다. 요즘은 거의 모든 시스템에서 링커(Linker, 링킹을 해주는 프로그램)를 자동으로 호출해서 굳이 구분하지 않아도 프로그래밍하는 데 문제가 없습니다. 컴파일링과 링킹에 관해 간단하게 알아봅시다.

다음과 같은 코드가 있습니다.

#include <stdio.h>
int main(void)
{
    printf("Hello, World!");
    return 0;
}

이 파일을 Hello_World.c 라는 이름으로 저장한다고 합시다. 그리고 컴파일러에게 이걸 컴파일하라고 하면, 컴파일러는 이걸 Hello_World.obj 라는 파일로 만들어냅니다. 이 확장자가 .obj인 파일을 오브젝트 코드 파일, 줄여서 오브젝트 파일이라 합니다. 오브젝트 파일은 완전하지 않고, 그저 이 소스코드'만' 기계어로 번역한 것에 불과합니다. 기계어로 번역만 하면 다 끝나는 거 아니냐고요? 아닙니다. 이 오브젝트 파일에는 없는 요소가 두 가지 있습니다.

 

첫 번째로 시동 코드가 없습니다. 시동 코드는 프로그램과 운영체제 사이의 인터페이스를 담당합니다.  오브젝트 코드는 하드웨어만 비슷하다면 어디서나 동작하지만(이 경우에는 모니터와 CPU, 램이 있다면 '비슷'한 겁니다), 운영체제마다 프로그램을 처리하는 방식이 다르므로 각자에게 맞는 시동 코드가 필요합니다. 내 자동차의 키로 다른 자동차의 시동을 걸 수 없듯이, 윈도우에 쓰는 시동 코드로 리눅스에서도 프로그램을 실행시킬 수 없습니다.

두 번째로 라이브러리 코드가 없습니다. 위에 Hello_world.c의 소스코드를 다시 보시면, printf()함수를 사용하고 있습니다. 그런데 Hello_World.obj 파일 어디에도 printf()함수를 정의하는 코드는 없습니다. 그저 printf()함수를 쓰라는 명령만 있을 뿐입니다. 그럼 어디서 정의되느냐? 맨 위에 있는 stdio.h라는 파일(헤더 파일이라 합니다) 안에 printf() 함수가 정의되어 있습니다. 하나의 라이브러리 파일에는 많은 함수들의 오브젝트 코드가 들어 있습니다.

그러므로 링커의 역할은 오브젝트 코드, 사용하는 운영 체제에 맞는 시동 코드, 라이브러리 코드를 묶어서 하나의 파일로 만드는 것입니다. 라이브러리 코드의 경우에는, 라이브러리 전체를 파일에 넣지 않고 필요한 함수가 있는 부분만 추출합니다. 링커가 필요한 코드를 모두 묶어서 나온 결과물이 바로 실행 파일입니다. ​

그런데 왜 이렇게 어렵게 나눌까요? 그냥 컴파일러가 링커 역할까지 한번에 다 해주면 안될까요? 안됩니다. 이렇게 두 가지로 분리된 접근을 함으로써 프로그램이 '모듈화'될 수 있습니다. 예를 들어 이름과 나이를 출력하는 프로그램을 만든다 합시다. 그럼 이름을 출력하는 모듈과 나이를 출력하는 모듈을 각각 만들고(name.c와 age.c가 되겠지요) 각 모듈을 따로따로 컴파일한 후에, 컴파일된 모듈들을 나중에 링커로 결합하겠지요. 그런데 name.c에서 심각한 문제가 발견되어 당장 수정해야 한다고 합시다. 그럼 name.c만 수정해서 name.c 만 컴파일하고 컴파일해서 나온 name.obj를 age.obj와 링커로 결합하면 됩니다. age.c를 다시 컴파일할 필요가 없습니다.

즉, 하나의 모듈만 수정이 필요할 경우에 나머지 다른 모듈은 다시 컴파일할 필요가 없다는 것이죠. 만약 컴파일러와 링커 역할을 프로그램 하나가 담당할 경우 모든 모듈을 다시 컴파일해야 합니다. 시간도 전기세도 모두 손해지요. 컴파일 그깟 거 다시 하면 되지 않냐고요? 간단한 프로그램이라면 컴파일 시간이 매우 짧지만, 아주 복잡하고 거대한 프로그램(게임이나 운영체제라든지)은 컴파일하는 데 몇 시간씩 걸리는 경우도 있습니다. 그런 까닭에 프로그램을 컴파일링과 링킹이라는 두 단계로 나누어 만드는 것입니다.

소스코드가 실행 파일이 되기까지

댓글

댓글 본문
작성자
비밀번호
  1. 폭스킴
    재미있게 읽었습니다~ 쉽게 잘 설명해 주셨네요~ 감사합니다 ^^
버전 관리
truelight
현재 버전
선택 버전
graphittie 자세히 보기