Intro
최근 들어 저는 Rust를 시작했습니다. 개발경력이 C embedded를 시작으로 해서 최근은 Python Application에 몸담고 있는 와중에 Rust를 왜 시작하게 되었을까요? Rust는 저에게 꽤 이상적인(실용적인지는 아직 잘 모르겠습니다) 언어였기 때문입니다. 개인적으로 느낀 Rust의 감상은 2가지 입니다.
Rust에 대한 개인적인 감상
1. GC가 없다.
GC로 인해 내가 Memory를 관리하지 않아도 되지만, 그것은 즉 memory에 대한 내가 세부적으로 제어할 수 없는 내부 동작이 있다는 의미이기도 합니다. 이는 곧 성능 최적화를 방해하는 요소가 되기도 합니다. 요즘 언어들은 대부분 GC를 가지고 있습니다. Java부터 Python, Javascript까지 요즘 Application을 담당하는 언어 중 GC가 없는 언어는 없다고 봅니다. GC가 없는 언어는 C/C++이 여전히 Major합니다. 이전에는 C를 많이 다뤄서 C로 알고리즘 문제도 많이 풀고는 했는데 Python을 꽤 쓰다보니 개발 속도는 늘었지만 C만의 그 빡빡하면서도 Machine의 성능을 잘 뽑아냈던 그 경험이 많이 그리웠습니다.
2. 현대적이다.
C/C++은 자유도가 꽤 높아 개발자의 실수나 관리 미숙이 Compiler에서 잡히지 않고 Runtime에서 null pointer같은 문제로 Program을 panic에 빠뜨리기 쉽다는 문제가 있습니다. 물론 smart pointer같은 C++11 표준이 들어오기는 했지만 뭔가 부족했습니다. 이런 문제들을 Compiler가 잡아줄 수 없을까, 최신의 철학과 많은 경험을 포함하여 새로 만들어진 언어가 없을까 하던 차에 Rust를 알게 되었습니다. Rust는 C++가 가지고 있는 "개발자가 저지를 수 있는 실수"를 "compile time"에서 잡을 수 있도록 다양한 규칙을 두고 있습니다. (물론 이 규칙이 C++의 모든 문제를 해결할 수 있다는 것은 아닙니다.)
문제 | C++ | Rust |
Dangling Pointer | 객체를 Delete한 후에도 객체를 가리키는 pointer가 남는 경우 | Ownership과 Lifetime으로 메모리 해제 후에 포인터가 남지 않도록 합니다. |
Double Free | 동일한 메모리를 두 번 해제하려 하는 행위 | Ownership으로 하나의 자원은 하나의 소유자만 가질 수 있음. Scope를 벗어나면 자원이 자동으로 해제되어 double free가 발생할 가능성을 원천 차단합니다. |
Use After Free | 객체의 메모리를 해제한 후에도 해당 포인터를 통해 접근하려는 행위 | Ownership으로 하나의 자원은 하나의 소유자만 가질 수 있음. Scope를 벗어나면 자원이 자동으로 해제되어 double free가 발생할 가능성을 원천 차단합니다. |
Data Race | 멀티스레드 환경에서 두개 이상의 스레드가 동시에 동일한 메모리 위치를 읽고 쓰려고 하는 행위. | 동시성 안정성(Concurrency Safety)를 Compiler level에서 보장. Rust의 borrow checker는 동일한 메모리에 여러개의 가변참조를 허용하지 않음. 다중 스레드 사용 시 안전한 동기화 메커니즘을 강제함. |
Unchecked Type Casting | reinterpret_cast 등을 통해 Unchecked Type Casting이 가능하므로 실수로 잘못된 Type변환 잠재성이 있음. | 안전하지 않은 Type Casting을 엄격하게 제안함. 만약 위험한 Casting이 필요한 경우 unsafe block안에서만 수행할 수 있므으로 위험한 Casting에 대한 명시적 표기를 할 수 있음 |
Null Pointer Dereference | nullptr가 있음. 역참조 하면 프로그램 충돌. | rust는 null값이 없음. 대신 Option를 통해 Some, None 확인 후 값을 명시적으로 처리 |
Manual Memory Management | 메모리 관리를 직접 수행해야 하므로 메모리 누수, 메모리를 잘못 해제하는 잠재적 위험이 있음 | Borrowing mechanism은 메모리 누수를 줄여주며 일반적인 상황에서는 메모리 해제를 수동적으로 할 필요가 없음. |
요약하자면, Rust의 Programming 규칙들은 C++에서 "개발자의 실수로 인해" 발생할 수 있는 다양한 메모리 관리 문제와 동시성 문제를 방지하기 위해 설계되었다는 것입니다.
이런 특성들은 Rust에 C embedded의 HW적인 static한 성격과 현대적인 Python의 편리함을 동시에 만족하는 언어라는 생각이 들게 되었고, 저는 Side Project를 Rust로 시작하게 되었습니다.
Rust를 좀 더 공부해 보자 많은 분야에서 사용이 가능하다는 것을 알게 되었습니다.
- System Programming
- Embedded System
- Web application Backend server (Actix, Rocket)
- Web Application Frontend wasm (Yew, Leptos)
- Game Application (Bevy)
- Blockchain (Solana, Polkadot)
- Data Engineering (Polars)
생각보다 많은 분야에서 Rust는 사용할 수 있다는 것을 알 수 있습니다 그렇다면 rust는 C++을 대체할 수 있을까요?
그래서 Rust는 C++을 대체할 수 있는가?
Rust의 장점이 많음에도 불구하고 여전히 Rust는 C++을 넘어야 할 여러가지 벽이 있습니다.
- 기존 코드와 생태계의 방대함 : 수십년간 쌓아온 방대한 코드베이스와 라이브러리, 개발자 Pool의 크기를 비교하면 Rust는 C++의 규모를 따라 잡기에는 아직 한참 멀었습니다.
- Low Level System Programming과의 호환성 : Kernel, Driver, Firmware, H/W 접근 분야에서 C/C++은 표준이나 다름없습니다. Rust는 아직 이런 분야에서 표준으로 불리기는 어렵습니다.
- Tool Chain : 다양한 플랫폼과 Compiler, debugger, Profiler와 같은 도구들이 오랜 시간동안 성숙해 왔습니다. GCC, Clang같은 Compiler가 대표적입니다. Rust의 프로젝트 관리자인 cargo나 compiler인 rustc도 좋은 tool이지만 C++ 수준의 다양한 분야의 지원 측면에 대해선 제한적입니다.
- C++과의 호환성 : C++을 대체한다는 것은 C++과의 호환성도 어느정도 수준에 올라와야 합니다. C의 경우 extern "C"로 어느정도 수준은 지원 하지만 C++의 vtable, exception handling, template metaprogramming같은 영역에서는 Rust의 직접 호환을 기대하기 어렵습니다.
- Learning curve : C++의 교육자료, 커뮤니티는 몇십년동안 발전해 왔습니다. 반면 rust는 비교적 새로운 언어입니다. 교육자료나 커뮤니티가 성숙할 시간이 더 필요할 것입니다. (rust 1.0은 2015년 05월 15일에 release되었습니다.)
특히 Rust의 엄격한 메모리 안전 규칙을 위한 Ownership, Borrowing rule과 같은 규칙은 다른 Programming에서는 볼 수 없는 완전 독창적이며 새로운 규칙입니다. 이는 Rust의 학습곡선을 더욱 가파르게 만들 수 있습니다.
(물론 Senior 수준에 다다르는데는 C++이 더 오래 걸릴 수도 있습니다ㅎㅎ)
Rust에 대한 설명은 이 정도로 충분한 것 같습니다. 이제 Rust의 문법에 대해서 간단한 Code를 작성해 보도록 하겠습니다.
Tutorial
Rust 1.79.0 (released 2024-06-13)
- Cargo 사용법 : https://tyoon9781.tistory.com/entry/rust-tutorial-2-cargo
- Variables : https://tyoon9781.tistory.com/entry/rust-tutorial-3-variables
- Data Type : https://tyoon9781.tistory.com/entry/rust-tutorial-4-data-type
* reference
'Rust > Basic' 카테고리의 다른 글
[Rust Tutorial] 6 - Control Flow (0) | 2024.11.17 |
---|---|
[Rust Tutorial] 5 - Function (0) | 2024.11.17 |
[Rust Tutorial] 4 - Data Type (0) | 2024.11.14 |
[Rust Tutorial] 3 - Variables (0) | 2024.11.14 |
[Rust Tutorial] 2 - Cargo 사용법 (0) | 2024.11.14 |