목차
- Ownership ( 소유권 ) 등장 배경
- Ownership ( 소유권 ) 동작원리
- 모든 변수에서 Ownership Move ( 소유권 이동 )이 발생할까?
- Ownership ( 소유권 )과 함수
Ownership ( 소유권 ) 등장 배경
동적 할당으로 인한 메모리 누수 문제를 다른 언어에서는 다음과 같이 대응했습니다.
C/C++ : "메모리 관리, 그거 프로그래머 실력이야!"
Java, Python 등 : "성능이고 나발이고 우린 Garbage Collector 쓸래."
C/C++에서는 문제를 방관했고, Java는 성능을 어느 정도 포기하고 개발의 편리함을 선택했습니다.
하지만 Rust에서는 조금 다른 방식으로 접근했습니다.
Rust : "동적 할당 변수도 지역변수처럼 사용하면 메모리 누수 문제를 해결할 수 있지 않을까?"
이처럼, Rust는 안전한 메모리 사용과 성능, 이 두 마리 토끼를 잡기 위해 GC를 선택하지 않고, C/C++ 보다 엄격한 컴파일러 규칙으로 메모리 누수 문제를 해결하려고 접근했습니다. 컴파일러 규칙으로 C++ RAII 패턴(메모리를 할당한 지역을 벗어나면 메모리의 할당을 해제)을 강제로 적용했습니다.
언뜻 들어보면, 간단히 문제가 해결될 것 같지만, 새로운 문제가 발생합니다. 문제를 살펴보기 앞서, 기존 프로그래밍 언어에서 다루는 데이터 복사 방식을 다시 한번 짚고 넘어가겠습니다.
- Deep Copy ( 깊은 복사 ) : 크기가 한정된 작은 데이터
- Shallow Copy ( 얕은 복사 ) : 리스트나 객체 등 주로 크기가 큰 데이터
Deep Copy | Shallow Copy |
|
Rust에서는 동적 할당 변수를 복사할 때, 어떻게 처리할까요?
※ String 객체는 컴파일 타임에 정확한 크기를 알 수 없어 heap영역에 할당됨.
heap 메모리 영역의 변수들을 Deep Copy 하면 프로그램의 속도 저하가 심각해지기 때문에, 다른 언어와 마찬가지로 Rust도 Shallow Copy를 선택해야 했습니다. 다만, 위에서 말씀드린 새로운 문제가 여기서 발생합니다. 두 포인터가 같은 데이터를 가리키고 있으므로, 같은 메모리 영역에 대해 메모리 할당 해제를 두 번 하게 되는 것이죠! 이 문제를 해결하기 위해 등장한 개념이 바로 Ownership ( 소유권 )입니다.
Ownership ( 소유권 ) 동작원리
Ownership ( 소유권 )이 무엇일까요?
Ownership ( 소유권 )은 단어 의미 그대로, '데이터를 소유할 권리를 어떤 포인터가 가지고 있냐'를 나타냅니다.
Rust에서는 어떤 데이터에 대한 Ownership( 소유권 )은 하나의 포인터만이 가질 수 있습니다. 따라서, 위의 복사 예시 코드에서는 Move( 소유권 이동 )이 발생합니다.
데이터 소유(s1) | 같은 데이터 가리킴 | 소유권 이동(s1->s2) |
※ 위에서 이야기할 때에는 Shallow Copy라고 말씀드렸지만 엄밀이 따져보면 다른 방식이므로, Rust에서는 Shallow Copy라고 부르기보다는 Move ( 소유권 이동 )이라고 합니다.
Move ( 소유권 이동 )이 아닌 Deep Copy를 하려면 어떻게 해야 할까요?
위의 예시 코드처럼 clone( ) 멤버 함수를 호출해주시면 됩니다. 다만, 메모리 용량이 큰 데이터를 복사하실 때, 프로그램의 속도가 저하되는 것을 염두하시고 사용하시길 바랍니다.
모든 변수에서 Ownership Move ( 소유권 이동 )이 발생할까?
아닙니다. 컴파일 타임에 크기를 알 수 있는 변수들은 stack에 저장되고, stack에 저장되는 이 변수들은 copy trait ( 복사 특성 )을 가집니다. 대입 연산 시, copy trait을 가진 변수들은 Move ( 소유권 이동 )이 아닌 Deep Copy를 합니다.
그럼 copy trait( 복사 특성 )을 가진 변수 타입은 무엇일까요?
- integer type 변수 ( i32, u32,... )
- bool type 변수
- floating point type 변수 ( f32, f64 )
- char type 변수
- 직접 쓰인 String 변수 ( ex. let s = "hello" )
- copy trait의 변수 타입인 element만을 가진 tuple ( 튜플 )
- copy trait의 변수 타입의 array ( 배열 )
Ownership ( 소유권 )과 함수
그럼 함수 매개변수와 반환 값에서의 Ownership ( 소유권 ) 관계는 어떻게 될까요?
함수 내부에서의 Ownership ( 소유권 ) 동작원리와 동일합니다.
공식 도서
https://doc.rust-lang.org/book/
공식 도서 번역본
https://rinthel.github.io/rust-lang-book-ko/
오늘은 Rust 메모리 관리와 Ownership에 대해 정리해보았습니다.
저도 정리하면서 공부할 수 있는 좋은 시간이었습니다.
여러분께도 조금이나마 도움이 되었으면 좋겠습니다.
감사합니다.
* 피드백은 댓글로 남겨주세요 *
'Rust' 카테고리의 다른 글
[example] Rust min, max (최소값, 최대값 구하기) (1) | 2021.06.25 |
---|---|
[example] Rust 표준입력, 한줄로 받은 입력 나누기 (1) | 2021.06.20 |
Rust 함수, 제어문 (0) | 2021.06.15 |
Rust 변수,상수, 데이터 타입 (1) | 2021.06.14 |
Rust 프로젝트, 컴파일, 빌드, 릴리즈 (0) | 2021.06.12 |