Rust가 C++를 대체할 수 있을까?
IT 관련 뉴스를 보다 보면, Rust (러스트) 언어가 자주 언급되는 것을 볼 수 있습니다. 그런 기사를 보면, 여러 기업 (Google
, AWS
등)과 프로젝트(Deno
, Redox
등)의 개발 언어가 C++에서 Rust로 대체 또는 사용된다는 내용을 볼 수 있습니다. (심지어 Linux 커널에도 러스트가 도입되는 계획이 있습니다.)
아마 "Rust vs C++"
가 주제인 논쟁이 자주 벌어지는 이유는, 두 언어의 사용처가 비슷하기 때문이겠죠.
이번 글은 러스트는 C++ 대신 사용하기 좋으며, 정말로 C++를 대체할 수 있을까? 에 대한 글입니다.
들어가기 앞서, 필자는 C++ 전공이 아니기 때문에 틀린 정보가 있을 수 도 있습니다. 이에 대해 반박하셔도 좋습니다.
러스트를 접해보았다면, C++과 상당히 비슷한 부분이 상당히 존재한다는 것을 알 수 있습니다.
안전한 러스트에선 전반적으로 RAII
(Resource Acquisition Is Initialization
) 패턴을 사용합니다.
이는 C++에서 유래되었습니다.
안전한 러스트
여기서 안전한 러스트는 다음과 같은 보장을 말합니다:
- 소유권과 참조, 수명을 컴파일 타임에 검사합니다.
- 소유권과 수명은 러스트의 가비지 컬렉터를 대신하여, 메모리 관리를 위해 고려된 생소한 개념입니다. (C++에도
unique_ptr
등의 소유권 개념이 있긴 합니다만.) - * 소유권과 수명을 이 글에선 서술하지 않습니다. 모든 값은 소유권과 수명을 가지고 있고, 이의 유효성을 컴파일 타임에 검사함으로써, 런타임 시 안전성을 보장한다는 것만 알아둡시다.
- 참조는 후술할 로우 포인터에 몇가지 안전성을 보장하는 시스템을 적용한 러스트의 기능입니다. 최종적으로는 로우 포인터로 컴파일됩니다.
- 소유권과 수명은 러스트의 가비지 컬렉터를 대신하여, 메모리 관리를 위해 고려된 생소한 개념입니다. (C++에도
null
이 없습니다. (=null pointer
에러가 없습니다.)- 가변성을 컴파일 타임에 검사합니다. 불변의 변수는 수정이 불가능하며,
mut
키워드를 통해 가변 변수를 선언할 수 있습니다. - 예외 대신
Result<T, E>
를 사용합니다. (패닉(panic
)이 존재하나, 디버그 (또는 테스트)가 아니라면, 프로그래머의 잘못이 아닌 이상 발생하진 않습니다.)
안전하지 않은 러스트
러스트가 안전하기만 하다고 서술하지 않고, 안전한 러스트라 서술한 이유는, 고급 기능인 안전하지 않는 (unsafe
) 러스트가 존재하기 때문입니다.
안전하지 않는 러스트는 다음과 같은 기능을 가집니다.
- 로우 포인터(
raw pointer
)를 역참조 할 수 있습니다. (=null
이 발생할 수 있습니다.) - 안전하지 않는 함수 호출할 수 있으며, 안전하지 않는 트레잇을 구현할 수 있습니다.
- 가변 정적 변수를 수정할 수 있습니다. (여기선 다루지 않습니다.)
즉, 러스트는 메모리 안전을 보장으로 하나, 이를 강제하지 않는 안전하지 않는 러스트를 가지고 있습니다.
이 글은 러스트의 unsafe
를 다루는 내용은 아니니, 이렇게 2가지의 러스트가 있다는 것만 알아둡시다.
또한 러스트는 C++의 거의 모든 (언어 레벨, 표준 라이브러리) 기능을 가지고 있습니다.
예를 들어, C++의 shared_ptr
은 러스트의 Rc<T>
(가변일 경우 Rc<RefCell<T>>
등), thread-safe
에서 사용할 경우 Arc<Mutex<T>>
또는 Arc<RwLock<T>>
) 등이 있습니다.
이를 바탕으로 C++와 러스트를 비교해봅시다:
러스트의 특징과 단점:
- 위에서 설명했듯이, (안전한 러스트에서) 메모리 안전을 보장합니다.
- 가비지 컬렉터가 없습니다.
null
이 없습니다.- 병렬 프로그래밍, 함수형 프로그래밍, 시스템 프로그래밍을 지원합니다.
Cargo
라는 패키지 매니저로, 강력한 패키지 관리를 지원합니다.- C++에 비해, 문서(자료)가 많이 없습니다.
- 생태계가 C++에 비해 매우 작습니다.
C++의 특징과 단점:
- C 언어의 절차적 프로그래밍을 기반으로 객체지향 프로그래밍, 템플릿 등을 사용하는 일반화 프로그래밍을 지원합니다.
- 러스트와 반대로, 문서(자료)가 많으며, 한국어 자료 또한 매우 많아서, 자료를 참고하기 좋습니다.
- 생태계가 상당히 구축되어있습니다.
- 러스트에 비해 메모리 관리가 어렵습니다 (메모리 안전을 보장하지 않습니다.) (물론 스마트 포인터
unique_ptr
(러스트의 소유권과 유사),RAII
패턴 등을 이용하면 어느 정도 방지할 수 있긴합니다만,) - 생산성이 안 좋으며, 디버깅 및 유지보수가 힘듭니다.
- 이렇다 할 패키지 매니저가 없습니다. (컴파일러가 러스트 처럼 단일하지 않습니다.)
둘 모두 서술되어있는 항목보다 더 많을 수도 있습니다. 이렇게만 보면, 러스트가 훨씬 좋아 보이는데, 그런데도 왜 아직까지 러스트보다 C++이 더 많이 쓰이는 걸까요?
러스트의 생태계
위에서 말한 대로, 러스트는 C++에 비해 생태계가 매우 매우 작습니다. 이 뜻은 문서(자료), 커뮤니티 등이 C++에 비해 부족하다는 뜻이며, 결국 이는 이번 주제 (C++ vs Rust)에서 결정적인 증거가 됩니다.
여러 러스트 사용자들이 생태계를 구축하기 위해, 노력하고 있긴합니다.
당장 한국만 해도 한국 러스트 사용자 그룹, Rust Book 한국어 번역 등의 노력이 보이긴 하나, C++에 비빌정도는 택도 안됩니다.
절대 C++를 대체할 수 없는 것일까?
그럼 러스트는 절대 C++를 대체할 수 없는 것일까요? 이건 또 아닙니다.
C++는 사실상 완벽한 생태계를 가지고 있고, 러스트는 생태계를 구축하는 중입니다.
이 뜻은 러스트가 C++를 충분히 대체할 수 있다는 얘기와 같습니다. 생태계가 작긴 하지만, 러스트는 표준 라이브러리 및 언어 문서화가 상당히 잘 되어있습니다.
그럼 영어도 능숙하게 할 수 있고, 메모리 안전성도 보장하고 싶으니, 러스트를 쓰겠다고 하는 사람도 분명 있겠죠. 언어의 선택은 본인의 자유이며, 언어마다 각자 장단점이 있긴 하지만, 러스트와 C++에 대해 한 가지만 말하고 글을 끝내겠습니다.
러스트는 메모리 안전을 보장으로 합니다. 하지만 그것에 완벽하다는 것은 아닙니다:
또한 C++은 발표된 지 무려 37년이 넘은 언어입니다. (러스트는 첫 릴리즈가 12년 전) 그런데도 메모리 안전성을 보장하지 않는 C++를 37년이 넘게 써왔습니다.
결국 이것은 프로그래머들이 큰 문제없이 써왔다는 것이며, 이는 곧 프로그래머에 따라, 메모리 안전을 보장할 수 있다는 뜻으로 해석할 수 있습니다. C++가 잘못된 언어가 아납니다. 러스트가 완벽한 언어는 아니며, 모든 언어는 장단점을 가지고 있습니다.
대기업 또는 큰 프로젝트에서 러스트로 대체한다는 건, 러스트의 장점에 반한 경우이며, 아직 C++로 작성되어있는 (또는 작성될) 프로젝트는 이보다 더 많습니다. (심지어 러스트로 대체한다는 계획을 절대 세우지 않는 프로젝트도 있을 겁니다.)
지금 당장은 러스트는 C++를 대체하기엔 어렵습니다. 하지만, 앞으로의 상황을 우린 알지 못합니다. 언젠간 러스트의 생태계가 커지고, C++를 대체하는 날이 올 수 도 있을겁니다.
이 주제에 대해 중립을 띄고 싶다면, 둘다 배워두시는 것도 좋은 방법입니다.