[알고 쓰자!] 컴파일과 링크, 빌드

개요

컴퓨터 조립을 엄청 좋아하던 저는 더 멋있어 보이는 프로그래머가 되기 위해 열혈C 프로그래밍으로 공부를 시작했던 기억이 납니다.


"내가 키보드에 입력한 문자들이 전선을 따라가 메인보드에 도착하고 메인보드에서 메모리로, 메모리에서 CPU로, CPU에서 1차캐시 2차캐시...코어... 쓰레드... 화면까지 보여주는 과정을 모두 알 수 있겠군!!"


하지만 책을 펴자 보이는 건 예상과는 너무 달랐습니다.


"사이트에 들어가세요. 그리고 Visual Studio 다운받고... Hello World따라 쓰시고... F5 누르면 끝! 자 이제 당신은 프로그램을 만들었습니다!"(내가 원한 건 이게 아닌데...)

분명 프로그래머는 프로그램을 만드는 사람인데, 다른 프로그램을 다운 받아 만든다는 것에 실망했죠. 마치 새로운 메모장 하나 더 생긴 느낌이었습니다.(실행 가능한 메모장.)

결국 책 끝날 때 까지 항상 머릿속에 의문이 남았습니다. 결국, 제가 작성한 코드는 어떻게 되고, 어떻게 돌아가는 걸까요?

적어도 과정 만이라도 알려줬으면...


프로그램이 만들어 지는 과정은 책을 만드는 과정과 같다고 합니다.

"책을 번역한다고 해보자. 책을 한 장 한 장씩 떼어낸다. 그 다음 여러 사람이 그 한 장의 글들을 전부 번역한다. 자 이제 이 번역된 종이들을 책 한 권으로 다시 엮어보자. 그럼 책이 완성된다. 우리는 프로그램이 만들어 지는 과정을 모두 보았다."


이번 글을 통해 위의 과정을 간단히 정리해 보겠습니다.



컴파일

먼저 컴파일 입니다.

컴파일(Compile)은 한글로 풀이하면 "엮다. 편집하다."입니다.

보통 책을 번역해서 한글로 만들면 항상 책 표지에 엮은이가 적혀 있죠. 컴파일도 마찬가지 입니다. 여러 글자들을 번역하는 작업을 하는 것을 컴파일 이라고 합니다. 따라서 컴파일을 알기 쉽게 "번역"이라고 치환할 수 있을 것 같습니다.

그럼 컴파일러는 "변역가" 또는 "통역사" 라고 할 수 있습니다. 변역, 통역을 해 주는 사람이죠.

그렇다면 컴퓨터에게는 왜 번역이 필요할까요?







사람과 사람 사이에서 의견을 주고 받을 때에는 주고 받을 수 있는 수단이 필요합니다. 수단에는 몸짓, 소리, 사진 등등이 있지만 가장 많이 쓰는 수단은 언어이죠.

하지만 언어는 의견을 주고 받는 두 사람이 모두 그 언어에 대해 알고 있어야 합니다. 한국어만 알고 있는 사람은 한국인에게만, 영어만 알고 있는 사람은 미국인 또는 영국인에게만 언어를 통해 의사를 전달할 수 있습니다.


이번 대상은 컴퓨터 입니다. 컴퓨터와 대화를 하기 위해선 컴퓨터 언어를 배워야 합니다.


하지만 컴퓨터는 기계이기에, 단 두 개의 상태 만을 알 수 있습니다. "전원이 들어왔다."와 "전원이 꺼졌다."이죠. 이것을 사람들은 논리적으로 1,0으로 표현합니다. 이러한 표현 방법을 기계어라고 합니다.

이제 컴퓨터와 대화할 수 있는 수단인 1,0이 생겼습니다. 이는 "전원을 켜라, 전원을 꺼라" 딱 두 가지만 실행할 수 있죠. 하지만 우리가 시키고 싶은 건 더욱 복잡한 일들입니다.


"더해라, 빼라, 곱해라, 나눠라, 길좀 찾아줘, 카톡 보내줘, 청소좀 대신 해줘(청소기?)"


정말 천재적인 사람들은 이러한 명령을 1,0으로 표현하여 컴퓨터에게 시킬 수 있다고 합니다... 하지만 대부분의 사람들은 손도 대지 못하고 포기하고 말겠죠.


사람들은 기계어와 같이 저급 언어(Low Level language, 기계에 가까운 언어)의 단점을 보완하고자 고급 언어(High Level language, 사람에게 가까운 언어)를 만들어 냅니다. 대표적으로 C, C++, Java, C#등등이 있죠.

이 고급 언어는 좀 더 사람의 언어에 가깝습니다. 그래서 (비.교.적)쉽게 배울 수 있고, 더 많은 사람들이 컴퓨터에게 귀찮은 일을 시키려고 합니다.

하지만 컴퓨터는 오로지 0과 1로 이루어진 기계어 밖에 해석하지 못합니다. 그래서 중간에 통역사를 두기로 했죠. 이것이 컴파일러 입니다.


컴파일러는 사람에게 가까운 언어인 고급 언어를 기계에게 가까운 저급 언어로 바꿔 줍니다. 저급 언어로 바뀐 파일을 오브젝트 파일(목적 파일)이라고 하는데, 컴파일러는 고급 언어를 저급 언어로 바꾸어 목적 파일로 만들어 줍니다.

이것이 바로 컴파일러가 하는 일(컴파일)입니다.

C컴파일러는 C를 기계어로 번역해 주고, C++컴파일러는 C++을 기계어로 번역해 줍니다. 마찬가지로 각 언어에는 전용 컴파일러가 존재 합니다. 마치 영어 전문 통역사, 일본어 전문 통역사가 있는 것과 마찬가지죠.


이제 조금 더 많은 사람들이 각자 자신 있는 언어로 (비.교.적)쉽게 컴퓨터에게 일을 시킬 수 있게 되었습니다.

자 이제 위의 문장에서 앞 부분의 의문이 해결되었습니다.


링크

이제 링크 입니다.링크(Link)는 "연결하다"라는 뜻을 가지고 있는데요, 바로 컴파일(번역)된 파일 하나 하나를 연결 시켜 주기 때문입니다. 위의 예시인 책 번역하는 과정과 같죠!

"책을 번역한다고 해보자. 책을 한 장 한 장씩 떼어낸다. 그 다음 여러 사람이 그 한 장의 글들을 전부 번역한다. 자 이제 이 번역된 종이들을 책 한 권으로 다시 엮어보자. "

왜 이런 작업이 필요할 까요?


어느 날 반항기가 돋은 한 작가는 자신의 소설의 모든 내용을 한 장에 담고 싶어졌습니다. 소설의 내용이 무지무지 짧다면 A4정도 크기에 다 담을 수 있겠지만, 질풍 노도의 시기를 겪고 있는 작가는 절대 적은 양의 내용을 담고 싶지 않습니다. 따라서 4A0라는 크기의 종이 한 장에 자신의 소설을 모두 담기로 합니다.(4A0는 사람보다 큰, 2m가 넘는 크기...)


그리고는 아무도 읽지 않아 보기 좋게 망했습니다.

이제 작가는 얌전히 소설을 여러장으로 나누어 책을 만들기 시작했습니다.

프로그램도 마찬가지 입니다.






너무 많은 양이 한 파일에 전부 담아져 있다면, 누가 읽고 싶어 할까요? 자기 자신도 읽기 싫어질 것입니다. 또 코드는 복잡해 져서 문제가 생기면 어디서 문제가 있는지 알기도 쉽지 않죠. 따라서 사람들은 목적에 맞게, 기능에 맞게 파일을 분리하며, 무지 어려운 SOLID원칙을 지켜 가며 코드를 작성하게 됩니다.

이 파일들은 여러 폴더에, 따로 따로 저장되게 됩니다. 하지만 실행을 할 때에는 한 곳에 모여 서로 얽히고 설켜 데이터를 주거니 받거니 하면서 실행이 되어야 합니다. 이 때에 사용되는 것이 링커 입니다.

링커는 따로 따로 저장된 목적 파일(Object file, 컴파일된 파일)들을 서로 엮어 하나의 프로그램으로 만드는 역할을 합니다.

또한 키보드를 입력 받을 수 있게 하는 함수라던가, 운영체제에 요청하는 기능 등, 우리가 신경 쓰지 못하는 필수 적인 기능들도 같이 엮어주죠.

옛날에는 컴파일러와 링커를 따로 불렀지만, 둘 다 필수적인 행동이기에, 요즘은 그냥 통합해서 컴파일러 라고 부릅니다.


빌드

자 그럼 빌드는 무엇일까요?

빌드(Build)는 "짓다. 세우다."란 뜻을 지니고 있습니다.

우리의 이 과정에 비유하면? 프로그램을 만드는 것이라고 할 수 있죠.

네. 그렇습니다. 그냥 프로그램을 만드는 것을 빌드라고 합니다.

빌드에는 위의 컴파일과 링크의 과정이 있구요.

결국, 컴파일과 링크를 한번에 모아 부르는 것을 빌드라고 합니다.(김 새는 용두시미 식 결말)


"좋아. 이제 프로그램이 어떻게 만들어 지는 지 알았어. 근데, 렘에는 어떻게 올라 가고, cpu에는 어떻게 실행 되는 것이지?"


다음 번에는 프로그램과 프로세스를 알아 보도록 하겠습니다!


오류 지적은 적극적으로 환영합니다!


댓글