컴파일 후에 일어나는 중요한 과정 이해하기
링크(Link)란?
안녕하세요. 버그없는토마토입니다 🍅
우리가 작성한 C 코드가 실행되기까지는 여러 단계의 빌드 과정이 필요합니다.
그중 많은 분들이 헷갈려하는 부분이 바로 “링크(Link)”라는 단계입니다.
컴파일은 많이 들어봤지만,
링크가 정확히 무엇을 하는 과정인지 이해하지 못하면
임베디드 개발, 자동차 ECU 개발에서 흔히 마주치는 오류를 해결하기 어렵습니다.
오늘은 링크를 초보자·취준생 눈높이에서 이해하기 쉽게 설명해보겠습니다.
실무에서 문제가 발생하지 않는다면 링크란 말을 직접적으로 사용할 일이 많지는 않습니다.
그래서 더더욱 모르고 넘어가기 좋은데요
알아두면 해가 될리 없는 지식이기 때문에 초급일때 완전한 개념을 짚고 넘어가는 것이 중요합니다.
저와 함께 보시죠

1. 컴파일만 하면 프로그램이 완성될까? → NO
많은 분들이 “컴파일하면 실행 파일이 만들어지는 것 아닌가?”라고 생각하지만,
컴파일만으로는 프로그램이 완성되지 않습니다.
컴파일을 하면 소스파일 하나당 각각의 .o(Object File)가 생성될 뿐입니다.
컴파일 중 빌드내역 안에 Link가 실행된 것을 찾아볼 수 있는데요
이에 Object file도 저장 되었을 거예요
각 환경에서 저장 된 곳을 찾아보고, 노트로 열어서 내용을 확인해보는 것도 좋습니다
예를 들면,
main.c → main.o
motor.c → motor.o
sensor.c → sensor.o
이 상태에서는 프로그램 조각들이 따로 존재할 뿐이며
아직 서로 연결되지 않았습니다.
이 조각들을 하나로 묶어 “하나의 실행 가능한 프로그램”을 만드는 작업이
바로 링크(Link)입니다.
사실 이번 내용의 핵심입니다.
이해를 위해 쉽게 표현하자면 .c 를 변역하면 .o가 되고 모든 .o를 하나로 묶는 과정을 Link라고 할 수 있습니다.
그렇게 하나의 파일로 묶어서 기계에 전달하는 거죠.
2. 링크(Link)란 무엇인가?
링크는 쉽게 말하면,
프로그램 조각(.o 파일)들을 연결하여 하나의 완성품(.elf, .bin)을 만드는 과정입니다.
현실 비유로 말하면
여러 레고 조각을 모아 하나의 완성품을 만드는 것과 같습니다.
컴파일 = 레고 조각 만들기
링크 = 조각들을 조립해 완성품 만들기
3. 링크 단계에서 “주소”가 결정된다
컴파일 단계에서는 함수와 변수가 “존재한다”는 정보만 있고
어디에 위치할지는 알 수 없습니다.
링크 단계에서 다음 작업이 이루어집니다:
✔ 함수 실제 주소 배정
Func_Init() → 0x000012F0
✔ 전역변수 주소 배정
g_counter → 0x20000020 (RAM)
✔ 여러 파일에 흩어진 함수 호출을 서로 연결
main.c에서 motor.c의 함수를 호출할 수 있게 되는 것도
링크 덕분입니다.
각 함수 호출 부분에서 오류가 발생할경우나 심볼 오류가 날 경우 링크에러로 표출되는 이유도 이 때문이죠
4. 초보자가 자주 겪는 오류는 대부분 "링크 오류"다
❌ 1) undefined reference (정의되지 않은 참조)
undefined reference to 'Motor_Init'
이 오류는 컴파일이 아니라 링크 과정에서 발생합니다.
원인:
- Motor_Init() 함수 구현이 없음
- motor.o 파일이 링크 목록에 빠짐
- 선언만 있고 정의가 없음
❌ 2) multiple definition (중복 정의)
multiple definition of g_counter
동일한 전역변수를 다른 파일에서 또 정의한 경우 발생합니다.
즉,
➡ 문법이 틀리면 컴파일 오류
➡ 함수가 없거나 중복되면 링크 오류
둘의 차이를 알고 있어야 디버깅이 쉬워집니다.
5. 임베디드에서 링크는 “더 중요”하다
PC 프로그램과 달리 임베디드 MCU는 Flash, RAM 크기와 주소가 매우 제한적입니다.
그래서 링크 과정에서 다음 요소가 매우 중요해집니다:
✔ 코드(.text)는 Flash에
✔ 초기화된 변수(.data)는 RAM으로
✔ 초기화되지 않은 변수(.bss)는 RAM으로
✔ Vector Table은 Flash 시작 주소에
✔ Stack/Heap 위치 결정
✔ Bootloader 공간 제외
이 모든 것을 정의하는 파일이 바로 링커 스크립트(Linker Script, .ld)입니다.
초급 단계에서는
“링크는 실행 파일을 만드는 과정이며, MCU의 메모리 주소를 결정하는 단계이다.”
이 정도만 이해하면 충분합니다.
저 말도 어렵게 느껴지신다면 위에서 제가 설명한 부분 정도만 알아도 되긴 합니다.
🏁 마무리
정리하면 링크는 다음과 같은 역할을 합니다.
- 여러 .o 파일을 하나로 묶는다
- 함수·변수의 실제 메모리 주소를 배정한다
- 프로그램 실행 가능한 .elf/.bin 파일을 만든다
- 임베디드에서는 메모리 맵까지 결정한다
컴파일만큼이나 중요한 과정이지만
초보자들이 가장 어려워하는 부분이기도 합니다.
그래서 중요하기도 하고, 초급자 때 제대로 개념을 정의해놓아야 합니다.
빌드 컴파일 링크 등등의 개념을 잘 잡아야 탄탄한 개발자가 될 수 있어요.
'임베디드 기초' 카테고리의 다른 글
| 실무자가 반드시 알아야 할 Static, Extern, Global 변수의 완벽한 차이 (3) | 2025.12.19 |
|---|---|
| 개발자가 반드시 알아야 할 Compile, Linking, Build, Rebuild, GenerateAll의 완벽한 차이 (0) | 2025.12.19 |
| 컴파일(Compile)이란 무엇인가? (0) | 2025.12.14 |
| RTOS와 Kernel은 무엇이 다를까? (0) | 2025.12.13 |
| Embedded Software는 왜 무한 루프를 사용할까? (0) | 2025.12.13 |