오랜만에 블로그 글을 써봅니다. 중간에 여러가지 마인드 변화 + 진로 고민끝에 백엔드보다는 로우레벨을 좋아하고, 재미가 있어서 게임서버 개발자를 준비해보기로 했습니다. 목표가 자주 바뀌는 것 같은데 , 지금 제 시기가 그런 시기라고 합리화하면서 쭉 달려보겠습니다.
소스코드를 작성하고, 프로그램을 만드는 사람을 프로그래머 혹은 개발자라고 합니다. 이때, 프로그램이 어떻게 만들어지고, 어떻게 해석이 되는지의 큰 흐름을 알아야합니다. 한마디로 정리하자면, Source코드를 컴파일 한뒤 , Linking을 끝내면 exe파일이 만들어집니다.
아래는 계산기 프로그램을 만든다고 할 때의 예시입니다.
Desktop App을 기준으로 설명합니다.플랫폼이 어디냐에 따라서 세부적으로는 차이점이 생길 수 있으나 대부분은 아래의 과정을 거치게 됩니다.
요즘은 컴파일과 링크는 하나의 작업이라고 봐도 무방하기 때문에 그냥 Build(Compile + Link) 라고 부릅니다. 프로그램 빌드라는 말은 많이 들어보셨을겁니다.(저도 처음알았습니다)
컴파일러는 Computer Science의 연구분야 중 하나일만큼 , 전문적인 내용이 많고 오래된 영역입니다. 그래서, 학부만 졸업한 제가 디테일하게 설명하기는 어렵겠지만, CS를 쪼끔 핥아본 입장에서 컴파일러를 설명해보려합니다.
우선, 큰 그림을 잡기 위해서 컴파일러는 소스코드를 기계어(머신코드)로 번역해주는 역할을 합니다.
번역해준다는 의미는 많은 뜻을 내포하고 있습니다.예를들어, 같은 소스코드여도 어떤 기계어로 번역되느냐에 따라 처리성능이 달라집니다. 즉, 코드 최적화도 컴파일러가 내부적으로 해주고 있습니다. 우리가 쉽게 느낄 수 있는 기능은 문법검사입니다.

대표적인 오픈소스 프로젝트로 LLVM이 있다고 합니다. LLVM Git에 기여할 정도면, 글로벌 IT기업에서 납치를 해간다는 소문이 있습니다 ㅎㄷㄷ..
링커는 분할 컴파일이라는 개념에서 탄생한 친구 입니다. obj파일을 연결하는 역할을 합니다. 그러므로 링커는 기본적으로 소스코드가 여러개가 있는 상황을 가정합니다.
.obj이 됩니다. .dll or .so파일로 만들게 됩니다. 소스코드의 분리가능
효율적인 컴파일
라이브러리의 개발
.lib입니다.Program이란
A sequence of Machine Instruction입니다.
우리가 흔히 생각하는 Program은 실행파일이라고 봐도 무방하고, 링커의 결과물이 실행파일이기 때문에 알고갑시다. Window에선 PE format이고, Linux에서는 ELF format을 갖고있는데 ELF Format을 기준으로 설명하겠습니다.

ELF 파일 포맷을 보면 알겠지만 .text와 같이 코드영역이 따로 있고, .data,.bss와 같이 데이터영역이 따로 있습니다. 아까 Linker가 데이터는 데이터끼리, 코드는 코드끼리 묶는다는게 이런 이야기입니다.
하나하나의 필드에 대해서 자세하게 아는것도 좋지만 저는 개인적으로 파일 Format은 어차피 정해져있는 틀이므로 이해하는 영역은 아니라고 생각합니다. 그러므로, 각 필드가 대략적으로 어떤 역할을 하는지만 간단하게 소개를 하고 넘어가겠습니다.
Memory에 Load될 때 프로그램이 해석하기 위해 , 필요한 정보들이 적혀있는 곳
왜 전역변수 영역이 2개일까?
데이터는 소스코드(명령어)에 비해서 용량이 클 수 밖에 없다. 하지만, 초기값이 정해지지 않았다면 애초에 이 친구는 추후에 변수의 값이 수정될 확률이 높기 때문에 실행파일에서 데이터를 갖고있을 필요가 없다. 예를들어 ,int arr[100000];이면 int이고 변수이름은 arr이고 크기는 100000라는 정보만 들고있으면 되기 때문이다. C언어에서 전역변수를 그냥 선언하면 0으로 초기화되는 이유이다.
라이브러리의 기능적인 역할은 자주쓰는 함수들의 모임이 맞지만, 라이브러리의 실체는 하나의 obj 파일의 일종이다.
실행파일에 필요한 모든 기능을 넣게되면 실행파일 하나는 어어어엄청 커질 수 있습니다.
예를들어, 내가만든 A.exe에 결제기능이 있어서 결제프로그램 pay.exe를 불러야할 때 A.exe는 굳이 pay.exe에 관한 모든 코드를 공유받지 않아도 됩니다. A.exe는 pay.exe의 결제기능만 원하므로 pay.exe가 갖고있는 결제 함수의 위치에 대한 정보만 갖고있으면 됩니다.
DLL파일이 있으면 실행 이미지(파일)의 크기를 작게할 수 있고 pay.exe의 결제기능을 다른 프로그램에서도 사용을 한다면 메모리가 절약되는 측면도 있습니다.
배포한 프로그램을 업데이트를 해야하는 경우 모든 프로그램을 다시 컴파일해서 다운받게 하는게 아니라 DLL에 수정사항을 넣어서 배포하면 되기 때문에 컴파일 시간도 줄일 수 있고, 교체에도 용이합니다.
DLL파일은 다른 DLL파일을 의존할수도 있고, 결국 실행시에 라이브러리를 의존하게 되는 의존성이 생깁니다. DLL파일로 인해서 프로그램이 실행되지 않을 수 있고 DLL은 디버깅과정에서 흐름을 쫓아가기 어려울 수 있습니다.
하지만, 여러가지 장점이 있으므로 성능이 중요한 게임엔진, 그래픽 드라이버,운영체제 등에서는 아직 널리 사용되고 있습니다.