1. Buildroot 임베디드 파일 시스템 크기 최적화 배경: SquashFS 및 Musl C Library 도입의 필요성
임베디드 리눅스 시스템 개발 환경에서는 NAND Flash, NOR Flash, eMMC 등 저장 공간의 물리적 제약이 존재합니다. Buildroot 기본 구성(Default Configuration)으로 빌드한 루트 파일 시스템(RootFS)은 불필요한 패키지, 디버그 심볼, 미사용 라이브러리를 포함하여 용량이 비대해질 수 있습니다.
파일 시스템 크기가 증가하면 저장 장치 비용이 상승하고, 부팅 속도가 지연되며, OTA(Over-The-Air) 펌웨어 업데이트 시 네트워크 대역폭 소비가 늘어납니다. Musl C 라이브러리 전환, SquashFS 압축 파일 시스템 적용, Binary Strip 처리, BusyBox 미사용 유틸리티 제거 기법을 적용하면 파일 시스템 크기를 최소화하고 런타임 성능을 향상시킬 수 있습니다.
2. Buildroot RootFS 용량 최적화 핵심 요약 (TL;DR)
- C 라이브러리 및 압축 최적화: make menuconfig에서 Toolchain C library를 Musl(BR2_TOOLCHAIN_USES_MUSL=y)로 변경하고, Filesystem images에서 SquashFS(BR2_TARGET_ROOTFS_SQUASHFS=y)를 선택합니다.
- 디버그 심볼 및 패키지 제거: BR2_STRIP_strip=y 설정으로 타겟 바이너리의 심볼을 제거하고, target-finalize 스크립트 또는 후처리 스크립트(Post-build script)를 활용해 /usr/share/doc, /usr/share/man 디렉터리를 삭제합니다.
- BusyBox 및 커널 최적화: make busybox-menuconfig를 통해 미사용 CLI 명령어를 제거하고, make linux-menuconfig에서 불필요한 파일 시스템 및 드라이버 모듈을 비활성화합니다.
3. Buildroot 용량 최적화 상세 분석 및 구현
3.1 파일 시스템 최적화 기법별 특징 및 용량 절감 효과 비교
| 최적화 기법 (Optimization Technique) | 주요 적용 대상 (Target Component) | 설정 옵션 (Configuration Symbol) | 용량 절감 효과 (Size Reduction Impact) |
| C Library 전환 | Glibc / Musl / uClibc | BR2_TOOLCHAIN_USES_MUSL=y | 수 MB ~ 십수 MB 절감 (Glibc 대비) |
| 압축 파일 시스템 적용 | RootFS Image | BR2_TARGET_ROOTFS_SQUASHFS=y | RootFS 전체 용량 최대 60~70% 압축 |
| Binary Strip | Executables & Libraries | BR2_STRIP_strip=y | 바이너리 용량 30~50% 감소 |
| BusyBox 경량화 | Core Utilities (/bin, /sbin) | make busybox-menuconfig | 수백 KB ~ 수 MB 절감 |
| 문서 및 헤더 제거 | /usr/share/man, /usr/include | BR2_PACKAGE_OVERRIDE_FILE / Post-build Script | 수 MB 절감 |
3.2 Musl C Library 및 SquashFS 파일 시스템 설정
Glibc(GNU C Library)는 기능이 풍부하지만 임베디드 환경에서는 메모리와 바이너리 크기 부담이 큽니다. Musl C Library 또는 uClibc-ng를 사용하면 크기를 크게 줄일 수 있습니다. 또한, 읽기 전용(Read-Only) 파일 시스템인 SquashFS를 적용하면 XZ 또는 ZSTD 압축을 통해 높은 압축률을 얻을 수 있습니다.
주의 (Technical Correction): .config 파일을 직접 수정하여 BR2_PACKAGE_PYTHON=n과 같이 작성하는 방식은 make 실행 시 Kconfig 의존성 체크에 의해 덮어씌워질 수 있습니다. 반드시 make menuconfig 인터페이스를 사용하거나 디폴트 컨피그(defconfig)를 통해 수정해야 합니다.
make menuconfig 내 최적화 옵션 경로는 다음과 같습니다.
# 1. C Library 변경 (Musl 적용)
Toolchain --->
C library (musl) --->
(X) musl
# 2. SquashFS 압축 파일 시스템 선택
Filesystem images --->
[*] squashfs filesystem
Compression provider (xz) --->
.config 파일 반영 예시:
# Toolchain optimization with Musl C library
BR2_TOOLCHAIN_BUILDROOT_MUSL=y
BR2_TOOLCHAIN_USES_MUSL=y
# SquashFS image configuration with XZ compression
BR2_TARGET_ROOTFS_SQUASHFS=y
BR2_TARGET_ROOTFS_SQUASHFS_XZ=y
3.3 Target Binary Strip 및 디버그 심볼 제거
컴파일된 ELF 바이너리에 포함된 디버그 심볼(Debug Symbol)과 심볼 테이블은 타겟 실행 환경에서 불필요한 용량을 차지합니다.
주의 (Technical Correction): 기존 글의 BR2_STRIP_STRIP=y 및 BR2_ENABLE_DEBUG=n은 올바르지 않은 Symbol Name입니다. Buildroot의 공식 Kconfig Symbol은 BR2_STRIP_strip=y 및 BR2_ENABLE_DEBUG=n이 포함되지 않는 기본 구조입니다.
make menuconfig 경로:
Target packages --->
[*] Strip target binaries
.config 파일 설정:
# Strip symbols from binaries and libraries on target
BR2_STRIP_strip=y
BR2_STRIP_EXCLUDE_FILES=""
BR2_STRIP_EXCLUDE_DIRS=""
3.4 BusyBox 및 Linux Kernel 기능 최적화
BusyBox의 미사용 명령어(Applet)와 Linux 커널의 불필요한 파일 시스템/드라이버 모듈을 제거하면 바이너리와 모듈 디렉터리(/lib/modules)의 크기를 최소화할 수 있습니다.
BusyBox 경량화
다음 명령어를 실행하여 미사용 Applet(예: vi, wget, ftpd 등)을 비활성화합니다.
$ make busybox-menuconfig
Linux 커널 모듈 최적화
다음 명령어를 실행하여 사용하지 않는 파일 시스템(NTFS, ISO9660) 및 드라이버를 제거합니다.
$ make linux-menuconfig
설정 파일(kernel.config) 변경 예시:
# Disable unused file systems in Linux Kernel
# CONFIG_NTFS_FS is not set
# CONFIG_ISO9660_FS is not set
# Build essential USB storage driver as built-in instead of module
CONFIG_USB_STORAGE=y
4. Buildroot 용량 최적화 실무 팁
4.1 Post-Build Script를 활용한 불필요한 문서 및 디렉터리 자동 삭제
Buildroot 빌드 완료 직후 타겟 파일 시스템(output/target)에서 문서, 매뉴얼, C 헤더 파일 등을 자동으로 제거하도록 후처리 스크립트(Post-build script)를 등록합니다.
make menuconfig 설정:
System configuration --->
Custom scripts --->
(board/custom/post_build.sh) Custom scripts to run inside the target filesystem
board/custom/post_build.sh 예시:
#!/bin/sh
# Remove documentation, manual pages, and header files from Target RootFS
TARGET_DIR=$1
rm -rf ${TARGET_DIR}/usr/share/doc
rm -rf ${TARGET_DIR}/usr/share/man
rm -rf ${TARGET_DIR}/usr/share/info
rm -rf ${TARGET_DIR}/usr/include
4.2 ncdu 도구를 활용한 Target RootFS 용량 분석
빌드 완료 후 어떤 디렉터리나 파일이 용량을 많이 차지하는지 분석하기 위해 ncdu 도구를 활용합니다.
# Analyze size distribution of output/target directory
$ sudo apt-get install ncdu
$ ncdu output/target/
5. Buildroot 용량 최적화 시 흔히 하는 실수 및 트러블슈팅
1. BR2_STATIC_LIBS=y (전역 정적 링크) 적용 시 용량 증가 문제
- 증상: BR2_STATIC_LIBS=y 옵션을 설정한 후 전체 RootFS 이미지 크기가 오히려 증가함.
- 원인: 정적 링크(Static Linking)는 단일 바이너리 실행 시 공유 라이브러리 Dependency를 없애주지만, 실행 파일이 여러 개일 경우 중복된 C 라이브러리 코드가 각 바이너리에 모두 포함되어 전체 용량이 늘어납니다.
- 해결 방법: 다수의 실행 파일과 데몬이 존재하는 일반적인 RootFS 환경에서는 동적 링크(Dynamic Linking)를 유지하고 라이브러리 자체를 Musl로 경량화합니다. 단일 바이너리만 실행되는 극소형 램디스크(Initramfs) 환경에서만 BR2_STATIC_LIBS=y를 고려합니다.
2. Glibc 전용 애플리케이션의 Musl 빌드 실패 (gnu/stubs.h 에러)
- 증상: C 라이브러리를 Musl로 변경 후 빌드 시 fatal error: gnu/stubs.h: No such file or directory 에러 발생.
- 원인: 소스 코드가 Glibc 전용 비표준 API(GNU Extension)에 의존하고 있어 Musl C 라이브러리와 호환되지 않음.
- 해결 방법: 소스 코드의 GNU 전용 API를 POSIX 표준 API로 수정하거나, 해당 패키지에 대해 Musl 호환 패치를 적용합니다. 수정이 불가능한 경우 uClibc-ng를 대안으로 선택합니다.
6. 결론: 체계적인 Buildroot RootFS 경량화 프로세스
Buildroot 파일 시스템 크기 최적화는 단일 설정이 아닌 시스템 전체 구성 요소의 정밀한 조정을 통해 달성됩니다.
- C 라이브러리 및 압축 최적화: Musl C Library 및 SquashFS(XZ/ZSTD)를 적용하여 기본 용량을 절감합니다.
- 바이너리 및 문서 정형화: BR2_STRIP_strip=y 설정 및 Post-build Script를 적용하여 디버그 심볼, manual, header 파일을 제거합니다.
- 컴포넌트 튜닝: Busybox 및 Linux Kernel 설정을 통해 미사용 기능과 드라이버 모듈을 제거합니다.
단계별 최적화를 통해 용량 제약을 극복하고 안정적인 임베디드 시스템을 구축할 수 있습니다.