1P by GN⁺ 9시간전 | ★ favorite | 댓글 1개
  • 러스트의 의존성 관리 시스템 이 개발을 편리하게 하지만, 의존성 개수와 품질 문제가 고민임
  • 잘 사용하는 크레이트 조차 최신 상태가 아닐 수 있어 직접 구현하는 것이 나을 때도 있음
  • Axum, Tokio 등 유명 크레이트를 추가한 뒤, 의존성 포함 전체 코드 라인 수 가 360만이나 되어 감당하기 어려움
  • 실제 내가 작성한 코드는 1,000줄 정도에 불과하나, 주변 코드는 검토와 감사를 사실상 못함
  • 러스트 표준 라이브러리 확장, 관리 어려움 등 명확한 ** 해결책**이 없는 상황임

러스트 의존성 문제 개요

  • 러스트는 내가 가장 좋아하는 언어이며, ** 커뮤니티와 언어 사용성**이 매우 뛰어남
  • 개발 생산성은 높지만, ** 의존성 관리** 측면에서 최근 걱정이 생김

러스트 크레이트와 Cargo의 장점

  • Cargo로 ** 패키지 관리 및 빌드 작업 자동화**가 가능하여 생산성이 매우 향상됨
  • 여러 운영체제 및 아키텍처 이동이 수월하고, ** 직접 파일을 관리하거나 빌드 도구 설정**을 신경쓰지 않아도 됨
  • 별도의 패키지 관리 고민 없이 바로 ** 코드 작성**이 가능함

러스트 크레이트 관리의 단점

  • 패키지 관리에 신경을 덜 쓰게 되어 ** 안정성**에 소홀해짐
  • 예를 들어, ** dotenv 크레이트**를 사용했는데, 유지보수 중단됨을 Security Advisory를 통해 알게 됨
  • ** 대체 크레이트**(dotenvy)를 고려하다가, 실제로 필요한 부분만 35줄 정도로 직접 구현함
  • 여러 언어에서 패키지 미유지 이슈가 빈번하게 발생하므로, ** 의존성이 불가피한 상황**이 문제의 본질임

의존성이 불러오는 코드량 급증

  • Tokio, Axum 등 ** 러스트 생태계의 중요하고 품질 좋은 패키지** 사용 중임
  • 종속성으로 Axum, Reqwest, ripunzip, serde, serde_json, tokio, tower-http, tracing, tracing-subscriber를 추가함
  • 웹서버와 파일 압축 해제, 로그 기능이 주 목적이어서 ** 프로젝트 자체는 단순**함
  • Cargo vendor 기능을 활용해 모든 의존 크레이트를 ** 로컬로 다운로드**함
  • tokei로 코드 라인을 분석해보니, 의존성 포함 ** 약 360만 줄**에 달함(벤더된 크레이트 제외시 약 11,136줄)
  • 참고로 리눅스 커널 전체가 약 2,780만 줄로 알려져 있어, 내 작은 프로젝트가 그 일곱 분의 일에 해당하는 양임
  • 내가 작성한 실제 코드는 약 1,000줄에 불과함
  • 이렇게 많은 줄의 ** 의존코드를 감시하고 감시**(audit)하는 것은 사실상 불가능임

해결책에 대한 고민

  • 현재로썬 뚜렷한 해결책이 없는 상태임
  • 일부는 Go처럼 ** 표준 라이브러리를 확장**하자고 주장하지만, 이 또한 유지 관리 부담 등 새로운 문제를 야기함
  • 러스트는 ** 고성능, 안전성, 모듈성**을 추구하며 임베디드나 C++과 경쟁할 목표라 표준 라이브러리 확대가 신중해야 함
  • 예를 들어, Tokio 같은 고도화된 런타임도 ** Github와 Discord**에서 매우 활발히 관리됨
  • 현실적으로 ** 비동기 런타임이나 웹서버 같은 핵심 인프라를 직접 구현**하는 것은 개인 개발자에겐 무리임
  • 대형 서비스인 ** Cloudflare**도 tokio와 crates.io 의존성을 그대로 사용하며, 감사를 얼마나 자주 하는지는 불분명함
  • ** Clickhouse**도 바이너리 크기, 크레이트 수량에 대한 문제를 언급함
  • Cargo로 최종 바이너리에 포함되는 코드 라인을 ** 정확히 식별하기 어렵고** 플랫폼별 불필요한 코드도 포함되는 한계가 있음
  • 결국, ** 커뮤니티 전체에 해답을 물을 수밖에 없는 현실임**
Hacker News 의견
  • 내 생각에는, 의존성이 "쉽게" 추가되고 크기나 비용에 페널티가 없는 시스템은 결국 의존성 문제로 이어진다는 것임. 지난 40년간 소프트웨어 배포 방식을 보면, 80년대에는 라이브러리는 돈 주고 사고, 용량 제약 환경에 맞추어 필요한 일부만 추려서 넣는 식이었음. 오늘날엔 라이브러리 위에 또 라이브러리를 계속 쌓음. import foolib 한 줄로 쓸 수 있고, 그 안에 뭐가 들어있는지는 아무도 신경 안 씀. 각 단계마다 5% 정도 기능만 필요하지만, 깊은 트리로 갈수록 쓸모없는 코드가 쌓임. 결국 단순 바이너리 하나가 500MiB가 되고, 숫자 포매팅 하나 때문에 의존성을 가져오는 꼴임. Go나 Rust는 모든 걸 한 파일에 몰아넣기를 장려해서, 일부만 쓰고 싶어도 난감한 상황이 생김. 장기적으로 진짜 해결책은 초정밀 심볼/의존성 추적으로, 모든 함수/타입이 필요한 요소만 명시해서 딱 필요한 코드만 쓰고 나머지는 버리는 방식임. 이 아이디어는 개인적으로 별로지만, 의존성 트리에서 온 우주를 다 긁어오는 현 시스템을 해결할 방법이 이것밖에 생각나지 않음
    • 대학생이라 잘 모를 수도 있지만, Rust 컴파일러는 이미 사용하지 않는 코드나 변수, 함수 등을 감지해줌. IDE들도 대부분 언어에서 가능함. 그렇다면 그냥 그런 부분을 제거하면 되는 것 아님? 쓰지 않는 코드는 컴파일되지 않음
    • 실제로 내가 Rust로 비교적 무거운 의존성 트리 라이브러리(Xilem)를 작업하면서 feature flag로 트리밍을 시도해봤는데, 거의 대부분 필요한 기능에 따라 유지되어야만 하는 의존성이었음(vulkan, PNG 디코딩, unicode shaping 등). 불필요한 의존성은 주로 아주 작은 것들이었고, serde_json만 소규모 수정으로 뺐음. 더 큰 의존성(winit/wgpu 등)은 구조 변경이 필요해서 쉽게 뺄 수 없음
    • Go나 C#(.NET)은 좋은 반례임. Rust나 JS(Node)만큼이나 효과적인 패키지 관리와 생태계를 갖췄는데, dependency hell이 상대적으로 없음. 표준 라이브러리가 워낙 훌륭해서임. 표준 라이브러리의 방대함은 대기업(구글, 마이크로소프트)만이 투자할 수 있는 부분임
    • 그렇다면 현재 컴파일러는 왜 사용되지 않는 코드를 제거하지 않는 것임?
    • 과거에는 각 함수별로 .o 파일을 만들어 .a 아카이브로 묶고, 링커가 필요한 함수만 꺼내 썼음. 네임스페이싱도 foolib_do_thing() 식으로 했음. 현재는 god object 패턴처럼 top-level 객체에 모든 함수를 가지고 있으니 foolib 하나 import하면 전체가 끌려옴. 이런 상태에선 링커가 어떤 함수가 꼭 필요한지 판단할 방법이 어려움. 대신 Go는 죽은 코드 제거가 훌륭해서, 안 쓰면 컴파일 결과물에서 잘려 나감
    • 현대 컴파일러와 링커는 이미 심볼 추출과 죽은 코드 제거를 수행하고 있고, Rust도 min-sized-rust 같은 프로젝트로 이를 지원함
    • 과거엔 모든 라이브러리를 프로젝트에 포함시켜 직접 빌드 파일에 통합하는 식으로 관리했었음. 큰 노력이 들고 귀찮지만, deps 파일에 한 줄 추가하는 것보다 훨씬 깊이 소통하게 됨
    • Go는 실제로 단일 파일만 고집하는 게 아니라 논리적으로 파일 분할도 쉽게 지원함. 이 부분이 정말 마음에 듬
    • Dotnet은 이미 Trimming과 Ahead Of Time Compilation을 통해 이 아이디어를 실현 중임. 다른 언어들도 Dotnet에서 배울 수 있음
    • LTO(Link Time Optimization)로 바이너리 크기 관점에서는 이 문제가 완전히 해결됨. 사용하지 않는 부분이 최적화로 제거됨. 빌드 시간은 여전히 걸림
    • 나는 오히려 라이브러리 그 자체가 문제가 아니고, 의존성을 추가한 이후 그 내부에 뭐가 얼마나 쓰이는지 시야가 부족한 점이 문제라고 생각함. 각 패키지별 성능/빌드 잉여 코드 비율 등을 손쉽게 피드백 받는 환경이 필요함
    • Unison이라는 언어가 이 아이디어와 부분적으로 유사한 방식을 도입함. 각 함수가 AST 구조에 따라 정의되고, 해시 기반 글로벌 레지스트리에서 불러와 재사용함
    • 작은 라이브러리 조각들을 많이 쓰는 npm의 isEven, isOdd, leftpad처럼 분산 유지보수보다는, 연합 팀이 관리하는 큰 범용 라이브러리가 훨씬 더 미래 보장과 연속성을 제공함
    • ultra-fine-grained 심볼/의존성 추구 대신, 초미세 모듈 구성과 기존 tree-shaking 시스템 활용도 아이디어임
    • Go의 실제 의존성 관리 방식이 원글에서 설명한 이상에 가까움. 모듈은 패키지 모음이고, 벤더링 시 실제 사용하는 패키지와 심볼만 포함하는 식임(정확히 심볼 단위로 동작하는지는 모르겠음)
    • JS 모듈 시스템은 바로 그런 초정밀 심볼 관리와 tree shaking을 지원함
    • 원래 제안된 초정밀 의존성 아이디어는 이미 rust의 --gc-sections 같은 section splitting으로 해결되고 있음
    • Rust는 crate feature를 통한 API 분할로 미세 import가 매우 잘 되는 언어임. Go와는 다름
    • 아키텍처에 따라, (예: 로컬 중심 thick client)라면 첫 설치 800MB여도 실제 사용 땐 네트워크로 엄청 제한된 통신만 하면 되니 문제 없음. UI에서 협업을 위한 반복적 대형 의존성도 용인함
    • 코드 재사용을 위한 최고의 방안은 바로 이 의존성 사용임. 정말 필요한 부분에서만 최적화하기
    • 80년대에 이미 재사용 가능한 소프트웨어 컴포넌트 개념이 Objective-C 같은 언어를 통해 현실화됨. Rust의 큰 성공 중 하나는 시스템 프로그래밍 언어에서도 이런 소프트웨어 컴포넌트화가 널리 채택된 점임
    • tree shaking으로 사이즈/코드 부풀림 이슈는 어느 정도 해결 가능함(서버에서는 아예 신경 안 씀). 더 심각한 문제는 의존성 공급망 리스크와 보안임. 대기업일수록 오픈소스 사용에 승인 프로세스가 있음. granularity만 높인다고 1000개 기능이 1000명의 NPM 저자에서 오면 보안적으로 의미 없음
    • 패키지 추상화 각 계층마다 활용도가 50%만 되어도, 계층별로 전체 사이즈가 실제 필요의 2배씩 증가함. 3단계면 88%가 쓸모없는 코드임. 예시: Windows 11 계산기에 쓸데없는 라이브러리(계정 복구 도구까지)가 따라옴. 기능 추가의 용이함이 복잡성 증가로 이어지는 사례임
    • 의존성 누적이 문제라는 점에는 동의함. 현 시점에서 할 수 있는 가장 좋은 방어책은 시스템 의존성을 극도로 엄격하게 관리하는 것임. 10줄짜리 함수 하나 때문에 외부 라이브러리 가져오는 대신 코드를 직접 붙여넣기도 함. 건강한 라이브러리 생태계가 예외적임. Junior 엔지니어들이 의존성을 무분별하게 추가하는 걸 즉시 제동을 걸곤 함
    • Rust에 대한 기초조차 모르면서 단정적으로 말하는 경우가 오랜만임
    • 죽은 코드 제거 덕분에, Rust 같은 컴파일 언어에선 의존성 트리가 커도 바이너리 부풀림으로 이어지지 않음
  • npm 생태계에서 느끼는 문제는 많은 개발자들이 설계에 대한 고민 없이 의존성을 가져오는 것임. 예를 들어 glob 라이브러리는 단순 globbing 함수여야 하지만, 저자가 커맨드라인 도구까지 묶어서 대형 파서를 의존성에 추가함. 이로 인해 잦은 "dependency out-of-date" 경고가 발생함. 또, glob 라이브러리의 책임 범위도 논란임. 단순히 문자열 패턴 매칭만 하는 게 유연한 설계임(테스트나 파일 시스템 추상화 용이). 전능한 "Do everything" 라이브러리를 원하는 사용자도 많지만, 그럴수록 부작용도 큼. Rust도 크게 다르지 않을 것으로 봄
    • 설계 감각이 중요한데, 좋은 언어는 이런 개발자 취향을 지원하거나 방해하지 않음. Rust, Zig, C 등이 그런 예임. 문제가 통계적으로 덜 발생함. 개발자 '군중'이 모이면 "누구나 자유롭게" 크레이트를 쌓는 "바자회(bazaar) 모델"이 생김. 궁극적으로는 Rust도 공식 표준 라이브러리(예: stdlib::data_structures::automata::weighted_finite_state_transducer 등)와 정돈된 네임스페이스로 "배터리가 포함된" 구성을 갖추길 바람. 언어 자체가 버전 관리와 하위 호환성을 내장했으니, 앞으로도 개선 기대함
    • POSIX glob 함수는 실제로 파일시스템을 탐색함. 문자열 매칭용으로는 fnmatch가 있음. fnmatch는 별도의 모듈로 두고 glob의 의존성이 되게 하는 게 이상적임. glob를 직접 구현하려 하면 상당히 어렵고, 디렉터리 구조, brace expansion 등 복잡한 요건이 있으니 잘 설계된 함수 조합이 필요함
    • Rust에서 borrow checker가 설계 감각 낮은 개발자에 대한 일종의 방패 역할을 해줬음. 이 영향이 언제까지 지속될지는 미지수임
    • Rust의 큰 장점 중 하나는 개발자들이 전반적으로 실력 있고, 크레이트 품질도 높은 편임
    • Bun에도 glob 기능이 포함됨
  • Rust로 불필요하게 특정지을 필요 없이, 의존성 문제와 공급망 공격은 이미 현실임. 새 언어를 설계한다면 'capability system'을 내장해 전체 라이브러리 트리를 안전하게 격리할 방법이 필요함. 예를 들어 이미지 로딩 라이브러리를 설계할 때, 파일이 아니라 스트림만 받아 처리하게 하거나, "파일을 열 권한이 없다"고 명시적으로 지정해서 위험한 함수 사용을 컴파일 타임에 막을 수 있음. 기존 생태계에선 쉽지 않지만 제대로 한다면 공격 표면을 최소화할 수 있음. 의존성 최소화 문화로도 근본적 해결은 어렵고, Go 같은 언어도 공급망 공격에서 자유롭지 않음
    • Sans-IO(dependency에서 직접 IO를 하지 않는 설계) 문화를 적극적으로 퍼트릴 필요가 있음. 새로운 라이브러리 발표 시 IO 직접 구현을 지적하는 문화조성도 필요함. 물론 대중 심사만으로는 충분하진 않겠지만, Sans-IO 원칙이 확산된다면 좋겠음
    • 예시로 WUFFS라는 특수 목적 언어가 있음. 실제로는 Hello world도 못 찍고, 문자열 타입도 없음. 대신 untrusted 파일 포맷 파싱에만 특화됨. 이런 특수 목적 언어가 더 많아질 필요가 있음. 속도도 빠르고, 위험성 없으니 불필요한 체크도 줄일 수 있음
    • Java와 .NET Framework는 decades 전에 partial trust/capabilities 기능이 있었으나, 널리 사용되지 않고 폐기됨
    • Rust에도 비슷한 경향이 약간 있음. #![deny(unsafe_code)]를 통해 unsafe 코드 사용시 컴파일 에러로 막고, 해당 사실을 사용자에게 안내함. 다만 모든 강제점검은 아니고, 특별히 허용하면 unsafe 코드를 쓸 수는 있음. 'feature' flag처럼 표준 라이브러리의 기능을 transitive하게 조절하는 capability system 도입을 상상해볼 수 있음
    • 이런 아이디어를 직접 만들고 싶고, 언젠가 실현되길 희망함. Rust에서 linter 기반으로 캐퍼빌리티 추적이 부분적으로 가능함. 컴파일러의 unsoundness 이슈는 해결이 필요함
    • 기존 언어나 생태계에 완벽히 정적 강제점을 도입하려면 어렵지만, 런타임 검증만 해도 대부분 효과를 누릴 수 있음. 라이브러리 코드를 소스에서 컴파일한다면, 시스템 콜마다 권한 체크 래퍼를 둘 수 있음. 위반 시 panic을 발생시키고, 각 라이브러리별 capability profile을 작성/배포하는 노력이 필요함. 이는 TypeScript에서 이미 유사한 일이 증명되었음
    • Haskell은 IO monad를 통해 이런 접근을 어느 정도 실현함. 직접 IO를 할 수 없는 함수는 타입 시그니처로 제약함
    • 내가 생각했을 때, 이런 체계를 위한 OS와의 소통 방식을 전면적으로 바꿔야 할 필요가 있음. 스트림을 읽는 것조차도 실제로는 파일 읽기용 시스템 콜을 사용할 수 있다는 게 함정임
    • Capslock이라는 프로젝트가 go에서 이 방식에 가깝게 작동함
    • 라이브러리가 시스템 API를 임포트하지 못하게 엔트리 프로그램부터 제한하면, 의존성 주입만으로 capability 전달이 가능함. 현존 언어에서도 설계 가능한데, 기존 라이브러리 호환성이 깨지는 게 실전 문제임
    • 이 아이디어와 유사한 무언가가 기존에 구현된 적이 있는지 궁금함. 현재 언어에선 적용이 매우 어려울 것 같음
    • 한 언어로는 안 되고, 다중 언어 생태계가 필요함
    • TypeScript 생태계에서는 예를 들어 파일 연산 클래스가 없는 환경이면 콤파일이 실패해서 자연스럽게 제한이 적용됨
  • 현대 소프트웨어 개발의 보편적 문제임. 진입 장벽이 낮고, 기존 코드 활용도 많아짐. 의존성 자체가 결국 신뢰할 수 없는 코드임. 기술적 해결이 없다면 누군가가 계속 코드 검토 및 유지보수, 사회적·법적 신뢰 시스템을 유지해야 함. Rust stdlib로 끌어오면 중심 팀이 그 코드 전체를 책임져야 하므로 관리 부담이 커짐
    • 언어마다 표면상의 심각도는 다름. 표준 라이브러리가 강력한 언어는 최소화된 외부 의존성으로도 많은 걸 할 수 있어 유리함. JS/Node처럼 기본 기능이 적은 언어는 외부 의존성이 기본이 됨. "가벼움"이 항상 좋은 건 아님
    • Rust에 더 많은 표준 라이브러리 통합이 필요하다고 봄. Go는 표준 라이브러리가 훌륭한 반면, Rust는 기본적인 기능(웹, tls, x509, base64 등)도 라이브러리 선택과 관리가 고통임
    • Gilad Bracha는 서드파티 라이브러리 샌드박싱에 대한 흥미로운 접근법을 제안했음. import 제거 후 모든 것을 의존성 주입으로. IO subsystem 같은 걸 주입하지 않으면, 3rd party 코드는 절대 그쪽에 접근 못 함. 읽기 기능만 주고 싶으면 읽기 기능만 래핑해서 주입 가능. 단, 시스템 프로그래밍 영역에선 한계가 있음(unsafe code 등 때문)
    • QubesOS처럼 모든 라이브러리를 격리 환경에서 돌리고, 본인 코드는 dom0, 각각의 라이브러리는 별도 템플릿 VM, 통신엔 네트워크 네임스페이스 사용 구조도 제안함. 민감한 산업에선 실용적임
    • 내가 본 바로는 우리가 더 복잡한 일을 하는 게 아니라, 동일한 일을 더 복잡하게 처리할 뿐임. 목표 자체가 어려워진 건 아님
    • 사실 언어마다 상황이 다름. C/C++는 의존성 추가가 어렵고, 크로스플랫폼 지원까지 하려면 훨씬 번거롭기 때문에 비슷한 문제가 발생하지 않음
    • 컴플렉스가 불필요한 코드 부풀림임. 거의 모든 프로젝트가 불필요한 복잡성과 과다설계로 가득 찼음. 이 업계의 문제임
  • blessed.rs는 표준 라이브러리에 담기 어려운 유용 라이브러리 리스트를 추천해줌. 이 시스템 덕분에 대부분의 패키지들은 특정 목적용으로 한정되고 관리할 수 있어 마음에 듬
    • cargo-vet도 추천할 만함. 신뢰할 수 있는 패키지 트랙킹 및 정의, 예를 들어 수입 전에 전문가 감사가 필요한 패키지부터, tokio 메인테이너가 관리하는 패키지는 그냥 신뢰하자 같은 semi-YOLO 정책까지 가능함. blessed.rs보다 좀 더 포멀하며, 팀 내 공식 준표준 목록을 공유하는 수단으로 좋음
    • 이런 시스템이 Python에도 있으면 참 좋겠음
    • 리뷰해보니 정말 괜찮은 추천 프로젝트임
  • leftpad 사건 이후 패키지 매니저에 대한 부정적 인식이 남음. tokio 같은 것은 사실상 언어 수준의 기능이라, 만약 OP가 Go 전체나 Node의 V8까지도 직접 감사를 해야 한다고 보는 건 비현실적임
    • 실제로 tokio도 누군가는 꾸준히 감사를 하고 있음. 다수가 하진 않지만, 어쨌든 누군가는 함
    • cargo가 두 의존성이 서로 다른 버전을 쓸 때 두 버전을 모두 포함하는 현상은 cargo가 독특하게 지원함
  • cargo 패키지에서 feature flag는 진짜 좋은 점임. 불필요한 의존성을 이 flag 뒤에 숨기는 PR을 자주 넣음. cargo tree로 의존성 트리를 쉽게 볼 수 있음. 바이너리에 실질적으로 들어가는 코드 라인 뷰는 별로 의미가 없음. 함수 인라인되는 경우 대부분 main에 합쳐지거든
    • npm엔 feature flag가 없어 아쉬움. 이미 지원하는 패키지 매니저가 있을지 궁금함. 내부 라이브러리에 특정 프레임워크 의존 코드를 고립시켜 확장하고 싶음
  • 나 역시 비슷함. Cargo로 의존성 추가가 너무 쉽게 되어서 혼자 조심한다고 해도, 몇 개만 추가하면 수십 개 트랜싯 의존성이 따라옴. 그렇다고 그걸 안 쓰자는 얘기는 현실적이지 않음. C++에선 이런 현상이 적음. Rust는 작은 패키지 분할이 많아서, 인터넷에서 무작위 코드를 가져오는 느낌임. Rust 자체는 좋아하지만, 이런 구조는 마음에 안 듬
    • Rust 서브레딧에서 링크된 글에서, C++이 의존성이 잘 안 보이는 이유는 대부분 동적 라이브러리로 제공되어서임. 오히려, OS 패키지 관리자의 안정성/보안 관리 능력에 의존하는 점도 장점임. Rust는 표준 라이브러리 확장판 개념이라도 도입하면 좋겠음
    • C++ 의존성이 복잡하고 빌드 시스템이 엉망이라서, Rust식의 덜 안정된 의존성이 더 낫다고 생각함. 실제 C++ 트랜싯 의존성은 프리컴파일 형태라서 더 안 보임
    • Rust에서 작은 패키지 분할이 '철학'이라기보다 빌드 속도 때문임. 규모가 커지면 프로젝트 쪼개서 크레이트로 나누게 됨. 추상화를 위해서가 아니라, 빌드 성능 때문에 강제로 그런 식 구조조정을 하게 됨
    • "그럼 직접 안 쓰면 돼"라는 논리에 무조건 동의할 필요는 없음. 좀 더 고민해봐야 함
    • C++와 CMake는 너무 어려워서, 실제로 많은 소프트웨어가 그냥 쓰지 않게 되는 경우도 많음
  • 핵심 라이브러리는 오픈소스 라이브러리를 쓰고, 소규모 기능은 오픈소스에서 참고해 직접 코드에 복붙하는 식으로 관리함. 코드가 어느 정도 불필요하게 커지지만, 외부 코드 검토 부담과 공급망 노출을 줄일 수 있음. 대형 라이브러리는 여전히 문제이긴 하지만, 모든 걸 직접 짤 순 없음. 이건 Rust만의 문제 아니라 전반적인 문제임
  • 나는 과거(다른 언어에서) 중요한 시스템은 직접 모듈/패키지를 최소화 정책을 세우고, 사용하는 패키지는 모두 사내 저장소로 옮겨 브랜치, 업데이트별로 감사했음. 프론트엔드 등 영역에서는 이런 엄격한 관리가 현실적으로 불가능함. 최근엔 요란한 오픈소스 AI 도구·모델들도 의존성 관리 쪽에서 비슷한 고민이 있음. Rust로 개인 프로젝트를 하면서도, UI/async 라이브러리 의존성 폭증이 가장 꺼림칙함. 하나라도 취약해지면 뚫리는 데, 이건 시간문제임
    • CI/CD 시스템을 공식 내부 저장소하고만 연결하는 게 현실적임. 개발자는 로컬에서 뭐든 설치할 수 있지만, 무단 커밋은 빌드 서버에서 막힘
    • 보안 리스크를 해결하려는 RFC도 있지만, 문화적(아마도) 이유로 급격한 변화는 없음
    • Rust가 멋진 점은 async도 원하는 방식으로 직접 구현 가능함. 특정 구현체에만 종속되는 게 아님