Rust
에는 다른 언어에서는 볼 수 없는 독특한 개념이 존재한다. 바로 Ownership
이라는 개념이다.
Rust
는 시스템 프로그래밍 언어를 표방한다. 즉, 퍼포먼스가 매우 중요한 언어인데 그렇기 때문에 GC
가 존재하지 않는다. 하지만 메모리 관리는 매우 중요하다. 그리고 개발자가 메모리를 잘 관리하는 코드를 작성하기란 매우 어렵다.
당연하겠지만, Rust
언어의 설계자들도 이것이 고민이었을 것이다. 그리고 고민 끝에 내놓은 개념이 바로 Ownership
이다.
Ownership
의 개념은 RAII와 비슷하다고 공식문서에서 설명한다.
Note: In C++, this pattern of deallocating resources at the end of an item’s lifetime is sometimes called Resource Acquisition Is Initialization (RAII). The drop function in Rust will be familiar to you if you’ve used RAII patterns. #Link
Ownership
은 다음과 같다.
Variable
은 Value
를 Own
한다.Value
는 특정 시점에 딱 하나의 Owner
, 즉 Variable
만 갖는다.Variable
은 특정 시점에 딱 하나의 Value
를 Own
한다.Variable
이 유효한 Scope
를 벗어나면, Variable
과 Value
는 메모리에서 해제된다.백문이 불여일견이라고 했다. 코드로 확인해보자.
문자열 객체를 하나 만들고, 출력해보자.
// 문자열 객체를 생성한다.
let a = String::from("Hello, Rust!");
// b에 a를 할당한다.
let b = a;
println!("{}", b); // Hello, Rust!를 출력한다.
println!("{}", a); // Hello, Rust!를 출력한다.
Rust
의 문법을 잘 모를지라도, 이해하는데 어려움이 없을 것이다. 단순히 변수 a
에 문자열 객체를 할당하고, 또 다른 변수에 a
가 가리키는 문자열 객체를 할당한뒤 둘 다 출력하는 평범한 코드다. 일반적인 언어에서라면, 여기에서 오류가 있을 것이라고는 상상하기 힘들다.
$ cargo check
Checking ownership v0.1.0 (M:\rust\ownership)
error[E0382]: borrow of moved value: `a`
--> src\main.rs:6:20
|
2 | let a = String::from("Hello, Rust!");
| - move occurs because `a` has type `std::string::String`, which does not implement the `Copy` trait
3 | let b = a;
| - value moved here
...
6 | println!("{}", a);
| ^ value borrowed here after move
error: aborting due to previous error
For more information about this error, try `rustc --explain E0382`.
error: could not compile `ownership`.
To learn more, run the command again with --verbose.
cargo
는 Rust
의 패키지 매니저다. Rust
의 컴파일러는 rustc
이지만, cargo
를 이용하여 전체 패키지를 컴파일하고 배포한다.
cargo check
는 현재 패키지가 유효한지를 검사한다. 즉, 컴파일이 되는지, 의존성에는 문제가 없는지 패키지의 전체적인 유효성을 검증하는데, Rust
에서는 보통 cargo
를 이용해 프로젝트를 생성하고 관리하기 때문에 따로 rustc
로 컴파일하지 않는다.
cargo check
는 실제로 바이너리를 생성하지는 않기 때문에 실제 빌드하는 것보다 빠르다. 그래서 언어 문법에 이상이 있는지 없는지 수시로 cargo check
로 검사를 한다.
아무튼, 6번째 줄인 println!("{}", a);
코드에서 오류가 발생했다!
위에서 보다시피 Rust
의 컴파일러는 매우 친절하기로 소문이 자자하다. 컴파일러의 오류 메세지만 봐도, 대부분의 문제는 해결 가능하다.
실제 콘솔창에서는 어디에서 오류가 발생했는지, 그 색깔로 표시가 된다.
6번째 줄에 빨간색으로 에러가 발생했음을 알 수 있다. 파란색 글자들은 빨간색 에러가 발생한 원인들을 친절하게 설명해주고 있다.
3번째 줄을 보면 value moved here
라고 나와있다. 즉, Value
가 변수 b
로 옮겨졌다는 뜻이다.
그렇다. 각 Variable
은 단 하나의 Value
만을 Own
할 수 있다. 따라서, 최초 변수 a
에 할당되었던 문자열 객체가 let b = a;
코드를 통해서 Owner
가 바뀐 것이다!
따라서, a
는 이제 그 어떤 Value
도 Own
하고 있지 않기 때문에 6번째 줄에서 오류가 발생한 것이다!
이것이 바로 Rust
의 Ownership
기본 개념이다. 즉, Variable
과 Value
간의 상호작용이다.
그렇다면 왜 이런 Ownership
개념이 생겼는가? 이는 다음 챕터에서 알아보도록 하자!