▲GN⁺ 7달전 | parent | ★ favorite | on: Zig가 실제 CLI 도구 개발에서 Rust보다 더 실용적으로 느껴지는 이유(dayvster.com)Hacker News 의견 Zig의 장점은 C 개발자처럼 계속 생각할 수 있게 해주는 점임, 하지만 어느 정도는 단순히 익숙함의 문제라고 봄 Rust에 충분히 익숙해진 개발자들은 더 이상 borrow checker와 싸우지 않음, 이미 그런 코드 구조로 사고하게 됨 Rust에서 “객체 수프(object soup)” 같은 접근은 잘 먹히지 않지만, 사실 그게 근본적으로 더 쉬운 방법이라고 보진 않음, 단지 우리가 익숙해서 쉽게 느껴지는 것임 ergonomics(사용자 경험)는 측정하거나 수치화하기 어렵다는 전제를 받아들이면 위와 같은 논의가 계속 모호해짐 "이 의자는 무너지지 않으니 안심하고 앉아라, 다만 조금 덜 편하고 무거울지 모르지만 대부분 사람들은 곧 익숙해져 불편을 못 느낄 것이다"라는 식의 이야기와 유사함 원글의 문장처럼 "Rust는 개발자 경험이 불편하지만 메모리 안전성을 주고, Zig는 더 나은 개발자 경험과 약간의 주의로 메모리 안전성을 줄 수 있다"는 것은 결국 안전성과 사용성의 교환임 Rust 커뮤니티는 이런 트레이드오프를 솔직하게 인정해야 한다고 생각함, 안전성 확보는 언제나 덜 편리함을 수반함 보안, 생명, 일상, 소프트웨어 전반에 이 바탕이 깔려 있고, 주로 애매하거나 주관적인 주장들이 많음 “익숙한 사람들은 문제가 없다”고 말하며 ergonomic 논점을 쉽게 무시하는 사람들도 있음, 이는 마치 “그것조차 힘들면 네가 덜 똑똑한 것”처럼 비칠 수 있음 “borrow checker와의 싸움”은 Rust에서 어휘적(Lexical) lifetime만 이해했던 시기에서 기원한 이야기임 내가 2021년에 Rust를 배울 때엔 이미 지나간 옛 얘기였음 실제로 파이썬, C, 자바스크립트 등만 써본 이들에게 Rust에 적응하는 건 쉽지 않을 수 있음 내 경우엔 쉽게 받아들여졌고, 대부분 그렇게는 느끼지 않는 것 같음 그런데 “Rust에선 진단 메시지를 읽으며 코드를 고쳐야만 한다”는 게 “용감하게 borrow checker와 싸운다”만큼 멋있게 들리지 않음, 실제 상황을 더 용감하게 표현해야 한다고 봄 내 경험상 숙련된 Rust 개발자들은 곳곳에 Arc를 뿌려서 자동으로 garbage collection과 비슷하게 씀 정적 메모리 관리가 꽤나 엄격해서 복잡한 자료구조에선 현실적으로 힘듦 lifetimes 때문에 도달해야 하는 경로가 너무 사람의 인지 능력 이상임 숙련된 Rust 개발자도 Arc, Clone, Copy 등을 곳곳에 쓰는 오픈소스 Rust 프로젝트를 많이 봄 Zig의 장점은 C처럼 익숙하게 개발하면서도 언어나 툴링에서 안전성을 챙길 수 있는 기능들이 있음 예를 들어 Zig의 optional 때문에 nil deference 문제를 피할 수 있음 디버깅이나 테스트 시 debug/custom 할당자를 직접 전달해 런타임 검사, 메모리 접근, 리소스 누수 체크도 쉽게 가능 명시적 인터페이스/trait 부재엔 불만이 있지만, 채택이 단순해서 실용적이라고 생각함 나는 원글 내용에 대부분 동의하지 않음 Rust도 C나 Zig와 마찬가지로 lifetime, ownership, borrow scope에 대해 고민하게 되나, 차이는 컴파일러의 도움 유무임 아무리 똑똑해도 피곤하거나 산만할 때 실수하는 것이 인간임, 실수 인정이 곧 현명함임 Rust 컴파일러가 안전하다고 간주하는 프로그램의 공간이 충분히 넓지 않아, 꽤 자주 정상적인 프로그램을 거부함 예시: 구조체 Foo에서 bar와 baz가 각각 문자열일 때, bar를 가변 참조 후 baz를 불변 참조하려 하면 컴파일이 되지 않아, 이런 상황에서 코드 구조를 억지로 우회할 수밖에 없음 반론하자면, “실제론 괜찮은 상태인데 컴파일이 거부되는 경우를 피하기 위해” 두세 번째로 좋은 설계로 코드를 바꿔야 하는 것 자체가 큰 부담임 이렇게 하면 코드베이스 전체의 설계가 바뀔 수 있음 이게 게임 개발자 등 어려운 작업을 하는 사람들에게 Rust 채택이 부담스러운 이유로 설명됨 만약 Rust compiler가 거짓 경고 없이 정확히만 동작한다면 ergonomic 측면에서도 극강일 것임, 물론 현실은 쉽지 않음 위 예시는 정말 훌륭한 사례 같음, 내 블로그나 기사에서 다뤄도 될지 묻고 싶음 위 코드를 보고 오히려 주장에 더 자신이 없어짐 모든 프로그램이 반드시 그렇게 "안전"할 필요 없음을 우리가 기억해야 함 많은 Unsafe 소프트웨어를 즐기며 성장함, Star Fox 64, MS Paint, FruityLoops 등 Zig의 창시자인 Andrew Kelley도 음악 제작 소프트웨어(DAW) 개발 환경이 없어서 Zig를 만들었다고 읽음, Zig가 그런 창의적 소프트웨어에 잘 어울린다고 생각함 누구든 메모리 버그에 민감하면 Rust 쓰면 됨 Super Mario World도 메모리 버그 때문에 더 재밌었다고 믿음 "안전"이란 "내 프로그램이 의도한대로 동작함"의 축약어임 의도하지 않은 비논리적인 코드(semantic gibberish)는 목적 달성에 불리함 예술적으로 난해한 코드를 일부러 짜는 경우(IOCCC, 해킹, 코드 시)도 있지만, 이런 경우엔 신중하게 craft 해야 함 Rust에서도 escape hatch(unsafe)로 의도적으로 이런 것 구현 가능 본문의 주장은, 본의 아니게 의미 없는(gibberish) 코딩이 장점이라는 것인데, 이는 쉽사리 동의하기 힘듦 만약 단점 없이 모든 코드를 안전하게 만들 수 있다면 누구나 원하지 않을까? Super Mario World의 스피드런 등은, 바이너리 패치로도 구현 가능하고, 입력을 통한 메모리 조작만이 유일한 재미라고 보진 않음 약간 혼동되는데, 내 말이 안 좋은 의견이라 생각하는 이유가 메모리 안전이 중요하지 않다는 의미인가 궁금함 borrow checker의 가치가 과소평가된 점이 아쉬웠음 Rust의 borrow checker는 유효하지 않은 메모리 접근을 컴파일 타임에 보장해 줌 물론, 컴파일러 규칙을 지키는 코드 구조로 바꿔야 하는 불편은 있음 직접 Rust를 따로 쓸 때 lifetime annotation이 틀렸다는 생각이 들진 않았고, 번거러운 chore 같긴 했으나 금방 익숙해졌음 unsafe를 쓰지 않는 한, Rust에선 두 스레드가 동시에 같은 메모리 쓰기 불가함 "왜 CLI 도구에서 Zig가 더 실용적으로 느껴지는지"는 공감이 안 됨, Rust가 CVE(취약점) 방지 면에선 여전히 강점임 실제로 나는 대부분 GC 언어로도 충분한 작업을 하고, 다른 언어로 기여할 땐 Rust, Zig, C/C++ 모두 상관없이 씀 CLI 도구가 특별할 게 없다고? 일반적으로 CLI 도구는 규모가 크지 않거나 개인 개발이 많아 관리가 쉬움 Zig나 C는 커다란 코드베이스엔 잘 안 어울릴 수 있음, 더 복잡한 프로젝트에선 babysitter(보호자)가 필요 이와 비슷한 과거 논쟁으로 Java도“babysitter 언어”라고 불렸지만, 실상 많은 코드베이스에선 그게 필요함 unsafe를 안 쓴다고 두 스레드가 동시에 같은 메모리를 못 쓰는 건 아주 깔끔하게 떨어지지 않음 내가 원하는 컴파일러의 지원은 주로 메모리 접근 순서(memory ordering) 문제 해결임 Rust는 이런 부분에서 race가 생기더라도 unsafe가 아니라 safe로 분류함 Rust에서 backlinks 구현이 너무 복잡하다는 점은 동의함 Rc, Weak, RefCell, .borrow() 등을 사용하면 가능하지만 쉽지 않음 짧게 실행되는 프로그램이라면 arena 할당도 방법임(CLI 도구가 뜻하는 바로 보임) Rust는 거대한, 멀티스레드, 장시간 구동되는 어플리케이션에서 진짜 힘을 발휘함 내가 실제로 Rust로 대형 메타버스 클라이언트를 썼는데, 수십 개 쓰레드를 24시간 돌려도 메모리 누수, 크래시 없었음 같은 걸 C++로 하려면 QA팀과 Valgrind 같은 툴이 필수이고, 스크립트 언어는 성능상 너무 느림 나도 Rust로 지구 곡률과 중력 편차까지 반영한 물리 시뮬레이션 비행기를 만들었음 5시간, 22시간짜리 경로 테스트를 수년간 아무 문제 없이 돌렸음 7년간 Rust로 크래시 경험은 소수에 불과, C/C++는 과거 유산 코드 고칠 때만 씀 Zig가 매력적이긴 한데 D도 여전히 존재하고, 개인적으로 D가 내가 원하는 C/C++ 대체라고 느껴짐 Zig의 문법이 뭔가 어색하고, Rust는 이미 생태계에서 중심이 되고 있음 Go 역시 여러 언어 툴에서 점유율이 높고, AI 분야에선 Python 다음으로 많이 쓰임 Rust 이전에 Go vs. D 논쟁이 있었고, 나도 D 교재까지 샀었다가 Go에 넘어감 나에겐 표준 라이브러리가 훨씬 실용적이었고, int64 같은 자료형 이름이 더 직관적이었음 D가 좋긴 하지만 대중화될 킬러앱이 안 나옴 Rust나 Zig로 굳이 CLI 툴을 써야 할 이유를 잘 모르겠음 IO가 병목이지, GC가 느려서가 아님 GC 이슈는 게임, DB 등 메모리 집중형이 아니면 논점이 아니라고 생각함 메모리 안전성 논쟁보다는 GC가 필요 없는 언어를 선택해야 하는 이유를 더 고민하는 편이란 점을 강조함 만약 “노-GC가 재밌어서” 쓰는 거라면 그 자체로 충분함, 논쟁 필요 없음 즉각적인 스타트업 타임(실행 지연 없음)이 아주 유익함 래핑 툴 만들 땐 수천 번 돌려도 부담 없음 Python 같은 환경의 배포 복잡성이 없어서 분배도 쉬워짐 Go로 CLI 만드는 게 매우 괜찮았음(비록 Go 언어 자체는 선호하지 않음) Python CLI는 의존성이 많으면 배포가 번거롭고, Rust/Zig도 Go처럼 정적 바이너리 배포가 쉬워 인기임 sum type, 패턴 매칭, async 지원이 있는 언어를 1순위로 고름 Rust가 아니어도 에러를 컴파일 타임에 잡아주는 기능이 좋음 GC 없는 개발이 게임 분야에만 해당된다는 지적에 대해 실제로 많은 모바일 게임도 Unity+ il2cpp 환경처럼 GC를 사용하고, GC 성능도 좋지 않은 경우가 많음 GC 논쟁은 일종의 밴드왜건 느낌임 50년 전 이미 GC 기반 언어로 Interlisp, Cedar 등 대형 워크스테이션이 성공적으로 만들어졌음 오늘날 하드웨어 성능은 1970년대 CLI, Electron 앱보다 훨씬 좋은데 효율적 활용이 부족함 Rust의 빌트인 borrow/referencing으로 간단한 노트 툴을 만들었는데, 생각만큼 복잡하지 않았음 notes 리스트의 인덱스를 저장하고 맵으로 연결하는 구조를 상상하면, 속도 차이도 거의 없고, 안전성 단점도 없음 인덱스 실수해도 범위를 벗어난 에러로 잡을 수 있어, 커널 메모리를 덮어쓰는 것보다 훨씬 좋음 printf debugging 때도 훨씬 쉽고 직관적임 raw pointer나 reference는 보통 allocator, async runtime처럼 정말 필요한 곳에만 쓰고, 일반적 로직에는 index-based가 더 맞음 유명하게도 Rust async가 self-referential struct를 못 써서 Pin 관련 이슈가 생기는 이유도 여기에 있음 vec에 저장된 값의 포인터는 realloc 등이 일어나면 무효가 되므로, 이땐 Miri에서 바로 오류가 남 C++ 개발자인 내가 안전한 언어를 찾는다면 Swift가 제일 적합하다고 느낌 친숙하거나 닮은 언어가 더 금방 적응 가능함 Swift는 최근 크로스플랫폼 지원도 강화되었고, 현직 C++ 표준위원회 사람들이 여러명 참여함 하지만 Apple 연관성, 네이티브 UI 프레임워크 부재 등으로 비애플 진영 확장은 상대적으로 덜 함 Swift가 더 많이 인기 얻길 희망함 Swift와 Zig/C를 비교할 수 있는 리소스 있으면 추천해주면 좋겠음 Zig도 적당한 주의로 메모리 안전 소프트웨어를 만들 수 있다는 말이 있는데, 사실 C도 일정 수준 disciplined하게 쓰면 같은 결과가 나옴 결국 이 “조금의 절제(훈련)”가 현실에선 부족해서 문제가 발생함 Zig는 추가적으로 아래 문제들을 해결함 Out of bounds access(전체 CVE의 70% 차지) null pointer dereference 타입 안전성 C보다 월등하고, use-after-free 같은 오류도 경계를 안 넘는 한 훨씬 쉽게 피할 수 있음 Zig의 뛰어난 크로스플랫폼 빌드 시스템, comptime 최적화, C++/Rust보다 수십 배 빠른 빌드 타임도 강점임 아직 표준 라이브러리가 미흡하고 자잘한 문제는 남았지만, perf-oriented 프로그램에선 미래가 밝다고 생각함 C가 50년 넘게 이런 discipline 문제로 실패했다면, "샤오린의 도" 이상으로 어려운 일임
Hacker News 의견
Zig의 장점은 C 개발자처럼 계속 생각할 수 있게 해주는 점임, 하지만 어느 정도는 단순히 익숙함의 문제라고 봄
Rust에 충분히 익숙해진 개발자들은 더 이상 borrow checker와 싸우지 않음, 이미 그런 코드 구조로 사고하게 됨
Rust에서 “객체 수프(object soup)” 같은 접근은 잘 먹히지 않지만, 사실 그게 근본적으로 더 쉬운 방법이라고 보진 않음, 단지 우리가 익숙해서 쉽게 느껴지는 것임
ergonomics(사용자 경험)는 측정하거나 수치화하기 어렵다는 전제를 받아들이면 위와 같은 논의가 계속 모호해짐
“borrow checker와의 싸움”은 Rust에서 어휘적(Lexical) lifetime만 이해했던 시기에서 기원한 이야기임
내 경험상 숙련된 Rust 개발자들은 곳곳에 Arc를 뿌려서 자동으로 garbage collection과 비슷하게 씀
숙련된 Rust 개발자도 Arc, Clone, Copy 등을 곳곳에 쓰는 오픈소스 Rust 프로젝트를 많이 봄
Zig의 장점은 C처럼 익숙하게 개발하면서도 언어나 툴링에서 안전성을 챙길 수 있는 기능들이 있음
나는 원글 내용에 대부분 동의하지 않음
Rust도 C나 Zig와 마찬가지로 lifetime, ownership, borrow scope에 대해 고민하게 되나, 차이는 컴파일러의 도움 유무임
아무리 똑똑해도 피곤하거나 산만할 때 실수하는 것이 인간임, 실수 인정이 곧 현명함임
Rust 컴파일러가 안전하다고 간주하는 프로그램의 공간이 충분히 넓지 않아, 꽤 자주 정상적인 프로그램을 거부함
예시: 구조체 Foo에서 bar와 baz가 각각 문자열일 때, bar를 가변 참조 후 baz를 불변 참조하려 하면 컴파일이 되지 않아, 이런 상황에서 코드 구조를 억지로 우회할 수밖에 없음
반론하자면, “실제론 괜찮은 상태인데 컴파일이 거부되는 경우를 피하기 위해” 두세 번째로 좋은 설계로 코드를 바꿔야 하는 것 자체가 큰 부담임
위 예시는 정말 훌륭한 사례 같음, 내 블로그나 기사에서 다뤄도 될지 묻고 싶음
위 코드를 보고 오히려 주장에 더 자신이 없어짐
모든 프로그램이 반드시 그렇게 "안전"할 필요 없음을 우리가 기억해야 함
많은 Unsafe 소프트웨어를 즐기며 성장함, Star Fox 64, MS Paint, FruityLoops 등
Zig의 창시자인 Andrew Kelley도 음악 제작 소프트웨어(DAW) 개발 환경이 없어서 Zig를 만들었다고 읽음, Zig가 그런 창의적 소프트웨어에 잘 어울린다고 생각함
누구든 메모리 버그에 민감하면 Rust 쓰면 됨
Super Mario World도 메모리 버그 때문에 더 재밌었다고 믿음
"안전"이란 "내 프로그램이 의도한대로 동작함"의 축약어임
약간 혼동되는데, 내 말이 안 좋은 의견이라 생각하는 이유가 메모리 안전이 중요하지 않다는 의미인가 궁금함
borrow checker의 가치가 과소평가된 점이 아쉬웠음
Rust의 borrow checker는 유효하지 않은 메모리 접근을 컴파일 타임에 보장해 줌
물론, 컴파일러 규칙을 지키는 코드 구조로 바꿔야 하는 불편은 있음
직접 Rust를 따로 쓸 때 lifetime annotation이 틀렸다는 생각이 들진 않았고, 번거러운 chore 같긴 했으나 금방 익숙해졌음
unsafe를 쓰지 않는 한, Rust에선 두 스레드가 동시에 같은 메모리 쓰기 불가함
"왜 CLI 도구에서 Zig가 더 실용적으로 느껴지는지"는 공감이 안 됨, Rust가 CVE(취약점) 방지 면에선 여전히 강점임
실제로 나는 대부분 GC 언어로도 충분한 작업을 하고, 다른 언어로 기여할 땐 Rust, Zig, C/C++ 모두 상관없이 씀
CLI 도구가 특별할 게 없다고?
unsafe를 안 쓴다고 두 스레드가 동시에 같은 메모리를 못 쓰는 건 아주 깔끔하게 떨어지지 않음
Rust에서 backlinks 구현이 너무 복잡하다는 점은 동의함
Rc, Weak, RefCell, .borrow() 등을 사용하면 가능하지만 쉽지 않음
짧게 실행되는 프로그램이라면 arena 할당도 방법임(CLI 도구가 뜻하는 바로 보임)
Rust는 거대한, 멀티스레드, 장시간 구동되는 어플리케이션에서 진짜 힘을 발휘함
내가 실제로 Rust로 대형 메타버스 클라이언트를 썼는데, 수십 개 쓰레드를 24시간 돌려도 메모리 누수, 크래시 없었음
같은 걸 C++로 하려면 QA팀과 Valgrind 같은 툴이 필수이고, 스크립트 언어는 성능상 너무 느림
나도 Rust로 지구 곡률과 중력 편차까지 반영한 물리 시뮬레이션 비행기를 만들었음
Zig가 매력적이긴 한데 D도 여전히 존재하고, 개인적으로 D가 내가 원하는 C/C++ 대체라고 느껴짐
Zig의 문법이 뭔가 어색하고, Rust는 이미 생태계에서 중심이 되고 있음
Go 역시 여러 언어 툴에서 점유율이 높고, AI 분야에선 Python 다음으로 많이 쓰임
Rust 이전에 Go vs. D 논쟁이 있었고, 나도 D 교재까지 샀었다가 Go에 넘어감
D가 좋긴 하지만 대중화될 킬러앱이 안 나옴
Rust나 Zig로 굳이 CLI 툴을 써야 할 이유를 잘 모르겠음
IO가 병목이지, GC가 느려서가 아님
GC 이슈는 게임, DB 등 메모리 집중형이 아니면 논점이 아니라고 생각함
메모리 안전성 논쟁보다는 GC가 필요 없는 언어를 선택해야 하는 이유를 더 고민하는 편이란 점을 강조함
만약 “노-GC가 재밌어서” 쓰는 거라면 그 자체로 충분함, 논쟁 필요 없음
즉각적인 스타트업 타임(실행 지연 없음)이 아주 유익함
Go로 CLI 만드는 게 매우 괜찮았음(비록 Go 언어 자체는 선호하지 않음)
sum type, 패턴 매칭, async 지원이 있는 언어를 1순위로 고름
GC 없는 개발이 게임 분야에만 해당된다는 지적에 대해
GC 논쟁은 일종의 밴드왜건 느낌임
Rust의 빌트인 borrow/referencing으로 간단한 노트 툴을 만들었는데, 생각만큼 복잡하지 않았음
notes 리스트의 인덱스를 저장하고 맵으로 연결하는 구조를 상상하면, 속도 차이도 거의 없고, 안전성 단점도 없음
인덱스 실수해도 범위를 벗어난 에러로 잡을 수 있어, 커널 메모리를 덮어쓰는 것보다 훨씬 좋음
printf debugging 때도 훨씬 쉽고 직관적임
raw pointer나 reference는 보통 allocator, async runtime처럼 정말 필요한 곳에만 쓰고, 일반적 로직에는 index-based가 더 맞음
유명하게도 Rust async가 self-referential struct를 못 써서 Pin 관련 이슈가 생기는 이유도 여기에 있음
vec에 저장된 값의 포인터는 realloc 등이 일어나면 무효가 되므로, 이땐 Miri에서 바로 오류가 남
C++ 개발자인 내가 안전한 언어를 찾는다면 Swift가 제일 적합하다고 느낌
친숙하거나 닮은 언어가 더 금방 적응 가능함
Swift는 최근 크로스플랫폼 지원도 강화되었고, 현직 C++ 표준위원회 사람들이 여러명 참여함
하지만 Apple 연관성, 네이티브 UI 프레임워크 부재 등으로 비애플 진영 확장은 상대적으로 덜 함
Swift가 더 많이 인기 얻길 희망함
Swift와 Zig/C를 비교할 수 있는 리소스 있으면 추천해주면 좋겠음
Zig도 적당한 주의로 메모리 안전 소프트웨어를 만들 수 있다는 말이 있는데, 사실 C도 일정 수준 disciplined하게 쓰면 같은 결과가 나옴
결국 이 “조금의 절제(훈련)”가 현실에선 부족해서 문제가 발생함
Zig는 추가적으로 아래 문제들을 해결함
C가 50년 넘게 이런 discipline 문제로 실패했다면, "샤오린의 도" 이상으로 어려운 일임