본문 바로가기

개발

Rust 소유권(Ownership) 이해하기 - 스택과 힙

소유권의 주요 목적은 힙 데이터를 관리하는 것입니다.소유권을 이해하려면 스택과 힙에 개념에 대해서 알아야합니다. 실제 코드를 작성하면 스택과 힙의 구조에 대해 자주 생각할 필요는 없지만 개념적으로 데이터가 어떻게 사용되고 어떤 영역에 존재하는지 알고 다릅니다.

스택과 힙

많은 언어들은 스택과 힙에 대해 자주 생각할 필요가 없습니다. 그러나 Rust와 같은 시스템 프로그래밍 언어는 값이 스택에 있는지 힙에 있는지 여부는 프로그램이 작동하는 방식과 의사결정을 내려야 하는 것에 대해 영향을 줍니다. 스택과 힙은 모두 코드에서 런타임에 사용할 수 있는 메모리의 일부이지만 서로 다른 방식의 구조입니다. 스택은 값을 가져온 순서대로 저장하고 반대 순서로 값을 제거합니다. 이것을 후입선출이라고 합니다. 접시를 생각하면 이해가 빠릅니다. 접시를 위에 쌓고 접시가 필요할 때 맨 위에서 하나를 꺼냅니다. 중간 또는 바닥에 접시를 추가하거나 제거하는 것은 안됩니다. 스택에 데이터를 추가하는 것을 푸시 라고 하고 데이터를 제거하는 것을 이라고 합니다. 스택에 저장된 모든 데이터는 알려진 고정 크기를 가져야 합니다. 컴파일 시 알 수 없는 크기 또는 변경될 수 있는 크기의 데이터는 스택대신 힙에 저장해야 합니다.

 

힙은 스택보다 경직되어있지 않습니다. 힙에 데이터를 넣을 때 특정 공간을 요청합니다. 메모리 할당자는 힙에서 충분히 큰 빈 자리를 찾아 사용 중인 것으로 표시하고 해당 위치의 주소인 포인터 를 반환합니다. 이 프로세스를 힙에 할당이라고 합니다. 힙에 대한 포인터는 알려진 고정 크기이므로 스택에 포인터를 저장할 수 있지만, 실제 값을 가져올때는 포인터를 통해 값을 가져옵니다. 식당에 앉는다고 생각해보세요. 들어갈 때 인원수를 말하면 직원이 빈 테이블을 찾아 모든 사람에게 맞는 빈 테이블을 찾아 안내합니다. 그룹의 누군가가 늦게 올 경우, 그들은 당신이 어디에 앉았는지를 직원에게 물어보고 그 자리를 찾을 수 있겠죠.

 

일반적으로 스택으로 푸시하는 것이 힙에 할당하는 것보다 빠릅니다. 그 위치는 항상 스택의 맨 위에 있습니다. 상대적으로 힙에 공간을 할당하려면 더 많은 작업이 필요합니다. 할당자가 먼저 데이터를 저장할 수 있는 충분한 공간을 찾은 다음, 이후 작업을 준비해야 하기 때문입니다. 또한, 힙에 있는 데이터에 액세스하는 것은 스택에 있는 데이터에 액세스하는 것보다 느립니다. 그 이유는 거기에 도달하기 위해 포인터를 따라가야 하기 때문입니다. 최신 CPU 프로세서는 메모리에서 덜 이동하기때문에 더 빠릅니다. 계속해서 유추를 진행하면서 많은 테이블에서 주문을 받는 식당의 서버를 생각하면 이해가 쉽습니다. 다음 테이블로 이동하기 전에 한 테이블에서 모든 주문을 받는 것이 가장 효율적입니다. 테이블 A에서 주문한 다음 테이블 B에서 주문한 다음 A에서 다시 주문하고 B에서 다시 주문하면 훨씬 느린 프로세스가 됩니다. 같은 가격으로 프로세서는 다른 데이터와 가까운 데이터(스택 영역)를 더 멀리 떨어져 있는(힙 영역) 작업을 수행하는 경우보다 더 잘 수행할 수 있습니다.

 

다음시간에는 본격적으로 소유권의 개념과 구조에 대해서 알아보도록 하겠습니다.