들어가며
시스템 시간을 변경 기능을 테스트하던 중, 소스 코드가 간헐적으로 빌드되지 않는 문제를 겪었다.
버그는 아주 엉뚱한 위치에서 발생했고,
같은 코드를 두고도 어떤 때는 빌드가 되고, 어떤 때는 되지 않는 이상한 상황이었다.
재현 조건을 찾기 어려워 원인 파악이 쉽지 않았다.
결국 예전에 공부한 컴파일 과정과 빌드 시스템의 동작 방식에서 답을 찾을 수 있었다.
현재 진행 중인 프로젝트는 C++ 기반이며,
"무중단 업데이트(Hot Swap)"를 지원하는 구조를 가지고 있다.
문제 정리
내가 겪은 문제를 버그 리포트로 작성하면 다음과 같다.
버그 제목 : 시스템 시간 변경 후 "부분 빌드" 시 변경 내용 미반영
- 시스템 시간 변경 후 부분 빌드(증분 빌드) 실행 시 변경 내용이 반영되지 않음
- 부분 빌드 실행 시 정상적으로 반영되는 경우도 있음
- 전체 빌드 실행 시 정상적으로 반영됨
문제의 원인 ㅡ 증분 빌드와 타임스탬프
시스템시간 변경 기능을 사용 후 빌드시 발생한다는 것에 힌트를 얻어 문제의 원인을 찾을 수 있었다.
문제의 원인은 우리가 흔히 "부분 빌드" 라고 부르는
의존성 기반 증분 빌드(incremental build) 방식에 있었다.
이를 이해하기 위해서는 현재 사용중인 빌드 환경에 대한 이해가 필요하다.
CMake + MinGW 빌드 과정 이해
현재 프로젝트는 CMake + MinGW(GCC) 환경에서 빌드된다.
MinGW 환경에서는 CMake가 Makefile을 생성하고,
make 도구가 GCC를 호출해 다음과 같은 과정으로 빌드를 진행한다.
소스코드 (.c / .cpp)
↓ (Preprocessor)
전처리된 소스 (.i / .ii) 중간 산출물
↓ (Compiler)
어셈블리 (.s) 중간 산출물
↓ (Assembler)
목적파일 (.o) 컴파일 결과물 (=Object file)
↓ (Linker)
실행파일 (.exe)
각 소스 파일은 컴파일되어 목적 파일(.o) 로 생성되고,
최종적으로 링커에 의해 실행 파일이 만들어진다.
make의 증분 빌드 방식 (빌드 최적화)
make는 빌드 시간을 줄이기 위해 증분 빌드를 수행한다.
예를 들어 A.cpp와 B.cpp 두 개의 코드로 구성된 프로젝트를 가정하자.
A.cpp (+A.h) → A.o
B.cpp (+B.h) → B.o
↓
App.exe
CMake는 이 의존성 정보를 기반으로 Makefile을 생성하고,
make는 이 Makefile을 이용해 소스 파일과 헤더 파일의
타임스탬프(mtime)를 비교해 어떤 파일을 다시 빌드할지 결정한다.
만약 A.cpp만 수정되었다면 타임스탬프는 다음과 같을 것이다.
A.cpp (최신) → A.o (과거)
B.cpp (과거) → B.o (과거)
이 경우 make는 A.cpp만 다시 빌드하고, B.cpp는 빌드하지 않는다.
이것이 바로 증분 빌드의 핵심 동작 방식이다.
왜 시스템 시간 변경이 문제를 만들었을까
나는 테스트 과정에서 시스템 시간을 과거 또는 미래로 변경했다.
이 과정에서 파일의 타임스탬프 기준이 깨지면서,
- 소스 파일보다 오브젝트 파일이 미래 시점으로 인식되거나
- 변경된 소스가 있음에도 불구하고 make가 빌드가 필요 없다고 판단하는 상황이 발생했다.
그 결과 어떤 경우는 빌드가 되고, 어떤 경우에는 빌드가 되지 않는 재현하기 어려운 문제가 만들어졌다.
회고 ㅡ 문제를 다시 바라보며
이 문제는 재현 조건을 찾기 어려워 분석에 시간이 걸렸다.
문제를 겪기 전 나는 시스템 시간 변경이 끼칠 영향을 고려하지 못했다.
시스템 시간 변경이라는 재미있는 조건을 가진 버그를 만나 인상 깊었고,
빌드 시스템이 시스템 시간과 밀접하게 연결됐다는 것을 알 수 있었다.
앞으로는 컴파일 과정과 빌드 시스템에 대해 시야를 넓게 보고 고려하게 될 것 같다.
'개발' 카테고리의 다른 글
| OPC UA란 무엇인가 ㅡ 개발자의 시선으로 정리한 산업 자동화 표준 (0) | 2026.01.30 |
|---|---|
| CI 입문 ㅡ Jenkins로 C++ 빌드·유닛 테스트 자동화 따라하기 (0) | 2026.01.21 |
| 개발 실무에서 UML을 어디까지 그려야 할까? (0) | 2025.12.31 |
| Linux 빌드 환경 구성하기 - Ubuntu 22.04에서 SVN 보안 문제 해결하기 (0) | 2025.12.24 |
| Service 기반 시스템 권한 기능 구현기 — 권한 분리 환경에서 IPC구현과 QLocalSocket DACL 문제 (0) | 2025.12.12 |