메모리 안전성 절대주의자들
요약
Zig와 Fil-C의 메모리 안전성 구현 방식과 Rust와의 차이점을 분석합니다. 메모리 안전성을 확보하는 과정에서 발생하는 성능 비용, ABI 호환성, 그리고 각 언어가 지향하는 설계 철학의 절충점을 다룹니다.
핵심 포인트
- Zig와 Fil-C는 C/C++ 의존성을 포함한 메모리 안전 실행 파일 컴파일을 지향함
- 메모리 안전성 확보를 위한 포인터 추적은 성능 비용(1~6배)을 발생시킬 수 있음
- Rust는 가비지 컬렉터 없이도 높은 메모리 안전성과 생산성을 동시에 제공함
- Fil-C의 ABI 비호환성은 기존 C 기반 생태계 활용에 걸림돌이 될 수 있음
- 언어별로 메모리 안전성, 성능, 개발 편의성 사이의 서로 다른 절충점을 가짐
OP가 불쾌하게 받아들인 듯한 Andrew Kelly의 발언은 Zig가 C/C++ 의존성 전체까지 탈출구 없이 완전한 메모리 안전 실행 파일로 컴파일할 수 있으며, 포인터 추적 빈도에 따라 성능 비용이 약 1~6배라는 내용임
글쓴이는 이를 Rust 공격으로 받아들이고 글 말미에는 Zig를 공격하지만, Fil-C와 Zig의 새 빌드 모드는 생태계에 긍정적인 기여이며 Rust와 다른 설계 지점과 절충점을 제공함
Zig 팀이 선호하는 데이터 지향 프로그래밍을 따르면 성능 비용을 1배에 가깝게 줄일 수 있다는 의미로 해석함
글쓴이는 “Fil-C에서 영감을 받은, Rust와 달리 실제로 메모리 안전한 컴파일 모드 도입”이라는 제목과 Fil-C 개발자의 Twitter 글에 대응한 것임
이를 불필요하게 도발적이라고 읽는 것도 무리는 아니며, Andrew는 이후 제목을 덜 자극적으로 바꿨음
평소와 반대로 “너희 언어는 메모리 안전하지 않다”는 가벼운 조롱이 향하자 Rust 개발자들의 반응 규모가 상당했음
나도 Rust를 무척 좋아하지만 공평하게 받아들일 필요가 있음
“Rust는 상당히 메모리 안전하지만 Fil-C가 그 측면에서는 더 안전하다”는 말은 별로 논쟁적이지 않고 사실로 보임
더 나아가 seL4의 형식 검증된 C는 한층 안전함
올바른 프로그램을 중시하고 가능한 한 그렇지 않은 코드는 쓰지 않으려 하기에, 역설적으로 Zig보다 Rust를 선호함
Zig는 메모리 할당 실패 시 올바르게 종료하기 쉽고 컴파일도 빠르다는 장점이 있음
Fil-C가 Rust보다 더 메모리 안전한지는 모르겠지만 내 용도에서는 가비지 컬렉터와 C ABI 비호환성이 결정적인 걸림돌임
단일 스레드로 만들면 경쟁 상태를 피하고 가비지 컬렉터를 넣으면 메모리 안전성을 얻을 수 있지만, Rust는 두 타협 없이 두 가지를 모두 제공하는 점이 좋음
메모리 안전성을 매우 중시하므로 Fil-C와 Zig의 Fil-C ABI 구현은 당연한 선택임
C 의존성이 있는 Rust 프로젝트는 안전성 보장이 약해지며, 순수 Rust만 쓰는 것도 가능하지만 불편함
Rust 역시 Fil-C ABI를 구현해 C 의존성을 안전하게 빌드하고 Rust와 연결할 수 있어야 하며, 이것이 왜 논쟁적인지 모르겠음
Rust에는 안전하지 않은 Rust 코드가 안전한 Rust의 보장을 지키는지 검사하는 Miri 인터프리터가 이미 있음
비슷한 기능을 구현한다면 디버그 빌드에서만 FFI 코드를 개선하는 보조 수단으로 쓰였으면 함
가비지 컬렉터를 두고 모든 연산을 런타임에 검사하는 방식은 모든 용도에 맞지 않음
Fil-C를 단순한 유틸리티용으로 치부하기 전에 Software Should Work 콘퍼런스의 Fil-C 발표를 볼 필요가 있음
발표자는 사용자 공간 전체와 OpenOffice Impress까지 Fil-C로 구성한 Linux 노트북으로 발표함
일부 C/C++ 프로그램에는 적절하지 않겠지만, 글쓴이가 여기는 것만큼 장난감 기술로 보이지 않음
Python 출신이라 메모리 안전성은 기본 전제였고, Rust를 선택한 이유는 세 가지였음
첫째, 강력한 타입 시스템으로 컴파일 시점 정확성을 확보할 수 있으며, #![forbid(unsafe_code)]와 cargo-geiger를 이용한 의존성 감사로 얻는 메모리 안전성은 그중 가장 덜 흥미로운 표현임
둘째, 코드를 한 번 안전하게 작성해 여러 언어와 실행 환경에서 공유하기 쉬운 생태계를 제공함
셋째, 당시의 try!(x)처럼 고수준 코드를 편하게 작성하게 해주는 문법 설탕이 있음
Zig와 Fil-C는 타입 상태 패턴이나 새 타입 등으로 불변 조건을 타입 시스템에 인코딩해 논리 오류를 컴파일러가 잡게 하는 능력을 충족하지 못해 보임
Fil-C의 ABI 비호환성도 공유 웹 호스팅의 CPython 같은 기존 런타임용 안전한 컴파일 모듈을 작성할 때 문제가 됨
Zig에서도 타입 상태 패턴과 다양한 제약 조건의 타입 인코딩이 가능하며, 어떤 면에서는 comptime이 Rust보다 표현력이 뛰어남
컴파일 시간과 장황함, 생태계 대부분이 이 수준까지 시도하지 않는다는 절충점은 있지만 실제로 가능하고 꽤 재미있음
Fil-C 같은 기술이 왜 20년 전에는 등장하지 않았는지 궁금함
메인프레임 분야에서는 포인터와 능력 기반 권한을 공유하고 태그하는 방식의 보안 문제를 수십 년간 경고해 왔음
하지만 누구도 CPU나 메모리, 즉 비용으로 그 대가를 치르려 하지 않았음
몇 달 전 Filip에게 비슷한 질문을 했고 다음과 같은 답변을 받았음
20042018년에는 아이디어가 있었지만 메모리 안전한 C라는 발상 자체가 어리석다고 봤고, 20182023년에는 생각을 바꿨지만 극단적인 호환성을 달성할 방법을 찾지 못했음
2023~2024년 초기 Fil-C는 호환성과 성능이 훨씬 낮았으며, 2024년 말 InvisiCaps의 돌파구로 현재의 높은 호환성과 괜찮은 성능을 얻었음
2018년경 생각을 바꾼 계기는 GPU에서 쓰이는 C 변형들이 메모리 안전한 C의 단순한 형태라는 관찰이었음
20년 전에는 컴퓨터가 더 느렸고 안전성 비용에 훨씬 민감했음
“Rust 진영이 정말 메모리 안전성을 중시한다면 더 안전한 Fil-C를 지지하고 Rust를 버려야 한다”는 말을 가장 선의로 해석하면, 이제 Fil-C가 있으니 세상을 Rust로 다시 쓰려는 노력을 중단하고 C/C++로 돌아가 예전처럼 통합된 라이브러리 생태계를 유지하자는 뜻임
Rust 라이브러리를 C/C++에서 쓸 수 있어도 이를 원하지 않는 개발자들이 있으므로, Rust 사용자가 더 나은 해법을 인정하고 포기하면 분열이 사라진다는 논리임
하지만 Fil-C에는 가비지 컬렉터와 x86-64 Linux 전용 지원이라는 Rust에 없는 절충점이 있음
메모리 안전성 외에도 Cargo와 전역 이름공간이 없다는 점은 Rust를 쓸 중요한 이유이며, 언어 진영 간 분열이 더 넓은 문화 전쟁과 얽힌 상황은 안타까움
누구나 기꺼이 쓸 라이브러리를 만들고 싶을 뿐임
C와 C++만으로도 이미 분절된 생태계 아닌지 의문임
C 개발자 중에는 C++ 라이브러리를 원하지 않는 이들도 있을 수 있고, Zig와 Odin까지 등장했으므로 Rust가 사라져도 분절은 남음
Rust가 특별히 다른 종류의 분절을 만드는 것인지 궁금함
나 역시 누구나 만족하며 라이브러리를 쓰는 세상을 원하며, 제네릭을 comptime으로 보존하는 Rust→Zig 고수준 트랜스파일러를 개발 중임
Rust는 더 많은 제약 조건을 인코딩하므로 원본 언어로 이상적임
AI 자동 생성 콘텐츠
본 콘텐츠는 GeekNews의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기