[Rust] Ownership - 1

undefcat·2020년 8월 21일
0

rust

목록 보기
1/1

Ownership

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은 다음과 같다.

  • VariableValueOwn한다.
  • Value는 특정 시점에 딱 하나의 Owner, 즉 Variable만 갖는다.
    • Variable은 특정 시점에 딱 하나의 ValueOwn한다.
  • Variable이 유효한 Scope를 벗어나면, VariableValue는 메모리에서 해제된다.

백문이 불여일견이라고 했다. 코드로 확인해보자.

Hello, Ownership!

문자열 객체를 하나 만들고, 출력해보자.

// 문자열 객체를 생성한다.
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.

cargoRust의 패키지 매니저다. 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는 이제 그 어떤 ValueOwn하고 있지 않기 때문에 6번째 줄에서 오류가 발생한 것이다!

이것이 바로 RustOwnership 기본 개념이다. 즉, VariableValue간의 상호작용이다.

그렇다면 왜 이런 Ownership 개념이 생겼는가? 이는 다음 챕터에서 알아보도록 하자!

profile
초보개발자니뮤ㅠ

0개의 댓글