C++를 통해 Rust의 매력을 보여준 Matt Godbolt의 설득
(collabora.com)- 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처럼 근본적인 안전성과 명확성을 제공하긴 어렵다는 점이 드러남
참고
- 강연: Correct by Construction: APIs That Are Easy to Use and Hard to Misuse
- Matt Godbolt의 활동 및 Compiler Explorer
c++의 단점이라고 드는 부분은 대부분 c언어와의 호환성 때문에 유지되는 내용이 대부분이군요.
c와의 호환성을 버리고 개발 할 수 있게 바꿀 수 있을까요?
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"에 관심이 있다면 들어볼 만함