메모리 안전성을 둘러싼 Rust, C, C++, Zig, Fil-C 논쟁과 절대주의적 주장에 대한 실용주의적 시각을 다룬 글.
Piotr Sarnacki가 작성
2026년 7월 28일
이 글의 제목을 보고, 어떤 사람들의 머릿속에는 가장 먼저 "Rust 개발자들!"이라는 생각이 떠올랐을 것이라고 생각합니다. 이런 연결은 근거가 없는 것은 아닙니다. Rust 개발자들은 메모리 안전성에 대해 열정적인 경향이 있습니다. 그중 일부는 분명 고전적인 언어 전쟁식 태도, 즉 내 언어가 네 언어보다 낫고 그 이유는 이렇다는 태도에서 비롯되었을 수도 있습니다. 하지만 저는 메모리 안전성을 중요하게 생각한다고 말하는 대부분의 Rust 개발자들이, Rust와 경쟁하는 언어를 비판하는 데만 관심이 있는 것이 아니라, 소프트웨어를 더 안전하게 만드는 데 진심으로 관심이 있기를 바랍니다.
놀랍게도, 이 글은 Rust 개발자들에 대한 글이 아닙니다.
최근까지 메모리 안전성과 관련된 대부분의 담론은, 적어도 C, C++, Zig, Rust 같은 비-GC 시스템 프로그래밍 언어를 놓고 보면, 비교적 단순한 기반 위에 있었습니다. Rust는 메모리 안전성 문제를 일으킬 수 있는 프로그램의 컴파일을 허용하지 않으려 하며(그 대가로 실제로는 안전했을 프로그램도 때때로 허용하지 않을 수 있습니다), unsafe라는 탈출구를 제공해 무엇보다도 raw pointer 역참조 같은 일을 가능하게 합니다. 반면 C와 다른 언어들은 메모리 안전성 보장을 프로그래머에게 맡깁니다. 언어가 제공하는 도움의 양은 다릅니다. 예를 들어 C++에는 RAII와 smart pointers가 있고, Zig에는 defer가 있지만, 대체로 메모리 접근 위반을 막아 주는 것은 없습니다.
오늘날 상황은 C, C++, 그리고 앞으로는 아마도 Zig 코드까지 메모리 안전하게 만들 수 있는 새로운 방식, Fil-C의 등장으로 조금 달라졌습니다. Fil-C로 컴파일된 C와 C++ 코드는 범위를 벗어난 접근이나 free 이후 사용 같은 잘못된 메모리 접근이 발생하면 panic을 일으킵니다. 이것은 GC와 InvisiCaps, 즉 포인터가 접근할 수 있는 메모리를 추적하는 방식을 결합함으로써 이루어집니다. 최근 Zig의 작성자는 Fil-C에서 영감을 받은 Zig의 새로운 컴파일 모드를 발표했습니다. Fil-C는 매우 흥미로운 프로젝트이며, 저는 진심으로 이것이 성공해서 적어도 일부 인기 있는 C 및 C++ 프로젝트가 Fil-C로 컴파일된 릴리스를 제공하게 되기를 바랍니다.
이상적인 세상이라면 메모리 안전성을 중요하게 생각하는 Rust 프로그래머들과 C/C++/Zig 프로그래머들 모두, 메모리 안전성 취약점을 최소화할 수 있는 방법이 더 많아졌다는 사실을 기뻐했을 것입니다. 하지만 안타깝게도 우리는 이상적인 세상에 살고 있지 않으며, 최근 Rust를 향한 많은 비판이 진정성이 없다는 느낌을 떨칠 수 없습니다. Fil-C 작성자의 Twitter에서의 견해를 읽어 보면, 그가 Rust를 좋아하지 않는다는 것은 너무도 분명하며, 저는 그가 unsafe를 사용할 때 Rust의 일부 보장을 우회할 수 있다는 이유로 Rust가 메모리 안전하지 않은 언어라고 주장하는 것도 보았습니다. Zig의 작성자 Andrew Kelley도 fil 컴파일 모드 이슈 제목에서 비슷한 입장을 보이는 듯합니다. "Fil-C에서 영감을 받은 실제로 메모리 안전한(Rust와는 달리) 컴파일 모드를 도입하자"는 표현입니다. 그 의미는 Rust는 안전하지 않고, 오직 Fil-C나 Zig의 "fil" 컴파일 모드만이 메모리 안전성과 관련된 취약점을 해결할 수 있다는 것입니다.
Rust와 Fil-C와 관련된 논의에서 저는 종종 다음과 비슷한 주장을 보았습니다. "Rust 진영 사람들이 정말로 메모리 안전성을 걱정한다면, Fil-C가 더 안전하니 Fil-C를 지지하고 Rust는 버려야 한다. 그렇지 않다면 그들은 그저 반짝이는 새 언어에만 관심이 있고, 메모리 안전성에는 관심이 없는 것이다." 여기에는 Fil-C의 작성자 자신도 포함됩니다. Andrew Kelley에 대해서는 확신할 수 없지만, 앞서 언급한 이슈 제목은 그 주장과 몹시 가깝게 느껴집니다. 제 생각에 이런 종류의 주장은 현실을 무시하고 있으며, 종종 Rust 개발자들이 받는 비난인 광신주의와 사이비 집단 같은 행동처럼 느껴집니다.
만약 Fil-C가 절대적으로 아무런 트레이드오프도 없는 완전한 drop in replacement였다면, 저는 아마 그 정서에 부분적으로는 동의했을지도 모릅니다. 하지만 Fil-C에는 트레이드오프가 있습니다. Fil-C로 컴파일되지 않은 프로그램과 ABI 호환되지 않고, 경우에 따라 몇 배 느릴 수 있으며, GC를 도입합니다. 이런 점들 중 어느 것도 어떤 프로그램들에게는 결정적인 문제는 아닙니다. 여러분이 매일 사용하는 많은 프로그램은 지금보다 몇 배 느려져도 아마 눈치채지 못할 것입니다. 또한 그중 많은 프로그램은 동적 링크를 전혀 하지 않기 때문에 ABI 호환성도 중요하지 않습니다. 하지만 모든 소프트웨어 프로그램이 단순한 유틸리티는 아닙니다. GC와 ABI 비호환성이 문제가 되는 인기 있는 프로젝트는 많이 있으며, 그런 프로젝트들이 Fil-C 같은 기술을 사용하기 시작할 가능성은 전혀 없거나, 적어도 현재 형태로는 그렇습니다. 그리고 중요한 점은 Fil-C를 사용할 수 없는 종류의 프로그램들이 흔히 Rust에 잘 맞는 경우가 많다는 것입니다.
하지만 Rust는 안전하지 않지 않느냐고요? 결국 unsafe가 있지 않느냐고요! 만약 여러분이 그렇게까지 엄격하고, 다시 말해 메모리 안전 절대주의자라면, 여러분에게는 그 말이 사실일 수도 있습니다. 하지만 저와, 그리고 바라건대 대부분의 사람들은 그보다 더 실용적입니다. 실제로 Rust가 얼마나 안전한지에 대한 데이터는 그리 많지 않지만, 제가 아는 한 실제 Rust 소프트웨어에서 악용 가능한 메모리 안전성 취약점은 많이 없었고, 데이터가 있는 큰 프로젝트도 있습니다. 예를 들어 Android의 5M+ LOC가 있습니다.
Android 플랫폼에 대략 500만 줄의 Rust 코드가 있고 잠재적인 메모리 안전성 취약점이 하나 발견되었으며(출시 전에 수정됨), Rust의 취약점 밀도 추정치는 100만 줄(MLOC)당 0.2개입니다.
C와 C++에 대한 우리의 과거 데이터는 MLOC당 메모리 안전성 취약점 밀도가 1,000개에 더 가깝다는 것을 보여 줍니다. 현재 우리의 Rust 코드는 그보다 자릿수 단위로 더 낮은 밀도를 보이고 있습니다. 즉 1000배가 넘는 감소입니다.
물론 이 수치는 다른 프로젝트에서는 다를 것이라고 확신합니다. 하지만 이제는 실무적으로 Rust가 메모리 안전성 문제를 도입할 위험을 최소화한다는 점이 충분히 확립되었다고 생각합니다.
만약 100%의 프로그램에서 문제의 99.9%를 막는 기술과, 90%의 프로그램에서 문제의 100%를 막는 기술 중 하나를 고를 수 있다면, 여러분은 어느 쪽을 고르시겠습니까? 실제 숫자가 무엇인지는 저도 모르지만, 요지는 전달되었으리라 생각합니다. 다행히도 일부 사람들이 주장하는 것과 달리, 우리는 둘 중 하나만 선택할 필요가 없습니다. 저는 C/C++/Zig로 작성된 프로젝트들 중 트레이드오프를 감수할 수 있는 것들은 Fil-C로 컴파일된 바이너리로 제공되고, 그렇게 할 수 없는 소프트웨어는 메모리 안전성 취약점을 도입할 위험을 완전히 혹은 대부분 제거하는 언어로 작성되기를 바랍니다.
그리고 Go나 Fil-C 같은 GC 언어를 사용할 수 있더라도 Rust를 사용하는 것은 전혀 괜찮다고도 생각합니다. 메모리 안전 절대주의자들은 그것이 용납될 수 없다고 말하겠지만, 그들 중 일부는 이상하게도 메모리 안전 절대주의를 Rust에만 적용하고 C, C++, Zig에는 적용하지 않는 것처럼 보이기도 합니다. 참 묘한 일입니다. 중요한 점은 GC 기반 언어로도 작성할 수 있는 프로그램들은 대개 unsafe를 전혀 필요로 하지 않으며, 반대로 unsafe가 필요한 프로그램들은 대개 GC를 사용할 수 없었을 것이라는 점입니다. 제 경험상, 문제 해결에 완전한 광신주의로 접근하지 않는 사람들은 대개 트레이드오프를 고려합니다. 그들 중 많은 사람들에게, 심각한 메모리 안전성 문제를 실제로 마주칠 아주 작은 위험은 다른 언어 차원의 보장들(예를 들어 data races 방지)과 다른 언어 기능들에 의해 충분히 상쇄됩니다. 게다가 MLOC당 1,000개의 메모리 안전성 관련 취약점 수치를 기억하시나요? Fil-C에서는 그것들이 충돌이 됩니다. 보안 취약점을 도입하는 것보다는 여전히 낫지만, 그것도 고쳐야 할 충돌이 꽤 많다는 뜻입니다. 우리가 비교적 드문 문제를 두려워하는 영역에 있다면, 과거에는 공격자가 프로그램을 충돌시킬 수 있다는 사실이 보안 취약점을 가능하게 했던 사례들도 있었다는 점을 언급하는 것이 좋을 수 있습니다.
이 글을 마무리하며, 만약 누군가가 메모리 안전성을 너무나도 중요하게 생각해서 Rust의 100만 줄당 0.2개의 취약점조차 받아들일 수 없다고 여긴다면, 저는 그 사람이 YOLO식 C/C++와 fil이 아닌 Zig를 컴파일하는 사람들에 대해서도 Rust 개발자들만큼, 아니 그보다 더 강하게 비판하기를 진심으로 바랍니다. 결국 여러분이 정말로 메모리 안전성을 그토록 강하게 중요하게 생각해서 Rust조차 충분히 안전하지 않다고 여긴다면, 그보다 더 안전하지 않은 대안을 사람들이 사용하도록 내버려 두고 싶지는 않을 테니까요.
이 글이 마음에 드셨다면 Twitter에서 저를 팔로우해 주시는 것도 고려해 주세요.