최근 수정 시각 : 2022-08-11 23:36:33

Rust


파일:나무위키+유도.png  
은(는) 여기로 연결됩니다.
게임에 대한 내용은 러스트(게임) 문서
번 문단을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
참고하십시오.
프로그래밍 사이트 선정 상위 점유율 프로그래밍 언어 목록
{{{#!wiki style="margin: 0 -10px -5px"
{{{#!wiki style="display:inline-block; margin:0 0 -5px; min-width:25%"
{{{#!folding ⠀[ IEEE Spectrum 2021 ]⠀
{{{#!wiki style="margin:-6px -1px -10px"
IEEE Spectrum에서 집계한 2021년 기준, 웹 분야 상위 10개 프로그래밍 언어
1 Python 2 Java 3 Javascript 4 C# 5 Go
6 HTML 7 PHP 8 Dart 9 Ruby 10 Rust
IEEE Spectrum에서 집계한 2021년 기준, 모바일 분야 상위 10개 프로그래밍 언어
1 Java 2 C 3 C++ 4 C# 5 Swift
6 Dart 7 Kotlin 8 Scala 9 Objective-C 10 Delphi
}}}}}}}}}
⠀[ Stack Overflow 2021 ]⠀
||<table width=100%><width=2000><-10><bgcolor=#FFA500><table bgcolor=#fff,#222> Stack Overflow에서 조사한 2021년 기준 사용률 상위 25개 프로그래밍 언어
1 JavaScript 2 HTML, CSS 3 Python 4 SQL 5 Java
6 Node.js 7 TypeScript 8 C# 9 Bash 10 C++
11 PHP 12 C 13 PowerShell 14 Go 15 Kotlin
16 Rust 17 Ruby 18 Dart 19 어셈블리어 20 Swift
21 R 22 VBA 23 MATLAB 24 Groovy 25 Objective-C
⠀[ TIOBE 2022 ]⠀
||<table width=100%><width=2000><-10><bgcolor=deepskyblue><table bgcolor=#fff,#222> TIOBE에서 선정한 2022년 2월 기준 검색어 점유율 상위 20개 프로그래밍 언어
1 Python 2 C 3 Java 4 C++ 5 C#
6 Visual Basic .NET 7 JavaScript 8 PHP 9 어셈블리어 10 SQL
11 Classic
Visual Basic
12 R 13 Go 14 Fortran 15 Groovy
16 Swift 17 Ruby 18 Perl 19 MATLAB 20 Delphi /
Object Pascal
{{{#!wiki style="margin:0 -10px -5px"
{{{#!folding [ 21위 ~ 50위 펼치기 · 접기 ]
{{{#!wiki style="margin:-6px -1px -10px"
21 Objective-C 22 Prolog 23 Scratch 24 SAS 25 LISP
26 COBOL 27 Rust 28 Ada 29 Dart 30 Transact-SQL
31 PL/SQL 32 ABAP 33 VBScript 34 LabVIEW 35 Julia
36 Scala 37 TypeScript 38 Kotlin 39 Haskell 40 Lua
41 Apex 42 Visual FoxPro 43 Bash 44 Scheme 45 D
46 PL/I 47 Elixir 48 Logo 49 PostScript 50 Ladder Logic }}}}}}}}}
⠀[ PYPL 2022 ]⠀
||<table width=100%><width=2000><-10><bgcolor=green><table bgcolor=#fff,#222> PYPL에서 선정한 2022년 3월 기준 검색어 점유율 상위 20개 프로그래밍 언어
1 Python 2 Java 3 JavaScript 4 C# 5 C/ C++
6 PHP 7 R 8 Objective-C 9 TypeScript 10 Swift
11 MATLAB 12 Kotlin 13 Go 14 Rust 15 Ruby
16 VBA 17 Ada 18 Abap 19 Dart 20 Visual Basic
}}}
프로그래밍 언어 목록 · 분류 · 문법

#!syntax rust
fn main() {
    println!("hello world");
}

러스트
Rust
파일:Rust 로고.svg
최초 개발자 그레이던 호어
개발 모질라 재단 러스트 재단
버전 1.62.1 ( 2022년 7월 19일)
웹사이트 파일:홈페이지 아이콘.svg 파일:GitHub 아이콘.svg 파일:cargo.rs.png
1. 개요2. 역사3. 언어의 특징
3.1. 안전한 메모리 관리
3.1.1. 소유권과 수명3.1.2. 가변성
3.2. 철저한 에러 관리3.3. 유연하고 편리한 enum3.4. 트레이트
3.4.1. 특수한 트레이트
3.5. 하이지닉 매크로3.6. 비동기 프로그래밍3.7. 제네릭
4. 개발 도구별 특징
4.1. 안전하고 강력한 컴파일러4.2. 패키지 관리 도구 Cargo4.3. IDE 지원 현황
5. 주목받고 있는 언어
5.1. 개발자들이 가장 좋아하는 언어5.2. 대기업에 주목받고 있는 언어5.3. 안드로이드 운영체제 개발 언어
6. 사용 현황 및 전망
6.1. 전망6.2. 기존 언어와의 비교
6.2.1. Rust vs C++
6.2.1.1. 결론
6.2.2. Rust vs Carbon
6.3. 실무에서의 사용
6.3.1. Rust를 사용하는 기업6.3.2. Rust로 제작된 것들
7. 도서
7.1. The book7.2. 그 외
8. 관련 링크

1. 개요

러스트 재단에서 개발되고 있는 메모리 안전성과 성능 및 편의성에 중점을 둔 프로그래밍 언어. 가비지 컬렉터 없이 메모리 안전성을 제공하는 대표적인 언어다. C++를 대체하기 위한 목적도 있다.

모질라 재단에서 2010년 7월 7일에 처음 발표했으며, 2015년 5월 15일에 안정 버전이 정식 발표된 이후, 2021년 2월부터는 러스트 재단으로 분리되어 AWS, Google, 화웨이, MS, 모질라 재단을 초기 회원사로 발족했다.

이 언어를 대표하는 키워드 몇 개를 나열해보면 안전성, 속도, 병렬 프로그래밍, 함수형 프로그래밍, 시스템 프로그래밍이 있다. Go보다는 반 년 늦게 나왔지만[1] 그나마 비슷한 시기에 등장했다는 점과 두 언어 모두 C/C++를 서로 다른 방향에서 대체하려 한다는 점 때문에 라이벌 관계로 엮이기도 한다.

온라인 상으로 표준 라이브러리 기반의 코드를 실행해볼 수 있다. #

Rust의 마스코트[2]도 있는데, 이름은 페리스(Ferris)다. 밝은 주황색의 게 모양을 하고 있으며, 러스트 관련 커뮤니티나 미디어에서 자주 등장한다[3]. 또한 이 페리스 때문에 Rust 개발자는 스스로를 Rustacean[4][5]이라고 자칭한다.

2. 역사

자세한 내용은 Github의 rust-lang/rust 릴리스 참조.

2018년 12월 6일에 발표된 1.31.0 버전을 기점으로 Rust 2018 Edition으로 에디션이 변경되고 ( 가이드 북) 1.31.0 이전 버전은 Rust 2015 Edition으로 정의되었다. 약 3년 단위로 새로운 에디션을 선보일 예정이며, 이에 따라 Rust 2021 Edition이 준비중에 있다.

원래는 모질라 소속의 개발자인 그레이던 호어의 개인 프로젝트였으나, 모질라 재단의 차기 웹 브라우저 엔진 프로젝트인 서보(Servo)를 개발하는 데에 쓰기 위해 함께 연구 프로젝트로 편입되었다.[6] 자세한 내용은 서보 참고.

3. 언어의 특징

Rust는 현대적인 시스템 프로그래밍 언어로, C/C++와 동등한 수준의 속도를 달성하면서 안전성, 동시성을 목표로 한다. '안전하지 않은' 코드를 사용하여 '안전한' 코드로 추상화할 수 있는 도구 또한 언어 차원에서 제공한다. 안전한 코드는 C++의 RAII (Resource Acquisition Is Initialization)를 강제하고 참조하는 변수의 수명을 컴파일러에서 확인한다. 또한 함수형 프로그래밍 언어로부터 발전된 타입 시스템을 도입하였으며, 클래스 대신 다른 언어에서의 인터페이스와 비슷한 트레이트(Trait)라는 개념을 기반으로 다형성을 달성한다.[7] 타입이 강제되는 매크로를 사용해 언어를 확장하는 것이 가능하며, 현대적인 모듈 시스템을 통해 쉽게 모듈화될 수 있다.

null 포인터 에러가 언어 차원에서 존재할 수 없다. null이 존재하지 않고, 언어 차원에서 지원하는 Option<T>이라는 제네릭 enum이 존재한다. Option<T>Some(T) 혹은 None 둘 중 하나로 지정 될 수 있으며, None이 기존 프로그래밍 언어의 null 역할을 담당한다. 이 Option<T>을 통해서 데이터가 없다는 상태를 관리하기 때문에, 논리적으로 프로그래밍을 잘못해 버그가 생길 순 있어도[8] unsafe 코드[9]가 아닌 이상 메모리 오류는 발생하지 않는다.

타입의 모호함도 방지하기 위함인지 전위연산자와 후위연산자, ++나 --가 존재하지 않는다.

3.1. 안전한 메모리 관리

Rust는 메모리 관리의 안전성이 상당히 고려된 언어이다.[10] 무분별한 참조를 막는 제약이 있고, 오버헤드가 없는 안전한 메모리 관리를 위해 후술할 Ownership(소유권)과 Lifetime(수명)이라는 다른 언어에는 없는 개념을 이용해 컴파일 단계에서 메모리 관리를 한다. 여기에 더해, 컴파일 설정을 Debug(개발단계에 사용)로 해두면 Integer overflow같은 오류들도 런타임에 잡아낼 수 있고, overflow가 예상되는 지점에만 표준 라이브러리가 제공하는 기능들을 적용하면 release 버전에서도 overflow에 대한 예외처리를 할 수 있다.

Rust는 시스템 프로그래밍 언어이니만큼, Zero-cost abstraction(무비용 추상화)를 지향하기 때문에 쓰레기 수집을 사용하지 않는다[11]. 그리고 기본적으로 C/C++와 마찬가지로 시스템에서 메모리를 직접 할당받아 사용한다.[12][13] 포인터에서 값을 직접 가져오거나 함수를 호출하는 것은 금지된다. unsafe 스코프나 함수 내에서는 허용되지만, 이는 안전하지 않은 코드를 안전한 코드로 추상화하거나, 하드웨어를 직접 다루기 위해 존재하는 것이다. 최적화를 통한 퍼포먼스 향상에도 사용될 수 있지만 컴파일러보다 잘 할 자신이 없으면 이 의도로는 건들지 않는게 현명하다

3.1.1. 소유권과 수명

Rust에서 안전성을 위해 고려된, 기존 프로그래밍 언어에 비해 가장 차이점이 많은 시스템이다. Rust를 처음 사용하는 사람들이 가장 많이 생소해 하는 부분이며, 기존 프로그래밍 언어와의 큰 차이로 인해 이 시스템의 작동을 본 문단만으로 모두 이해하는 것은 어려우니 참고만 하면 된다.

소유권(Ownership)과 수명(Lifetime)을 통해 어떻게 안전한 메모리 관리를 이루어내는지를 간략하게 설명하자면, Rust에서 모든 값[14]은 그 값이 대입된 변수나 구조체 필드, 넘겨받은 함수 인자 등의 이름에 귀속된다. 이름은 자기에게 귀속된 값에 대한 소유권을 가지며, 다른 변수에게 값을 대입하면 그 이름으로 소유권이 이전되고, 기존 변수는 파기된다. 그러므로 기존 변수에 대한 소멸자는 호출되지 않는다.[15] 그런데, 러스트는 스택뿐만 아니라 힙에 할당되어 있는 값(value)도 그 값에 대해 소유권이 있는 변수가 스코프(Scope)를 나가면 할당이 해제된다. 값이 할당이 해제되지 않으면서 자신의 Scope밖으로 나갈 수 있는 방법은 단 두가지가 있는데, return을 통해 소유권을 외부로 넘기거나, 외부에서 reference된 객체가 내부에서 만들어진 객체의 소유권을 가져가는 방법 뿐이다. 값을 Scope 안쪽으로 집어넣을 수도 있는데, 함수 인자를 통해 소유권을 함수로 넘기면 함수가 끝나는 시점에 값의 할당 해제를 발생시킬 수도 있다. 이때, 변수[16]가 생성되고 소멸되기까지의 범위를 수명이라고 하고, 컴파일 타임에 레퍼런스의 수명을 값의 수명과 모두 비교하여 레퍼런스의 범위가 값의 범위를 절대 넘어서 살아남지 못하게 하는 방식으로 dangling 포인터를 방지한다.

Rust는 이렇게 소유권과 수명을 컴파일 타임에 추적할 수 있도록 설계되었으며, 스택 영역에 할당되는 객체와 변수의 생성과 소멸 시기를 컴파일 타임에 모두 결정한다. 참조자는 수명을 자동적으로 결정할 수 없는 경우도 있는데, 메소드나 함수의 (매개) 변수에 수명을 명시해주어야 한다. 이 부분이 기존 프로그래머들에게는 매우 생소하여 많은 프로그래머들이 컴파일 에러를 겪었던 원인 중 하나이다. 이러한 개념을 스마트 포인터와 혼동하는 경우가 있는데, 스마트 포인터는 힙 영역에 할당되는 객체를 자동적으로 관리하기 위한 것으로 객체의 수명이 런타임에 결정되므로, 위 개념과 스마트 포인터는 역할이 엄연히 다르다.

한편, 이와 같은 소유권의 특성으로 인해, a = b와 같은 연산은 기본적으로 복사 연산이 아닌 이동 연산이다.[17] b가 가지는 데이터의 소유권을 a로 이전하게 되며, b로는 데이터에 접근할 수 없게 된다. 다만, 단순 메모리 복사만 해도 되는 타입 (즉, memcpy로 복사해도 되는 타입)에는 #[derive(Copy)]와 같은 마커로 Copy Trait라는 복사 특성을 객체에 부여할 수 있다. 그러면, a = b과 같은 연산이 이동 연산 대신 복사 연산을 수행하도록 할 수 있다. std::vec::Vec과 같이 값을 단순히 복사하는 것으로 객체를 복제할 수 없는 경우 기본적으로 이동 연산을 그대로 사용하게 된다. 모든 정수, 실수, bool 타입은 Copy이기 때문에 프로그래밍 할때 거슬리는 수준은 아니다.

함수에 넘겨진 인자는 함수가 기본적으로 소유권을 가지게 된다. 함수가 반환하는 변수는 함수 바깥 스코프(Scope)로 소유권을 넘겨준다.[18] 만약 소유권을 넘겨주지 못한 채로 함수나 해당 스코프가 종료되면, 거기에 묶여 있던 변수도 수명이 끝나게 된다.

소유권 규칙에 따라 하나의 값은 언제나 하나의 이름으로만 접근할 수 있게 되는데, 실제로 이렇게만 프로그래밍을 하려면 제약이 너무 심하다. 따라서 Rust에서 다른 변수를 참조할 수 있도록 Borrowed pointer(`&`)[19]를 제공하고 있다. Borrowed pointer는 C나 C++에서의 포인터처럼 다른 변수를 참조할 수 있는데, 참조되는 변수는 참조하는 변수보다 수명이 같거나 길어야 한다. 쉽게 말하자면, "도서관에서 책을 빌렸으면 적어도 도서관이 망하기 전에는 책을 반납하시오"와 같다.[20] 책을 반납하러 도서관에 왔더니 이런 일이 생기면 안된다는 소리이다. 멀티 스레드 참조와 같은 상황으로 인해, 수명을 컴파일 타임에 결정 할 수 없는 경우 컴파일 에러가 발생하게 된다.

힙 영역에 할당하는 객체의 경우, Rust 표준 라이브러리에서 제공되는 std::boxed::Boxstd::rc::Rc를 통해 스마트 포인터를 사용할 수 있다. std::rc::Rc와 같은 Reference Counting(참조 횟수 계산) 스마트 포인터의 경우, 순환 참조에 의한 메모리 누수가 여전히 발생할 수 있다는 점에 유의하자. 이 경우 참조 횟수를 추가하지 않는 std::rc::Weak를 상황에 맞게 사용해서 해결 할 수 있다.

3.1.2. 가변성

Rust 언어에서는 모든 변수의 가변성을 명확하게 컴파일 타임에 구분한다. 변수 수정에 관한 규칙은 다음과 같다.
  • 한번 초기화된 변수는 기본적으로 읽기만 가능하고 변경이 불가능하다.
  • mut 키워드를 통해 변경 가능한 변수를 선언할 수 있다.
    • 참조의 경우, 변경 불가능한 변수를 변경 가능한 변수로 참조할 수 없다.
    • 가변 참조자는 스코프 내에서 두 개 이상 선언될 수 없다.

이러한 개념은 동시성을 제어하기 위해 설계된 것은 아니다. 멀티 스레드에서 변경 가능한 변수를 락이나 뮤텍스 없이 공유하는 것은 대부분의 경우에서 바람직한 방법이 아니다. 멀티 스레드 환경에서는, 변경 가능한 변수를 std::sync::Arcstd::sync::Mutex와 같이 동시성 제어를 제공하는 타입으로 묶어서 안전하게 관리할 수 있다.

3.2. 철저한 에러 관리

Rust에는 예외가 없다. 대신 에러를 함께 제공하고자 하는 타입 `T`를 Result<T, E>[21]로 묶어서 에러를 처리할 수 있도록 한다.

에러 처리를 철저히 관리하여 프로그램의 안정성을 보장한다. 에러를 처리해주어야 하는 경우 함수에서 Result<T, E>를 반환하는데, 에러를 처리할 것인지 패닉을 발생시켜 프로그램을 종료시킬 것인지 명시적으로 작성하도록 한다.

다른 언어의 예외와 비교하면 오버헤드가 거의 없기 때문에 Rust의 모토인 무비용 추상화(zero-cost abstraction)에 부합한다. C++의 경우 예외를 처리할 때 스택 되감기를 해야 하기 때문에 5000~10000 cycle에 달하는 오버헤드가 발생한다. 그래서 예외 자체를 비활성화하는 경우도 허다하나 표준 라이브러리를 사용하는 이상 예외를 피할 수 없다는 단점이 있다.

러스트 개발자들도 에러 처리가 귀찮다는 것을 알기 때문에 편의성을 높여주는 기능들이 러스트에 되어 있다. 예를 들면, 다음과 같이 함수를 호출하여 발생한 에러를 그대로 반환할 수도 있다.
#!syntax rust
use std::error::Error;

fn foo() -> Result<(), Box<dyn Error>> {
    bar()?;         // bar()에서 에러가 발생하면 이를 즉시 반환한다.
    Ok(())
} 

또한 러스트는 타입 유니온[22]이 없기 때문에 여러 에러를 한데 묶기 위해선 enum을 별도로 선언해야 한다. 이러한 귀찮음을 막고자 thiserror등 매크로 기반 서드파티 크레이트도 존재한다.

3.3. 유연하고 편리한 enum

Rust의 enum은 C/C++의 enum과 다르다. C/C++의 enum은 단순히 상수들에 이름을 붙인 것이지만, Rust는 각각의 열거 값을 구조체나 튜플로 정의할 수 있다. 그리고 내부에 값을 포함(bind)하는 것이 가능하며, 이때 해당 값의 소유권을 가져간다. 다양한 동작을 할 수 있도록 구조체나 튜플처럼 메서드를 추가하거나 트레이트를 구현할 수도 있다. enum의 크기는 열거 값 중 가장 큰 것의 크기에 따라 컴파일 타임에 결정된다.[23]

간단한 예시는 다음과 같다.
#!syntax rust
enum Action {
    Hello(String),
    Call { country: u16, number: String },
    ThankYou(String, i32),
    Unknown,
}

let action = Action::Hello(String::from("namu"));

match action {
    Action::Hello(name) => println!("hello {} again !", name),
    Action::Call { country, number } => println!("call at +{}{}", country, number),
    _ => println!("sorry, i do not know that action :("),
}

이렇게 enum을 설계함으로서 enum의 유연성을 극대화시켰으며, 그 결과로 러스트에서는 다른 언어의 switch에 해당하는 match 키워드가 자주 쓰인다. match 키워드를 이용하면 열거 값에 따라 분기하면서 구조 분해까지 한 번에 할 수 있다.

이 때 주의할 점은, match는 가능한 모든 분기를 검사하도록 강제된다.
#!syntax rust
enum State {
    Running,
    Waiting,
    Terminated,
}

let process_state: State = State::Waiting;

match process_state {
    State::Running => do_something(),
    State::Terminated => cleanup_process(),
    // error[E0004]: non-exhaustive patterns: `Waiting` not covered
    // State는 3가지 종류의 값이 될 수 있지만, 위 코드의 경우 2가지 밖에 핸들링되지 않았다.
    // 에러를 없애려면 Waiting시 정해진 동작을 할 수 있도록 다음 코드를 추가하자.
    // State::Waiting => todo!()
    // 모든 종류의 패턴을 한번에 처리하고 싶으면 _(wildcard pattern)을 사용하는 방법도 존재한다.
    // _ => todo!()
};
러스트 컴파일러는 enum 타입에 대한 정보를 가지고 주어진 match문이 가능한 모든 경우를 핸들링했는지 컴파일 타임에 검사한다. 만약 컴파일러가 충분히 똑똑하지 못했다면, 위 코드는 대기중인 프로세스를 처리하지 못하고 루프를 반복해서 돌기만 하는 버그를 일으켰을 수 있다. 덕분에 enum과 match문을 효과적으로 사용하는 러스트 개발자는 버그를 미연에 방지할 수 있으며, 조금 더 확신을 가지고 개발에 집중할 수 있다.

특히나 이 match 구문은 함수형 프로그래밍 언어 사용자들이라면 익숙할, 패턴 매칭 기능이다. elixir 만큼 자유로운 매칭까지는 아니지만 범위 매칭, @ 바인딩, 매치 가드 등 다양하고 풍부한 표현을 제공한다. 상술한 '값을 저장 가능한'(bindable) enum 또한 함수형 언어의 개념 중 하나인 모나드에서 가져온 아이디어이며, 이런 특성을 대폭 활용한 대표적인 enum으로 Result<T, E>, Option<T> 등이 있다. 이들은 언어 자체의 특별한 문법이 아니라 STL에 정의된 enum일 뿐이다.
#!syntax rust
enum Option<T> {
    None,
    Some(T),
} 
Some이 T를 소유하기 때문에 이를 앞서 본 것과 동일한 match문으로 검사하여 값이 있는지 없는지를 실수 없이 검증할 수 있다.

3.4. 트레이트

Rust는 클래스와 클래스간 상속이라는 개념이 존재하지 않는 대신 트레이트(Trait)가 존재한다. 트레이트는 객체의 특성을 나타냄과 동시에 그 특성과 관련한 인터페이스[24]를 제공한다. 객체에 Clone 트레이트를 구현하면 복제가 가능함을 나타냄과 동시에 clone() 메소드가 제공되어, 객체의 특성과 메소드가 하나의 묶음으로써 존재하게 된다.

트레이트는 객체와 달리 변수를 가질 수 없으며 상속이 가능하다. 그리고 impl T for A 블록을 작성해서 어떤 클래스에 트레이트를 구현하게 되면, 구현된 메서드를 사용할 수 있다. 트레이트에 메서드의 기본 구현이 있는 경우, 기본 구현을 그대로 사용하도록 하는 것도 가능하다.

트레이트가 가지는 중요한 역할 중 하나는, 제네릭 인자에 트레이트를 써서 인자로 들어갈 타입에 필요한 조건(특성)을 붙이는 것이다.[25] 이는 다른 언어의 덕 타이핑과 유사한 개념이며, Iterator를 구현한다면 (타입은 잘 모르겠지만) 순회 가능할 것이고, Fn을 구현한다면 클로저일 것이고, Ord를 구현한다면 (역시 구체적인 타입은 몰라도) 크기를 비교 가능한 값임을 알 수 있다. 예를 들어 값 세 개를 오름차순으로 정렬하는 제네릭 함수는 이렇게 만들 수 있다.

덕 타이핑에서 한 단계 더 나아가, '어떤 트레이트를 구현하는 타입이라면 이런 연산을 할 수 있을 것' 이라고 정의한 것이 바로 연산자 오버로딩(operator overload)이다. 가령 복소수를 표현하는 구조체를 만들고 Add를 구현해 복소수끼리의 덧셈을 정의했다면 일반 숫자를 다루듯이 + 연산자를 사용할 수 있다. 역참조 연산자인 * 또한 오버로딩 할 수 있으며, Deref Drop트레이트를 수동으로 구현해서 스마트 포인터를 만들 수 있다.

3.4.1. 특수한 트레이트

몇몇 트레이트(Trait)는 컴파일러에게 특수한 취급을 받는다. 이중 몇몇은 특수한 성질을 나타낼 때 쓰이고 몇몇은 문법적 추가 요소(Syntactic Sugar)로서 작동한다.
  • Send: 타입 T가 스레드 경계선을 넘나들 수 있음을 명시한다.
  • Sync: 타입 T의 참조가 스레드 경계선을 넘나들 수 있음을 명시한다. T: Sync&T: Send 와 동치이다. 기본적으로 모든 primitive type (u8, char 등) 은 Send/Sync 이고 이들을 사용한 파생 타입 또한 Send/Sync 이기 때문에 일반적으로 신경쓰지 않아도 변수를 자유롭게 스레드 간에 공유할 수 있다. 포인터와 같이 Send/Sync가 구현되지 않는 타입을 포함하는 경우 Send/Sync가 자동으로 구현되지 않는다. 개발자가 unsafe를 명시하여 구현할 수는 있으며 이 경우 스레드 안전성은 개발자가 책임을 갖게 된다. (예시: Cell<T>, AtomicUsize<T>)
  • Clone: 완전한 복제를 제공하도록 하는 트레이드. 이게 없는 객체는 =으로 이동 연산만 가능하다.
  • Copy: 필요한 경우 a = b에서 이동 연산 대신 복사 연산을 수행하도록 하는 트레이트. 단순히 타입의 값을 복사하는 것으로 복사가 가능한 타입에만 자동으로 구현되며 이를 수동으로 구현하는 것은 불가능하다. 모든 primitive type은 기본적으로 이 트레이트를 구현하고 있다.
  • Deref/DerefMut: *(역참조) 연산을 구현하는 트레이트. 스마트 포인터를 만들 때 유용하며, 따라서 Deref를 구현하는 객체는 거의 대부분의 경우에 &T 와 동일하게 사용할 수 있다. 또한 Deref트레이트를 구현하는 타입을 함수로 전달할 때, 타입이 맞지 않으면 러스트 컴파일러는 암묵적 자동 역참조(implicit deref coercions)를 사용해 해당 타입을 재귀적으로 역참조한다. 예를 들어, 슬라이스만 받는 함수를 벡터의 참조를 통해서도 호출할 수 있는데, 이는 &Vec<T>deref&[T]타입을 반환하기 때문이다. #
  • Sized: 컴파일 시 타입의 크기를 알 수 있는 경우를 명시.
  • Unpin: Pin을 통해 포인터가 고정된 타입을 이동 연산할 수 있는 경우를 명시.
이 외에 for 문에서 쉽게 사용될 수 있도록 하는 Iterator/IntoIterator 등의 trait 등도 존재한다.

3.5. 하이지닉 매크로

Rust의 매크로는 다음의 특징을 가지고 있다.
  • 매개 변수의 이름으로 인해 텍스트 중복이 되지 않도록 자동 처리된다.
  • 매크로에 입력될 매개 변수의 타입을 지정할 수 있다.
  • 메타 프로그래밍이 가능하다.

C/C++에서의 매크로는 단순한 문자열 치환이다. 예를 들어 MUL5(x) (x * 5)라고 한다면 MUL5(3)(3 * 5)로 치환될 것이다. 이것은 문맥에 따라 수많은 잠재적인 문제를 만들 수 있다. Rust는 LISP의 하이지닉 매크로 개념을 사용한다. 매크로는 단순한 텍스트가 아니며, 단순한 텍스트 중복이 문제가 안 되도록 컴파일러가 알아서 잘 처리한다. 단순한 문자열 치환이 아니라 문법의 일부이며, 전처리기가 아니라 컴파일러가 처리한다.

C/C++의 매크로에서는 MUL5(3)에서 3이 곱셈이 가능한지, 실수인지 이런 여부를 판단할 수 없다. Rust의 매크로 시스템에서는 MUL5(x)에 들어온 인자가 변수의 이름인지, 문자열인지, 네임스페이스인지, 람다 함수인지 등을 알 수 있다.

또한, Rust의 매크로는 메타 프로그래밍을 지원한다. 메타 프로그래밍은 컴파일 타임에 모든 것이 결정되는 프로그램을 작성하는 것으로써, 입력되는 매개 변수에 따라 넣을 코드를 결정하거나 미리 계산하도록 할 수 있다.

Rust에서 제네릭과 메타 프로그래밍이 분리되어 지원되는 것은, C++에서는 템플릿 문법이라는 하나의 도구를 이용해 일반화 프로그래밍(제네릭)과 메타 프로그래밍 두 가지를 지원하는 것과 대비되는 점이다. 물론, Rust에서 메타 프로그래밍이 매크로로 분리되었다고 해도, 메타 프로그래밍 자체가 여전히 어려운 것은 변함이 없다.

3.6. 비동기 프로그래밍

https://areweasyncyet.rs/

Rust는 언어 차원에서 비동기 프로그래밍을 지원하고 있으며, Python, C# 같은 다른 언어에서 사용되는 async/await 구조의 비동기 구문을 비슷한 형태로 사용할 수 있다. #

다른 언어에서 흔히 사용되는 비동기 프로그래밍 패턴 중 Future 개념은 코루틴[26]인 대표적인 예이다. 이러한 개념을 구현한 Future # 트레이트와 async/await 문법을 사용하면 되는데, Javascript 와 같은 Promise 기반의 언어와 달리 비동기 함수를 실행할 실행자(Executor)가 별도로 존재한다. Promise 객체는 객체가 생성됨과 동시에 자동으로 스케줄링이 되지만, Future 객체는 객체 생성 순간에는 아무것도 실행되지 않는다. 실행자는 실질적으로 작은 스케줄러 역할을 수행하며 이에 대한 구현은 서드파티에게 맡긴다. 현재 tokio async-std가 가장 널리 쓰이는 실행자 구현체이다[27].

Futureasync 함수 선언을 통해 자동적으로 구현된다. Future는 기본적으로 스레드 간에 이동될 수 있기 때문에 어떤 스레드에서 일시 정지되었다가 다른 스레드에서 재개하는 것도 가능하다. 그러나 async 함수에서 포인터와 같이 Send가 구현되지 않은 타입을 다루게 되면, FutureSend가 구현되지 않으며 비동기 프로그래밍에 상당한 제약사항이 발생한다. # 이러한 문제를 해결하려면 async 함수에서 그러한 타입을 직접 다루지 않고 별도의 함수에서 처리하도록 해야 한다.

Rust에서 비동기 프로그래밍을 시작해보고 싶다면 Asynchronous Programming in Rust[28]를 읽어보는 것을 추천한다. 아직 미완성이기는 하지만 Rust 언어에서 코루틴과 실행자를 구성하는 대략적인 구조를 이해하는데 도움이 되며, 부족한 내용은 표준 라이브러리 API 명세을 참고하거나 구글 검색으로 관련 내용을 찾아보면 보충할 수 있다.

3.7. 제네릭

Rust에서도 C++, C#, Java 등 대중적인 정적 타입 프로그래밍 언어들에서 흔히 제공하는 일반화 프로그래밍(Generic Programming) 패러다임을, 제네릭이라는 기능으로 제공하고 있다.

다만, Java나 C#이 제공하는 제네릭과, Rust가 제공하는 제네릭(그리고 C++ 템플릿)은 언어 설계 단계에서 채택한 정책이 서로 크게 다르다.

예를들면, Java의 제네릭은 컴파일 했을 경우 단 하나의 코드가 생성된다. 이후에 여러가지 다른 타입의 인자가 주어졌을 경우, 각 인자의 타입을 지워서(type erasure) 이미 생성해둔 하나의 코드에 적용시키는 방식이다. 이에 반해서, C++ 템플릿은 컴파일 했을 경우 해당 프로그램 전체의 사용 패턴을 확인해서 적용된 모든 타입의 인자에 해당하는 코드가 각각 따로 생성된다.

즉, Java의 경우에는 코드 생성 과정이 단순하고 생성된 코드 크기가 훨씬 작다는 장점을 선택한 대신 매번 실행시에 type erasure 과정을 거치는 오버헤드를 감수하기로 한 것이고, C++의 경우에는 매번 실행시에 오버헤드가 전혀 없다는 장점을 선택한 대신에 생성 코드 크기가 커질 수도 있고 컴파일 타임이 길어질 수도 있다는 것을 감수하기로 한 것이다. Rust는 C++의 방식을 채용하므로, 런타임 성능을 강조하고 컴파일 타임을 약간 희생하는 방식이다.

하지만, Rust의 제네릭과 C++의 템플릿 방식 사이에도 차이점이 존재한다. Rust의 경우 위의 다른 항목에서 설명한 트레이트 덕분에 코드 생성에 필요한 정보가 컴파일러에게 보다 많이 제공될 수 있다. 이를 통해 Rust 컴파일시에 C++보다 더 많은 체크와 최적화가 이론적으로 가능하다.[29]

4. 개발 도구별 특징

4.1. 안전하고 강력한 컴파일러

안전성을 위해 컴파일에 최대한 오류가 많이 걸러지게 설계된 Rust의 특성상 컴파일러가 매우 강력하다. 대부분의 예외나 에러는 컴파일러에서 잡히고, [30] 오류를 잘 검출하는 것 뿐만 아니라, 오류가 난 이유와 과정, 해결 방법 제안 등 컴파일 단계에 많은 정보를 제공한다.

컴파일 단계에서 여러 const 관련 기능, 상술한 C, C++ 라이브러리와의 정적 링크를 위한 코드 생성, 극도로 strict한 타입 관리, 에러 발견 등 최대한 많은 작업을 처리하려고 하기 때문에 컴파일 속도가 느린 편에 속한다. 하지만 이것은 컴파일러에 도입한 incremental compile[31]을 통해 부분적으로 해결하였다.

Rust는 C나 C++의 코드를 오버헤드 없이 코드에 이식할 수 있는데, 그 Cross-Language LTO라는 기능도 이 컴파일러의 기능이다.

4.2. 패키지 관리 도구 Cargo

자체적으로 업로드, dependency설정, 버전관리등 다양한 기능을 가지는 패키지 관리 프로그램 Cargo가 있다. 모듈들은 크레이트(Crate)라고 하는 단위로 묶여서 Crates.io (Rust 패키지 저장소)를 통해 실행 파일이나 라이브러리로 배포될 수 있으며, Cargo를 통해 빌드 및 패키지 배포를 자동화하고 필요한 라이브러리를 Cargo를 통해 자동으로 다운로드받을 수 있다.

주석을 통한 자체 문서화 기능도 있어서, 특수 주석을 통해 실제 사용 예시와 함께 소스코드 내에 문서화를 해주면 패키지를 업로드 할 때 패키지 주소에 자동으로 문서가 만들어진다!
이 문서 시스템을 적용한 대표적인 예는 Rust의 std가 있으며, 이러한 편리한 문서화 기능으로 인해 rust의 std문서는 상당히 잘 구성되어 있다.

Rust에서 제공하는 다양한 툴을 실행하는 기능도 가지고 있다. 기본적인 build, run, check[32] 명령어와 함께, Rust에서 추가로 제공하는 fmt[33], clippy[34]등을 설치하여 사용할 수도 있다.

4.3. IDE 지원 현황

IntelliJ IDEA CLion의 Rust 플러그인은 IntelliJ 플랫폼답게 히스토리 기반 코드 컴플리션, 리팩토링, 디버깅, Cargo 패키지 추적 등 여러가지 편의성을 제공한다. Visual Studio Code는 IDE는 아니지만, 공식으로 Rust 언어용 플러그인을 제공한다. 몇몇 다른 언어와 마찬가지로 Rust Language Server와 통신하는 방식으로 동작하며, Cargo 프로젝트 내의 모든 문제나 오류를 바로 쉽게 확인할 수 있다. Visul Studio Code를 사용한다면 일반적으로 rust-analyzer[35] 확장을 추천한다. 본래 비공식 플러그인이었으나 22년 2월부터 러스트 조직에 합류하여 러스트 공식 플러그인이 되었다. 시각적으로 타입 힌트를 표시하는 등 기존의 플러그인보다 더 편리한 기능들을 제공한다. Atom도 Rust를 플러그인 형태로 지원하고 있다.

5. 주목받고 있는 언어

5.1. 개발자들이 가장 좋아하는 언어

2015년부터 스택 오버플로우 설문조사에서 매년 가장 좋아하는 언어 중에 하나로 선정되고 있다. 2015년에는 3위에 진입했다가, 2016년부터 매년 연속 1위를 달성했다. ( 2017년, 2018년, 2019년, 2020년, 2021년 설문조사 결과)

5.2. 대기업에 주목받고 있는 언어

아마존, 구글, 마이크로소프트, 페이스북, 모질라, 리눅스 재단, 디스코드, 드롭박스, npm 등 IT 관련하여 유명한 기업이나 재단이 자사 서비스에 Rust를 적극적으로 활용하고 있다. #

Visual Studio를 개발한 마이크로소프트 메모리 안정성이 좋고, C 및 C++를 대체할 수 있는 시스템 프로그래밍 언어라고 밝혔다. 심지어 Rust의 주목성에 탐이 났는지 Rust 같은 언어를 자체적으로 만들겠다는 소식이 나왔을 정도.

실제로 MS에서도 러스트를 밀어주기 위해 자사 소프트웨어 기술지원 사이트인 Docs에 Rust 교육과정을 추가했으며 러스트 개발과 관련된 기초적인 자료를 올려놓기 시작했다. Docs 특성상 MS에서 만든 .NET계열이나 Azure관련 자료가 많았는데 MS가 주도하지 않는 언어가 추가되었다는 사실 자체로도 매우 놀랍다고 볼수있다.

구글또한 MS와 마찬가지로 Rust와 같은 언어를 자체적으로 만드는 시도를 해서 Carbon이라는 언어를 공개하였다.

5.3. 안드로이드 운영체제 개발 언어

2021년 4월 6일 구글 보안 블로그에 따르면 안드로이드 오픈소스 프로젝트(Android Open Source Project, AOSP)가 안드로이드 OS개발 언어로 Rust를 추가하기로 하였음을 밝혔다.[36] 이는 기존에 주로 C C++로 이루어지던 안드로이드 OS의 하단부 개발과 관련하여, 기존의 코드를 갈아 엎겠다는 것이 아니라 새로운 프로젝트들을 Rust로 작성하는 것도 허용하고 장려하겠다는 뜻이다.[37][38]

6. 사용 현황 및 전망

6.1. 전망

오버헤드 없는 안전한 메모리 관리가 가능하다는 점에서 시스템 프로그래머들이 주로 선호하는 편이다. 모질라 재단에서 개발한 만큼, 파이어폭스에서는 상당 부분을 Rust로 대체 하였고, 구글은 차기 운영체제인 퓨시아에서 Rust를 사용중이며, 아파치의 mod_ssl 모듈의 안정성을 개선하기 위해 Rust를 사용할 것이며 지원하겠다고 밝혔다. 또한 머신러닝 라이브러리인 Tensorflow Rust 또한 지속적으로 지원하고 있다. 링크 .
페이스북도 내부 시스템 일부에 Rust를 적용한 상태라고 한다. 레딧에서는 백엔드 개발을 담당할 Rust 엔지니어를 구인한 바 있다. # 이 언어로 Redox란 운영체제도 개발되고 있다. 또한 페이스북의 암호화폐 리브라에서도 사용되고 있다. npm Cloudflare는 기반 언어를 C에서 Rust로 교체했다. 2020년 기준 Discord가 서버와 클라이언트단 언어를 Golang에서 Rust로 교체하였다. 차세대 자바스크립트 런타임인 Deno도 시스템 바인딩을 Rust로 작성하였다.

그러나 전체적으로 보면 여전히 Rust의 사용률은 미진한 편이다. TIOBE 순위에서는 순위가 떨어지는데, 이는 소프트웨어 인프라가 기존 언어로 대부분 갖추어져 있고, 전문 인력을 구하기 쉽지도 않으며, 라이브러리에 대한 지원이 적기 때문으로 보인다. # 순위는 5년동안 꾸준히 상승하고 최근 Scala Kotlin을 제치고 올라가고 있지만, 여전히 대부분의 기업은 시스템 프로그래밍에 거의 C/ C++만을 사용하고 있다.

다만, 2019년 스택 오버플로우 개발자 설문조사에서 무려 파이썬 자바스크립트를 제치고 83.5%의 높은 선호도로 "개발자들에게 가장 사랑받는 언어" 1위를 차지했다는 점이나 구글 트렌드나 각종 랭킹 사이트에서의 수치가 장기적으로는 증가하고 있다는 것을 고려하면 Rust의 미래가 어둡지 않다.

"Rust는 소유권과 수명을 직접 지정해줘야해 불편하고 문법이 어렵고 기능이 많아 배우기 힘들다"는 주장이 있으나, "Rust의 주 타겟이 되는 유저들은 Rust보다 훨씬 더 어렵고 불편한 C/C++를 쓰고 있기에 문제가 되지 않는다"는 반론도 있다. 페이스북이 공개한 자료에 따르면 자사 엔지니어가 Rust를 능숙하게 익히는데 두달이면 충분했다고 한다.

C++ 사용자들의 가장 큰 불만은 난이도가 아니라 메모리와 관련한 실수를 하기 매우 쉽다는 것이다. Rust의 설계 목표가 비교적 안전한 시스템 프로그래밍 언어인 만큼, Rust에서 메모리 안정성을 위해 문법을 강제함으로써 발생하는 불편함과 C++에서 메모리 버그를 코드 리뷰와 디버거로 일일이 찾아내는 수고는 비교가 안 된다. 구글과 마이크로소프트에서는 Rust를 사용할 경우 자사 제품의 보안 버그 패치 비용의 70%를 절감할 수 있을 것이라는 내용의 문서도 공개하였다. 구글/마이크로소프트/인텔은 이미 Rust의 개발에 깊숙이 관여하고 있으며, 각종 컨퍼런스에서 공개적으로 이를 언급하고 있다.

Rust는 모질라 재단을 통하여 개발이 시작된만큼 모질라와 상당한 연관이 있는데, 2020년 8월 기부금으로 움직이는 모질라 재단이 코로나로 인해 자금 융통이 어렵다는 이유로 250명을 감축했으며, 이로 인해 Rust개발팀이 상당한 피해를 입었을 거라는 추측이 돌았다. # 그러나 일각에서는 Rust가 이미 모질라재단 소속의 기여보다 외부의 기여가 많아진 상황이라, 큰 영향은 없을 것으로 보기도 했다.

2020년 9월 TIOBE에서 18위를 달성했다.

AWS는 다른 기업보다 Rust에 관심이 많은데, 실제로 Rust를 사용하여 Amazon S3(Amazon Simple Storage Service), Amazon Elastic Compute Cloud(Amazon EC2), Amazon CloudFront 등 서비스를 제공한다. 최근에는 러스트로 작성된 Linux 기반 컨테이너 운영체제 보틀로켓(Bottlerocket)을 출시했다. 또한 아마존 EC2 팀은 Nitro Enclaves와 같은 민감한 애플리케이션을 포함한 새로운 AWS Nitro 시스템 컴포넌트의 선택 언어로 Rust를 사용한다. 또한 2020년 11월 아마존(AWS 클라우드 팀)이 Rust 컴파일러의 공동 리드를 맡았던 펠릭스 클록(Felix Klock)을 개발자로 영입했다. 영입을 이끈 Matt Asay는 트위터를 통해 AWS에서도 Rust가 사용되고 있으며, 안정성과 퍼포먼스에 상당한 기여를 하고 있다고 밝히기도 했다. Matt Asay 트위터. 또한 AWS는 2019년에 스폰쉽을 시작으로 2021년 2월에 발족한 러스트 재단에 초기 회원사가 되었다. 이외에도 Rust 개발자를 적극적으로 구인하는 중이라고 밝히기도 했다. 관련 기사 한 편으로는 이를 모질라재단의 감축으로 인한 효과라고 보는 시선도 있다.

한국인 개발자에 의해 개발된 TypeScript 컴파일러인 SWC shopify, Next.js # 등 큰 생태계를 가진 플랫폼에서 정식 채용되면서 또다시 관심을 받았다. 또한 2020년 이후로 WebAssembly가 적극적으로 사용되면서 서버사이드 뿐 아니라 브라우저에서도 Rust를 활용할 여러 방법들이 제시되는 등 웹개발 분야에선 끊임없이 관심의 대상이 되고있다.

Ruby의 컴파일러인 YJIT의 코드베이스가 C99 에서 Rust로 대체될 예정이다. Ruby의 핵심개발자들이 포팅에 참여해서 작업해 2022년 4월 20일, 포팅이 완료되었으며, 다른 기여자들의 리뷰를 위해 소스코드가 공개되었다. 해당 Github 풀 리퀘스트

6.2. 기존 언어와의 비교

6.2.1. Rust vs C++

Rust와 C++를 비교하기에 앞서 항상 주의할 점은, C++가 대체되지 않을 것이라고 주장하는 사람들이 많다는 점이다. 그러한 사람들은 기본적으로 "Rust로부터 배울 점은 있지만, C++가 대체되는 일은 발생하지 않음. 이미 D언어라는 자칭 C++ Killer가 있었지만 성공하지 못했음." 이라는 입장이다. Rust는 D언어와 달리 이미 성공적인 상업적 사용 사례가 상당수 존재하며, 기존의 모든 코드를 인력과 돈을 낭비해가며 굳이 Rust로 대체할 이유도 없다. 구글이나 아마존이 클라우드에 적극적으로 사용하고 디스코드가 Go로 작성된 서버를 대체하는 것을 보면, "C++를 대체할 것인가"와 관계없이 안전하고 빠른 고생산성 언어로써 충분히 메리트가 있다는 점을 알 수 있다. 기존의 레거시들을 강제로 세대교체할 이유는 없다. 앞으로 세상에 내놓아지는 물건들이 Rust, Swift 등 이쪽 계열의 현대적인 언어들로 만들어진다면 그것만으로 Rust의 향후 언어 생태계 조성에 대한 잠재성은 충분하다.

Rust의 출시 배경은 C++의 안전하지 않은 메모리 관리로 인해 숙련되지 않은 프로그래머가 작성시에 오류나 취약점이 발생할 위험이 매우 높아진다는데 있다. 전 세계 수십억명이 사용하고 있는 윈도우 크롬은 개발 과정에서 코드 리뷰 과정을 여러 번 거칠 것임에도 불구하고 매년 CVE로 분류되는 수십개의 메모리 버그를 해결하기 위해 계속 패치 및 긴급 패치를 제공하고 있다는 점을 알고 있을 것이다. 현실적으로 C/C++ 언어에서 메모리 버그를 완전히 잡아내기란 어렵다. 따라서 Rust나 가비지 컬렉터 언어가 제공하는 메모리 안전성은 프로그래머에게 안정감을 제공함과 동시에 보안성 및 생산성 측면에서 상당한 이점을 가져다 주며 이것이 C/C++와의 큰 차이점이라고 할 수 있다.

C++의 단점을 거의 지워버리듯이 한 Rust는 C++을 충분히 대체할 수 있을듯 싶지만, 아직 C++에 비해서 점유율이 많이 밀린다.
  1. C++로 구현된 기존의 인프라
    C++ 은 수십년간 존재하던 언어로서 기존의 많은 프로그램이 C++ 기준으로 작성되어 있고 유지되고 있다. 대부분의 라이브러리는 다른 언어에 바인딩을 제공하는 경우가 많기 때문에 큰 문제가 되지 않지만, Qt와 같이 복잡한 라이브러리는 바인딩이 매끄럽지 못하다. 그리고 대다수의 하드웨어들은 리소스 접근을 C/C++ 언어로 지원한다.
  2. 아직은 생소한 언어
    대부분의 기업이나, 정부 기관 입장에서 Rust 언어는 아직은 생소하다. 프로그래밍 언어의 경우 대세가 바뀌기 까지 짧게는 10년[39]이 걸린다. C++로 작성된 기존의 프로그램을 유지 보수만 하고 있는 마당에 Rust 언어로 뭔가 덧붙이거나 다시 작성하지는 않을 것이다. 아직도 MFC 같은 레거시 라이브러리를 쓰는 경우도 많다.
  3. 엄격함에 따른 불편함
    Rust 언어가 메모리 안전성을 보장할 수 있도록 설계되다보니 다른 언어와 비교하여 엄격하기 때문에 불편하다. 대표적으로, 참조자나 객체의 수명을 개발자가 직접 지정해야 하는 경우 초보 개발자들은 이때 발생하는 에러와 복잡성에 골치를 앓게 된다. 그리고 철저한 에러 처리 규칙으로 인해 실질적으로 에러 발생 가능성이 없는 부분에도 컴파일러가 에러 처리를 하라는 경고 메시지를 출력한다. 다만 컴파일러가 원인을 이해하기 쉽게 설명해주고 수정안을 표시해주는 등 다른 언어들에 비해 비교적 친절한 편이다.
6.2.1.1. 결론
현재까지 Rust는 C++에 비해 사용자가 적어서 열세인 모습을 보이고 있다. 그러나 D언어와 달리 많은 기업에서 관심을 가지며 성공적인 도입 사례가 많은 만큼, Rust의 상대적 편의성과 안전한 코딩 방법으로 인해 장기적으로 볼 때 C++의 강력한 대안이 될 수 있다. 다만, 이미 검증된 기존 프로젝트를 뒤엎고 Rust로 재작성한다는 것은 매우 큰 개발비 비용을 초래하며 아무런 이득이 없기 때문에 지양될 것이며, Rust는 새로운 프로젝트에서 사용될 가능성이 높다.
다만 최근 구글 보안팀의 발표에 따르면, 장기적으로 보안이 필요한 부분에서는 잠정적인 위헙이 존재하는 C++코드를 들어내고 대체하려한다라고 발표해서, 기존 코드들도 필요에 따라선 많은 회사에서 C++에서 Rust로 대체할 것으로 보인다.

6.2.2. Rust vs Carbon

Carbon 구글 C++를 대체하기 위해서 2022년에 발표한 프로그래밍 언어이다. 위에 상기한 바와 같이 Rust의 최대 단점은 C++로 쓰여진 수없이 많은 기존 인프라와 호환에 문제점이 있다는 점인데, 이를 보완하기 위해 "C++와 양방향 상호 호환"을 철학으로 삼고 있다. 뉴스 기사
파일:상세 내용 아이콘.svg   자세한 내용은 Carbon 문서
번 문단을
부분을
참고하십시오.

6.3. 실무에서의 사용

6.3.1. Rust를 사용하는 기업

  • Discord - 백엔드에 golang을 사용했지만 GC처리속도로 인해 러스트로 옮겼다 #. 또한 클라이언트 단에서도 비디오 인코딩을 위해 사용한다고 한다.
  • Dropbox - 대표적으로 러스트를 사용하는 기업 중 하나. 파일 동기화 엔진을 모조리 러스트로 재작성했다고 한다 #.
  • npm - C 언어로 짜여 있던 레지스트리 코드를 러스트로 옮긴 후 성능이 향상되었다. 현재는 yarn과 성능이 대등하다.
  • Sentry: 실무에서 많이 쓰이는 에러 로깅 툴로, 소스맵 처리기의 성능 개선을 위해 Python서 Rust로 CLI를 교체하였다.
  • 솔라나 - 러스트로 구현된 암호화폐. 자세한 내용은 해당 문서 참고.
  • 러스트를 사용하는 다른 기업들.

6.3.2. Rust로 제작된 것들

7. 도서

7.1. The book

러스트 프로그래밍 공식 가이드
The Rust Programming Language
파일:1718500440_2.jpg
파일:k562636803_1.jpg
원서 한국어 번역서
온라인 보기 한국어 번역문

이 책은 러스트의 공식 가이드이자 오픈소스 서적인 the book을 그대로 책으로 옮겨 출판한 것이다. 국내 출판은 제이펍이 맡았다.

국내 출판서의 번역과는 별개로 the book자체를 포크해 기여자들이 자발적으로 번역한 한국어 번역이 있다. 그 외 언어에 대한 번역은 이곳에서 찾을 수 있다.

책 자체가 하나의 Git 저장소이기 때문에 최신 내용들이 제때 업데이트 되며, 누구나 PR할 수 있기 때문에 오탈자 또한 적은 편이다. 반대로 출판 서적의 경우 2018 에디션을 기준으로 하기 때문에 대부분의 경우 문제는 없지만 2021에디션을 사용한다면 사소한 차이가 있을 수 있다. (deprecated된 ... 표기법 등)

여담으로 문서 툴로는 mdBook을 사용한다.

7.2. 그 외

이외에도 Rust in Action(번역서: 한 줄 한 줄 짜면서 익히는 러스트 프로그래밍)이나 중급자 이상을 위한 Rust for Rustaceans과 같은 책들이 있다.

8. 관련 링크


[1] 첫 발표 기준으로, 1.0 정식판 기준으로는 Rust가 3년 늦게 나왔다. [2] 언어에 마스코트가 왜 필요한지 의문이 들 수도 있는데, Go를 비롯한 비교적 최근에 나오는 몇몇 언어들은 고유한 마스코트가 따로 존재한다. 언어는 아니지만 유니티 엔진도 유니티짱이라는 마스코트가 존재한다. [3] 페리스를 위한 사이트(!)도 존재한다. [4] Crustacean(갑각류)에서 따온 것으로 보인다. [5] Go개발자들이 스스로를 고퍼(Gopher)라고 하는 것과 유사하다 [6] 그레이던 호어는 이 뒤로도 한동안 수석 개발자로 개발에 참여하고 있다가, 2013년에 수석 개발자 지위를 내려놓은 상태이다. [7] 기존의 객체 지향 프로그래밍 언어와 비교해서 상당한 차이가 있다. Rust는 직접적인 상속을 지원하지 않으며, 인터페이스 역할을 하는 트레이트를 하나의 객체에 여러 개 합성하거나, 트레이트가 다른 트레이트를 상속하거나 하는 시스템을 가지고 있다. 트레이트는 말 그대로 객체의 특성을 나타내기도 한다. 예를 들자면 Clone 트레이트는 객체가 복제될 수 있음을 나타내는 동시에 복제 인터페이스를 제공한다. [8] Option<T>을 다뤄보면 알겠지만, 애초에 None에 대한 처리 없이는 데이터에 접근할 수 없어서 이 부분에서 실수할 일이 많이 없다. [9] unsafe라는 키워드를 통해서 raw 포인터를 다룰 수 있다. 하지만, 많은 상황에서 쓸 일이 없고, unsafe라고 해서 모든 안전 장치가 풀리는 것도 아니다. 하드웨어에 대한 직접적인 접근을 허용된다는 의미이다. 주로 C나 C++코드를 러스트에서 사용할 때 사용된다. [10] unsafe 스코프를 사용하지 않는다는 전제하에 dangling pointer, double-free, use-after-free 같은 메모리 버그를 작정하고 도입하려해도 아예 원천적으로 불가능하다. 단 러스트는 공식적으로 메모리 누수에 대해 보호를 보장하지는 않는다. [11] 정확히는 오버헤드가 큰 "추적 기반 쓰레기 수집" 을 사용하지 않는 것이고, Rc, Arc 등의 스마트 포인터에 "참조 기반 쓰레기 수집"이 포함되어 있다. Rust 및 C++로 작성되는 많은 프로그램은 스마트 포인터를 자주 사용하고 있다. [12] 1.32 이전에는 메모리 할당자인 jemalloc을 기본적으로 사용했기 때문에, 속도는 좀 더 빠르지만 OS 입장에서는 항상 사용하는 만큼만 메모리를 할당받는 것은 아니었다. 원하는 경우 라이브러리를 활용하거나 직접 구현하여 메모리 할당자를 바꿀 수 있다. [13] 스레드 또한 시스템에서 직접 할당받아 사용한다. n:m 방식으로 스레드 할당을 받고자 하는 경우, 특정 라이브러리를 사용해야하며, 이렇게 하면 약간의 성능을 희생하여 편의성을 얻을 수 있다. [14] 메모리 영역이라고 이해해도 무리는 없다. [15] 러스트는 모든 스코프(Scope) 이탈 시 스코프 내에서 할당이 이루어진 값에 대해 할당 해제가 발생하는데, 스코프를 나가는 변수가 2개가 되어 같은 메모리에 대한 할당 해제가 2번 일어나는 것을 막기 위해 하나를 파기시키는 것이다. [16] 이때의 변수는 참조(reference)와 값(value)를 통틀어서 말한다. [17] 단, 후술되는 특수한 트레이트인 Copy트레이트를 연산 되는 타입이 지니면 복사연산이 실행된다. [18] 값이 이동할 때 새로 메모리를 할당하고 메모리를 복사할 지, 그냥 주어진 메모리 영역을 그대로 쓸지 결정하는 것은 Rust 컴파일러의 몫으로, 최적화하기에 따라서는 함수로 인자를 넘기고 리턴받는 동안 단 한 번의 메모리 복사도 일어나지 않을 수도 있다. C++를 아주 잘 알고 있다면, RVO라는 약어가 익숙할 것이다. [19] Borrowed reference라고도 부른다 [20] 그러나 Rust 컴파일러에서 수명과 관련한 오류를 확인하는 방식은 "책을 빌린 사람이 있으면 그 전에는 도서관 문을 닫지 마시오" 가 된다. [21] C++ TS의 std::expected와 비슷하다. [22] 타입 TU의 합집합. 다른 언어에서는 주로 T | U로 표기한다. TypeScript식 표기를 기준으로 '문자열 또는 숫자를 아이템으로 가지는 배열의 타입'은 Array<number | string>와 같이 표시한다. [23] Rust의 ABI는 안정적으로 제공되지 않으므로 이러한 내용은 언제든지 바뀔 수 있다. [24] 다른 언어를 기준으로 설명하자면, Java8 이후의 Java interface와 매우 비슷하다. 물론 차이는 있다. [25] C++20의 Concepts 기능과 유사한 역할을 한다. [26] 코루틴은 서브 루틴을 일시 정지하고 재개할 수 있는 구성 요소를 말한다. 쉽게 말해 필요에 따라 일시 정지할 수 있는 함수를 말하며, 이를 활용하여 I/O 처리를 극대화할 수 있다. 이는 단순히 대기해야 하는 작업이 처리되기 전에 다른 작업을 먼저 처리하도록 할 수 있기 때문이다. 멀티 스레드 환경에서도 공유 자원의 접근이 필요할 때 뮤텍스의 락을 얻지 못하는 경우, 다른 작업을 먼저 처리하도록 하여 컴퓨팅 자원의 사용을 극대화할 수 있다. [27] 단순 연산 뿐만 아니라 네트워크, 파일 입출력, 타이머 등의 처리를 복합적으로 수행한다. 일반 Socket 을 사용할 지, epoll 등의 event 기반 I/O 를 사용할 지는 이 실행자 구현체의 세부 사항으로 결정된다. [28] 한글판 [29] C++에서도 C++20 표준의 Concept을 통해서 Rust의 트레이트와 유사한 정보를 컴파일러에게 제공할 수 있게 되었다. [30] 심지어는 match(타언어의 switch)에서 default가 없는 등 빠진 논리 흐름이 있으면 컴파일이 안된다! [31] 전에 컴파일했던 코드와 현재 컴파일하는 코드를 비교하여, 변경된 부분만 다시 컴파일하는 기법이다. [32] 컴파일 시에 일어나는 에러를 직접 컴파일 하지 않고 적은 비용으로 확인할 수 있다. 런타임시 발생 가능한 에러를 최대한 컴파일 타임에 잡아내는 러스트의 특성상 사용할 일이 많은 명령어이다. [33] 소스코드를 보기 좋게 자동으로 정렬해준다. [34] 컴파일 시에 일어나는 에러를 확인함과 동시에 쓸데없이 장황한 코드를 깔끔하게 만드는 방법을 제공하는 툴 [35] LSP를 사용하기 때문에 비단 vscode뿐만이 아닌 neovim등 다른 에디터에서도 사용 가능하다. [36] "we’re excited to announce that the Android Open Source Project (AOSP) now supports the Rust programming language for developing the OS itself." # [37] "our memory-safe language efforts are best focused on new development and not on rewriting mature C/C++ code." # [38] 2021년 10월, AOSP 페이지에 RUST 빌드 가이드 항목이 생겼다. https://source.android.com/setup/build/rust/building-rust-modules/overview?hl=en [39] Python이 현재의 인기에 도달하기까지 30년이 걸렸다 [40] 디스코드 서버가 아래 서버와 함깨 상당히 활동적이다. 예의만 잘 지킨다면 초보자들은 질문이 생겼을 때 여기서 상당히 친절한 답변을 받을 수 있다 [41] 원래 공식 서버가 아니었으나, 정식 파트너쉽을 맺었다