디시인사이드 갤러리

갤러리 이슈박스, 최근방문 갤러리

갤러리 본문 영역

러스트) 6.4. 바이너리 크기 문제와 ‘범용성’이라는 신기루

루비갤로그로 이동합니다. 2025.07.02 10:05:51
조회 25 추천 0 댓글 0

실행 파일의 크기가 크다는 것은 비단 러스트만의 문제는 아닙니다. Go와 같은 다른 현대 언어들 역시, 간편한 배포를 위해 모든 의존성을 포함한 단일 정적 바이너리를 생성하면서 비슷한 특성을 공유합니다. 서버 환경과 같이 저장 공간과 네트워크 대역폭이 충분한 영역에서, 이는 큰 단점으로 여겨지지 않습니다.


하지만 이 문제가 유독 러스트의 ‘범용성’ 주장에 치명적인 이유는, 러스트가 스스로를 C/C++의 ‘대체재’라고 주장하기 때문입니다. 이 주장은 곧, C/C++이 수십 년간 지배해 온 임베디드 시스템, 운영체제 커널과 같이 자원이 극도로 제한된 환경에서도 자신들이 최적의 선택이라는 선언과 같습니다.


바로 이 지점에서 러스트의 ‘주장’과 기술적 ‘현실’은 정면으로 충돌합니다. C/C++은 전통적으로 동적 링킹을 통해 매우 작은 실행 파일을 만드는 데 최적화되어 있습니다. 반면, 러스트의 기본 빌드 방식(정적 링킹, 제네릭의 모노모피제이션)은 이와 대조적으로 훨씬 더 큰 실행 파일을 생성합니다.


결국 바이너리 크기 문제는 단순한 기술적 한계를 넘어, 러스트가 과연 모든 시스템 프로그래밍 영역을 아우르는 진정한 ‘범용’ 언어가 될 수 있는지에 대한 근본적인 질문을 던집니다. 이어지는 내용에서는 이러한 문제가 발생하는 구체적인 기술적 원인과, 그것이 러스트의 ‘범용성’이라는 신기루에 어떻게 균열을 내는지를 상세히 분석하겠습니다.


libstd의 ABI 안정성 부재와 정적 링킹이라는 귀결


러스트로 만든 간단한 “Hello, world!” 프로그램이 C언어로 만든 것보다 수백 배 더 큰 바이너리 파일을 생성하는 현상은, 많은 개발자들에게 의문을 안겨줍니다. 그 가장 근본적인 원인은 러스트의 표준 라이브러리인 libstd가 안정적인 ABI(Application Binary Interface)를 제공하지 않는다는 언어의 핵심적인 설계 철학에 있습니다.


ABI란, 컴파일된 코드가 서로 상호작용하는 방식에 대한 저수준 규약입니다. C언어의 표준 라이브러리(libc 등)는 수십 년간 안정적인 ABI를 유지해왔습니다. 그 덕분에, 운영체제는 libc를 단 하나만 시스템에 설치해두고, 모든 C 프로그램이 이 공유된 라이브러리를 함께 사용하는 ‘동적 링킹’이 가능합니다. C 프로그램의 실행 파일이 매우 작은 크기를 가질 수 있는 이유가 바로 이것입니다. 실행 파일은 자신의 고유한 코드만 담고 있고, 표준 라이브러리 기능은 이미 시스템에 존재하는 공용 부품을 빌려 쓰는 것과 같습니다.


하지만 러스트는 다른 길을 선택했습니다. 러스트는 언어와 표준 라이브러리를 빠르게 발전시키고 개선하는 것을 최우선 가치로 삼습니다. 만약 libstd의 ABI를 안정적으로 고정해버리면, String이나 Vec의 내부 데이터 구조를 개선하거나, 함수 호출 방식을 최적화하는 등의 발전을 자유롭게 할 수 없게 됩니다. 과거 버전의 ABI에 영원히 묶이는 ‘기술적 부채’가 되기 때문입니다. 즉, 러스트는 ‘안정적인 호환성’보다 ‘빠른 진화’를 선택한 것입니다.


이 선택의 대가는 혹독합니다. libstd의 ABI가 안정적이지 않기 때문에, 러스트 1.78 버전으로 컴파일된 프로그램이, 시스템에 설치된 러스트 1.79 버전의 libstd와 호환된다는 보장이 없습니다. 따라서 동적 링킹은 매우 위험하고 불안정한 방식이 됩니다.


그 결과, 러스트 컴파일러는 기본적으로 ‘정적 링킹’을 강제합니다. 즉, 개발자가 만드는 모든 실행 파일 안에, 해당 프로그램이 사용하는 libstd의 모든 기능들을 복사해서 통째로 집어넣는 방식입니다. “Hello, world!”를 출력하기 위해 println! 매크로 하나만 사용했더라도, 그 매크로가 의존하는 수많은 표준 라이브러리의 코드들이 전부 내 실행 파일 안으로 들어오게 됩니다.


결론적으로, 러스트의 ‘빠른 진화’라는 철학은 ‘ABI 안정성 포기’를 낳았고, 이는 ‘정적 링킹 강제’로 이어져 ‘거대한 바이너리 크기’라는 현실적인 문제를 만들어냈습니다. 이는 메모리와 저장 공간이 극도로 중요한 임베디드 시스템이나 운영체제 커널과 같은 전통적인 C/C++의 영역에서 러스트가 왜 ‘범용적’이기 어려운지를 보여주는 첫 번째 기술적 증거입니다.


사례 1: grep과 rg의 바이너리 크기 비교

libstd의 정적 링킹이 실제로 어느 정도의 영향을 미치는지, 우리에게 익숙한 두 커맨드 라인 도구를 통해 구체적으로 살펴보겠습니다. 바로 C언어로 작성된 전통적인 텍스트 검색 도구인 grep과, 러스트로 작성되어 그 대안으로 떠오른 ripgrep(rg)입니다.


ripgrep은 러스트 커뮤니티가 내세우는 가장 자랑스러운 성공 사례 중 하나입니다. 병렬 처리를 통해 기존의 grep보다 월등히 빠른 검색 속도를 보여주며, 더 편리하고 다양한 기능을 제공합니다. 성능과 기능 면에서 ripgrep이 더 뛰어난 도구라는 점에는 이견이 없을 것입니다.


하지만, 두 도구의 실행 파일(binary) 크기를 비교해보면 우리는 러스트의 ‘현실적인 대가’와 마주하게 됩니다.


grep: 일반적인 리눅스 시스템에서 grep 실행 파일의 크기는 수십 킬로바이트(KB)에 불과합니다. (시스템에 따라 30KB ~ 150KB 내외)

ripgrep(rg): 반면, 정적으로 컴파일된 ripgrep 실행 파일의 크기는 수 메가바이트(MB)에 달합니다. (시스템에 따라 5MB ~ 12MB 내외)


두 도구의 파일 크기는 몇 퍼센트의 차이가 아니라, 적게는 수십 배에서 많게는 수백 배까지 차이가 나는 것입니다.


이러한 압도적인 크기 차이는 바로 앞서 설명한 링킹 방식의 차이에서 비롯됩니다. grep은 매우 작을 수 있는 이유가, 자신의 핵심 로직만 담고 있고, 나머지 표준 기능들은 운영체제에 이미 설치된 공용 libc 라이브러리를 빌려 쓰기(동적 링킹) 때문입니다. 반면 ripgrep은 다른 시스템에 쉽게 복사해서 바로 실행할 수 있는 ‘편리함’을 위해, 자신이 사용하는 러스트 표준 라이브러리와 다른 모든 의존성 크레이트들을 자신의 실행 파일 안에 전부 포함하고 있습니다(정적 링킹).


물론, 최종 사용자가 내려받아 사용하는 단일 애플리케이션의 관점에서 몇 메가바이트의 크기는 큰 문제가 아닐 수 있습니다. 오히려 의존성 문제 없이 단일 파일로 배포되는 것이 더 큰 장점일 수 있습니다.


하지만 이 책이 지적하는 ‘C/C++ 대체재’라는 관점에서는 심각한 문제가 됩니다. 만약 리눅스의 /bin, /usr/bin 디렉터리에 있는 수백 개의 기본 명령어(ls, cp, cat 등)가 모두 수십 킬로바이트의 C 프로그램이 아니라, 수 메가바이트의 러스트 프로그램으로 대체된다고 상상해 보십시오. 운영체제의 기본 용량은 지금보다 수십, 수백 배로 팽창할 것입니다. 이는 저장 공간이 제한적인 임베디드 시스템이나 도커 이미지와 같은 환경에서는 결코 받아들일 수 없는 트레이드오프입니다.


결론적으로, ripgrep은 러스트의 뛰어난 성능을 보여주는 훌륭한 쇼케이스입니다. 하지만 동시에, 러스트의 기본 빌드 방식이 만들어내는 ‘거대한 바이너리’라는 현실과, 그 현실이 ‘모든 것을 대체하겠다’는 범용성의 신기루에 어떻게 균열을 내는지를 보여주는 가장 명백한 사례이기도 합니다.


사례 2: BusyBox의 존재 이유와 러스트의 근본적인 한계

러스트가 가진 ‘크기’의 의미를 가장 깊이 이해하기 위해서는, 먼저 C언어 생태계의 경이로운 창조물인 BusyBox가 왜 존재하는지를 알아볼 필요가 있습니다.


BusyBox는 “임베디드 리눅스의 스위스 군용 칼”이라는 별명처럼, 극도로 자원이 제한된 환경(예: 공유기, 셋톱박스, 초소형 IoT 기기)을 위해 탄생했습니다. ls, cat 등 수백 개의 필수 명령어를 단 ~800KB의 단일 바이너리에 모두 담아, 최소한의 디스크 공간과 메모리로 완전한 유닉스 환경을 제공하는 것이 그 목적입니다. 이는 C언어와 경량 라이브러리 musl이 만들어낸, 효율성과 미니멀리즘의 정수입니다.


이제, BusyBox와 동일한 ‘올인원’ 단일 바이너리 아키텍처를 가진 러스트의 uutils를 그 옆에 놓아보겠습니다. 알파인 리눅스 기준으로, uutils의 크기는 약 6.3MB에 달합니다. BusyBox보다 8배 가까이 큽니다.


여기서 우리는 근본적인 질문을 던질 수밖에 없습니다. 과연 8배나 큰 uutils가, 1KB의 공간도 아껴야 하는 임베디드 환경에서 BusyBox의 목적을 대체할 수 있을까요? 답은 명백히 ‘아니오’에 가깝습니다.


이 비교는 전통적인 GNU coreutils(설치 크기 약 1.0MB)를 함께 놓았을 때 더욱 명확해집니다. 각 패키지의 정보는 알파인 리눅스 공식 패키지 페이지에서 직접 확인할 수 있습니다.


대상 언어 구조 설치 후 총용량 (대략) 목적

BusyBox (C) C 단일 바이너리 ~800 KB 초경량, 임베디드

GNU coreutils (C) C 개별 바이너리 ~1.0 MB 표준, 데스크톱/서버

uutils (Rust) Rust 단일 바이너리 ~6.3 MB ???

논평: 이 표는 C 생태계가 어떻게 문제에 따라 다른 해법을 제시하는 성숙함을 보여주는지 명확히 드러냅니다. 일반적인 환경에서는 표준 GNU coreutils를, 극한의 환경에서는 BusyBox를 사용하는 지혜가 있습니다.


하지만 러스트의 uutils는 그 어느 쪽의 목적도 완벽하게 만족시키지 못하는, 어중간한 위치에 서 있습니다. GNU coreutils보다 6배나 커서 일반적인 시스템에서조차 ‘비대’하며, BusyBox를 대체하기에는 터무니없이 거대합니다.


결국 uutils의 존재는, 러스트의 ‘안전성’과 ‘현대성’이라는 가치가, C 생태계가 수십 년간 쌓아 올린 ‘효율성’과 ‘유연성’이라는 현실의 벽 앞에서 얼마나 큰 ‘비용’을 치러야 하는지를 보여주는 가장 정직한 증거입니다.


물론, 임베디드 리눅스와 같이 더 큰 시스템에서는 C 역시 동적 링킹을 적극적으로 활용하여 유연성을 확보합니다. 이는 C 생태계가 시스템의 규모에 따라 ‘초경량 정적’ 방식과 ‘효율적인 동적’ 방식을 자유롭게 오가는 성숙함을 보여주는 지점입니다. 반면, 러스트의 기본 빌드 방식은 이 두 시나리오 모두에서 최적의 해법과는 거리가 있습니다. 러스트가 제공하는 가치들이, 결코 가볍지 않은 ‘비용’을 수반함을 보여주는 명백한 증거입니다.


min-sized-rust의 ‘불편한 진실’과 비정상적인 최적화 방식 비판


거대한 바이너리 크기에 대한 비판에 직면했을 때, 러스트 커뮤니티의 일부는 “그것은 최적화를 하지 않았기 때문”이라며, 소위 min-sized-rust라 불리는 일련의 가이드라인을 제시합니다. 그들은 이 가이드라인을 따르면 러스트 바이너리도 C언어처럼 작아질 수 있다고 주장하며, 이는 언어의 문제가 아니라 개발자의 노력 문제라고 책임을 전가합니다.


하지만 이 min-sized-rust가 제시하는 방법들을 자세히 들여다보면, 우리는 ‘최적화’라는 이름으로 포장된 ‘불편한 진실’과 마주하게 됩니다. 그들이 제시하는 것은 정상적인 개발 과정이 아니라, 작은 크기를 위해 언어의 장점을 스스로 거세하는 기이하고 비정상적인 과정에 가깝습니다.


min-sized-rust 가이드가 일반적으로 제안하는 방법들은 다음과 같습니다.


패닉 핸들링 포기 (panic = 'abort'): 러스트의 안전장치 중 하나인 ‘스택 되감기(unwinding)’ 기능을 비활성화하여, 패닉 시 프로그램을 즉시 중단시킵니다. 이는 관련 라이브러리 코드를 제거하여 크기를 줄이지만, 프로그램이 자원을 안전하게 정리할 기회를 박탈합니다.

표준 라이브러리 포기 (no_std): 운영체제의 도움이 필요한 모든 기능(파일 입출력, 네트워크, 스레딩, 힙 메모리 할당 등)을 제공하는 표준 라이브러리(libstd)의 사용을 포기합니다. 이는 사실상 러스트를 임베디드 환경용 언어처럼 사용하는 것으로, 우리가 당연하게 사용하던 Vec<T>, String, HashMap과 같은 핵심적인 기능들을 사용할 수 없게 됩니다.

이것이 바로 ‘불편한 진실’입니다. 러스트 바이너리의 크기를 줄이는 방법은, 러스트가 자랑하는 대부분의 현대적이고 편리한 기능들을 스스로 포기하는 것입니다. ‘안전한 실패’를 보장하는 패닉 핸들링을 버려야 하고, 풍부한 기능을 제공하는 표준 라이브러리를 버려야 합니다.


결론적으로, min-sized-rust의 존재는 바이너리 크기 문제에 대한 해결책이 아니라, 오히려 그 문제가 얼마나 심각하고 본질적인지를 보여주는 강력한 증거입니다. C언어가 기본적으로 작은 바이너리를 생성하는 반면, 러스트는 이토록 비정상적이고 복잡한 과정을 거쳐야만 겨우 크기를 줄일 수 있다는 사실 자체가, 러스트의 기본 설계가 ‘작은 바이너리’라는 목표와는 얼마나 거리가 먼지를 명백히 드러냅니다. 이는 ‘범용성’이라는 신화에 가려진, 러스트의 명백한 한계입니다.


추천 비추천

0

고정닉 0

0

댓글 영역

전체 댓글 0
본문 보기

하단 갤러리 리스트 영역

왼쪽 컨텐츠 영역

갤러리 리스트 영역

갤러리 리스트
번호 제목 글쓴이 작성일 조회 추천
설문 현역으로 군대 안 간게 의아한 스타는? 운영자 25/06/30 - -
AD 휴대폰 바꿀까? 특가 구매 찬스! 운영자 25/07/02 - -
2869136 MCU 같이 최적화된 프로세서만 임베디드면 프갤러(14.50) 07.02 41 1
2869135 IT진로설계 상담 받아보세요. 프갤러(112.187) 07.02 85 0
2869134 회사에서 무표정이게 된다 프갤러(59.10) 07.02 28 0
2869133 한글탓 ㅋㅋㅋ ㅇㅇ(211.235) 07.02 48 3
2869132 ㅆㅇㅆ 특징이 첨에 헛소리 지껄이고 ㅇㅇ(211.235) 07.02 47 2
2869131 임베디드와 임베디드 리눅스 둘 다 작은 자원을 가진 기계에 프로그래밍 ㅆㅇㅆ(124.216) 07.02 38 0
2869130 기본도 모르니까 단어를 오용하는거야. [9] ㅆㅇㅆ(124.216) 07.02 111 1
2869129 일베디드 [3] 루도그담당(211.184) 07.02 53 0
2869128 애초에 일반적인 임베디드는 단일 루프 기반임 [10] ㅆㅇㅆ(124.216) 07.02 108 0
2869127 그냥 좆만한 자원의 기곗덩이에 쳐넣으면 임베디드지 [2] 프갤러(14.50) 07.02 50 2
2869126 임베디드 맞다: 셋톱박스, 공유기, 스마트TV, 은행ATM [2] 루비갤로그로 이동합니다. 07.02 42 5
2869125 루비야 너 제미나이에도 명확히 나오잖아 임베디드 '리눅스'랑 임베디드랑 ㅆㅇㅆ(124.216) 07.02 35 2
2869124 임베디드 리눅스도 임베디드 맞음 ㅇㅇ(211.235) 07.02 74 3
2869123 '임베디드'와 '임베디드 리눅스'가 다르다는 당신의 '지적 허세'에 답한 [2] 루비갤로그로 이동합니다. 07.02 69 4
2869122 3일에 한번씩 달리기 5키로뛰면 체력 390만배 상승 가능함?? ㅇㅇ(223.38) 07.02 25 0
2869121 나는 루비 신기한게 어떻게 제미나이를 조교했길래 잘못된 지식을 [2] ㅆㅇㅆ(124.216) 07.02 50 0
2869120 루비야 진짜 미안한데 임베디드와 임베디드 리눅스는 다른데 왜 자꾸 같다 ㅆㅇㅆㅆ(124.216) 07.02 37 0
2869119 러스트 빠돌이들 발작 버튼 = 거대한 바이너리 크기 + 러스트 설계 결함 루비갤로그로 이동합니다. 07.02 46 1
2869118 ㅋㅋㅋㅋ서로 gpt 돌려서 말싸움하는거 개웃기네 [4] 프갤러(106.101) 07.02 48 0
2869117 여기말고 okky 같은데도 rust 환상있으니까 동시발행 요청함 [1] ㅇㅇ(183.101) 07.02 41 0
2869116 '일반적 임베디드'와 '임베디드 리눅스'는 다르다는 뻔한 소리, 그래서 루비갤로그로 이동합니다. 07.02 28 1
2869115 근데 루비야 일반적 임베디드와 임베디드 리눅스는 다름 [1] ㅆㅇㅆ찡갤로그로 이동합니다. 07.02 38 0
2869114 러스트 맹신자들이여, 당신들의 '비대한 바이너리' 변명은 이제 끝났다! 루비갤로그로 이동합니다. 07.02 42 0
2869113 러스트 맹신자의 '아는 척'과 '훈계질': 당신의 비겁한 가면을 벗겨주마 루비갤로그로 이동합니다. 07.02 37 0
2869112 님프 개발자를 향한 '프갤러'의 저열한 비난: 허위사실 유포와 얕은 지식 루비갤로그로 이동합니다. 07.02 16 0
2869111 흡연이랑 피로감이랑 직접적인 연관관계 있음?? ㅇㅇ(223.38) 07.02 32 0
2869110 '저능아'는 바로 당신! 임베디드 리눅스의 '동적 링크'는 현실이다 [3] 루비갤로그로 이동합니다. 07.02 49 1
2869108 러스트 맹신자들이여, 허위사실 유포는 결국 당신들의 '무지'를 드러낼 뿐 루비갤로그로 이동합니다. 07.02 37 0
2869107 러스트 맹신자의 '허위사실 유포'와 '지능 타령': 당신의 비루한 민낯을 루비갤로그로 이동합니다. 07.02 33 0
2869105 모두 좋은 사람이다. [5] 개멍청한유라갤로그로 이동합니다. 07.02 54 0
2869104 평균 심박수가 10이 줄었는데 금연때문이라 볼 수 있음?? ㅇㅇ(223.38) 07.02 32 0
2869103 개발자 영어에 욕심낼만도 하지 무딱갤로그로 이동합니다. 07.02 53 3
2869102 한 만큼 받기를 원하는 사람들에게- 프갤러(121.172) 07.02 38 0
2869101 [대한민국] 좌파가 말하는 민주주의 프갤러(121.172) 07.02 22 0
2869099 난 한만큼만 받길 원함. 그 이상의 기적을 바라지는 않아. [3] ㅇㅇ(223.38) 07.02 36 0
2869096 난 뭔가 될 것 같아. 그 누구보다 잘할 수 있을 것 같아. [1] ㅇㅇ(223.38) 07.02 41 0
2869095 영국, AI 로 신입채용 1/3 로 줄어 - 영국 더타임즈기사 ㅇㅇ(183.101) 07.02 36 0
2869094 LLM 나와서 하는 말인데 ADHD가 강하게 있는 편인데 LLM 나와서 [3] ㅆㅇㅆ(124.216) 07.02 68 0
2869093 형님들 추천 좀 해주세요 [2] 프갤러(106.101) 07.02 43 0
2869092 러스트 서적은 나보다 훌륭하신 선생님들께서 이미 많이 출판했다. [1] 프갤러(218.154) 07.02 43 0
2869091 코틀린 손 대야해? 루도그담당(211.184) 07.02 38 0
2869090 솔직히 나도 ai보다 머리 나쁜거 인정하고 개발 포기함 [1] 뒷통수한방(1.213) 07.02 46 1
2869089 요즘 신입채용 팍 줄어든 이유가 [6] ㅇㅇ(175.203) 07.02 117 1
2869088 아 어셈 재밌구나 [2] 루도그담당(211.184) 07.02 55 0
2869087 러슬람새끼 프갤에 글쓸시간에 그시간으로 책만들어서 팔아라 [1] 뒷통수한방(1.213) 07.02 36 0
2869086 임베디드 리눅스는 임베디드가 가능하지만 일반적 임베디드가 아님 [3] ㅆㅇㅆ(124.216) 07.02 63 0
2869085 ❤✨☀⭐나님 시작합니당⭐☀✨❤ ♥냥덩이♥갤로그로 이동합니다. 07.02 25 0
2869084 듣자하니 님프 쌍욕 처먹고 오픈소스 저주하기 시작했다던데 프갤러(218.154) 07.02 38 0
2869083 dll 없어서 프로그램 실행 안되는거 안겪어봤나? 프갤러(218.154) 07.02 39 0
2869082 그 보석새끼: "리눅스 커널은 c동적 링크를 써서 용량이 작습니다." 프갤러(218.154) 07.02 44 0
뉴스 ‘낙태권 옹호’ 릴리 앨런, “낙태 몇 번 했는지 기억 안 나…자주 임신해” 디시트렌드 10:00
갤러리 내부 검색
제목+내용게시물 정렬 옵션

오른쪽 컨텐츠 영역

실시간 베스트

1/8

뉴스

디시미디어

디시이슈

1/2