7P by GN⁺ 2일전 | ★ favorite | 댓글 4개
  • 20년 이상 C++을 사용한 저자가 Rust의 장점을 재발견하게 된 계기를 Matt Godbolt의 강연을 통해 소개함
  • C++에서는 타입 혼동에 의한 실수가 컴파일러에서 제대로 잡히지 않지만, Rust는 이를 컴파일 타임에 강하게 차단
  • Rust는 단순한 메모리 안전성 외에도 API 오용 방지에 유리한 설계를 갖고 있음
  • 특히 런타임 입력 처리에서도 Rust는 에러를 명시적으로 처리하도록 강제하여 위험을 줄임
  • 결국 언어 설계가 개발자의 실수를 방지하는 강력한 도구가 될 수 있음을 보여주는 사례임

서론

  • Matt Godbolt의 강연 "Correct by Construction"은 C++의 API 설계 문제를 조명하고 있으며, 이는 Rust의 철학과도 부합함
  • Rust의 강점을 이해하는 데 있어 이 강연은 좋은 입문 자료임

What's in a type — C++의 한계

  • void sendOrder(const char *symbol, bool buy, int quantity, double price) 같은 함수 시그니처는 매우 오류에 취약함
  • bool, int, double 등의 기본 타입만 사용하면, 타입을 잘못 넣어도 컴파일러가 경고하지 않음
  • using Price = double 같은 타입 별칭은 실제 타입 구분 기능이 없음
  • 클래스와 explicit 생성자를 사용하여 Quantity, Price를 만들고 나면 컴파일러가 일부 오류는 잡아주지만:
    • 음수 값도 허용되며, 이는 런타임에만 문제가 됨
    • static_assert와 템플릿을 활용하면 컴파일 타임 체크를 강제로 할 수 있음
    • 하지만 여전히 atoi 같은 런타임 변환은 정수 오버플로우를 유발하며 컴파일러는 감지하지 못함

Rust는 어떻게 다를까?

  • 동일한 함수 정의에서도 Rust는 타입 불일치를 컴파일 시점에서 명확하게 오류로 표시함
  • struct Price(pub f64); struct Quantity(pub u64); 와 같은 새로운 타입 정의도 간단하며, 음수 입력 차단도 자연스럽게 동작함
  • "string".parse::<u64>() 처럼 런타임 문자열 변환도 명시적 오류 처리가 필요함
  • .expect()로 강제로 값 언래핑을 하면 런타임 크래시가 발생하지만, 이는 C++의 침묵 속 오류보다 낫다는 점이 강조됨

결론

  • Rust는 단순한 메모리 안정성 이상으로 API 오용 방지, 컴파일 타임 체크, 명확한 타입 시스템을 통해 개발자를 보호함
  • 언어 설계의 힘이 개발자의 실수를 미연에 방지할 수 있음을 보여줌
  • Rust 초심자는 빌림 검사기(borrow checker) 와 싸우는 어려움을 겪을 수 있지만, 이는 시간이 지나면 해결됨
  • C++는 역사적으로 많은 발전이 있었지만, 여전히 Rust처럼 근본적인 안전성과 명확성을 제공하긴 어렵다는 점이 드러남

참고

c++의 단점이라고 드는 부분은 대부분 c언어와의 호환성 때문에 유지되는 내용이 대부분이군요.
c와의 호환성을 버리고 개발 할 수 있게 바꿀 수 있을까요?

unsafe 를 제공하지 않았다면 더 좋았을텐데 말이죠.

Hacker News 의견
  • Rust의 가장 큰 장점은 오류 전파 방식이 단일화된 Result 타입임. 예외 처리나 다양한 오류 반환 방식에 신경 쓸 필요가 없다는 점이 매력적임

    • ? 단축키와 Result의 함수형 인터페이스 덕분에 오류 처리가 재미있고 쉽게 다룰 수 있음
    • C++의 복잡한 오류 처리 방식에 비해 일관성이 부족한 점이 불만임
  • C++에 대한 불만이 많음. 특히, 많은 규칙을 기억해야 하고 하나라도 틀리면 코드가 취약해질 수 있다는 점이 문제임

    • C++의 안전성을 높이기 위해 Rust의 안전한 방식과 유사한 접근이 필요함
  • 현재 작성하는 C++ 코드는 Rust와 유사함. 명시적이고 강력한 타입, 명확한 수명 관리 등을 사용함

    • Rust 컴파일러가 버그를 잡고 오류를 보고하는 데 더 도움이 됨
  • C++의 암시적 변환 문제는 언어보다는 라이브러리의 문제임

    • C++에서도 Rust와 유사한 기능을 구현할 수 있지만, 라이브러리 지원이 필요함
  • Rust는 키워드 인자나 이름이 있는 튜플이 없어 Args/Options 구조체를 사용하는 데 불편함이 있음

  • -Wconversion 옵션은 특정 변환 문제를 잡을 수 있지만, 모든 경우에 적용되지는 않음

    • 예를 들어, 1000.0을 1000으로 변환하는 것은 정확도 손실이 없다고 간주됨
  • Rust가 더 나은 점은 암시적 숫자 변환이 없다는 것임. C++에서는 atoi를 사용하지 말고 STL의 변환 함수를 사용하는 것이 좋음

  • SQL의 제약 조건이나 pydantic의 사용자 정의 타입 및 검증자와 유사한 기능이 Rust나 Golang에는 아직 없음

  • Matt와 Ben Rady의 프로그래밍 팟캐스트 "Two's Complement"에 관심이 있다면 들어볼 만함