<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Rust Ownership &#8211; KGG Studio</title>
	<atom:link href="https://blog.kggstudio.com/tag/rust-ownership/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.kggstudio.com</link>
	<description>개발자 테크 블로그</description>
	<lastBuildDate>Mon, 23 Mar 2026 11:08:08 +0000</lastBuildDate>
	<language>ko-KR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://blog.kggstudio.com/wp-content/uploads/2025/05/cropped-K-1-32x32.png</url>
	<title>Rust Ownership &#8211; KGG Studio</title>
	<link>https://blog.kggstudio.com</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">244941309</site>	<item>
		<title>Rust(10) &#8211; Ownership</title>
		<link>https://blog.kggstudio.com/rust10-ownership/</link>
					<comments>https://blog.kggstudio.com/rust10-ownership/#respond</comments>
		
		<dc:creator><![CDATA[TimTam]]></dc:creator>
		<pubDate>Mon, 23 Mar 2026 11:08:08 +0000</pubDate>
				<category><![CDATA[Dev]]></category>
		<category><![CDATA[Rust]]></category>
		<category><![CDATA[Rust Ownership]]></category>
		<guid isPermaLink="false">https://blog.kggstudio.com/?p=328</guid>

					<description><![CDATA[Ownership은 러스트 언어의 핵심 개념입니다. 이것만 알아도 Rust를 알수 있다 할수 있습니다. 가비지 콜렉터도 없지만 C++의 포인터처럼 복사를 최소화하여 성능을 극대화 시킬수있는 새로운 개념입니다. 많은 프로그래머들에게는 생소할수있지만 사실 개념자체는 이미 오래전에 만들어지고 C++에서도 스마트포인터라는 이름으로 20여년전부터 많이 쓰이는 방식이긴 합니다. 문제는 C++에서 이 방식을 사용할경우 변수선언에 코드가 지나치게 길어지기도 해서 일반변수에는 잘안쓰고 class 객체위주로 사용하는 ... <a title="Rust(10) &#8211; Ownership" class="read-more" href="https://blog.kggstudio.com/rust10-ownership/" aria-label="Rust(10) &#8211; Ownership에 대해 더 자세히 알아보세요">더 읽기</a>]]></description>
										<content:encoded><![CDATA[
<p>Ownership은 러스트 언어의 핵심 개념입니다. 이것만 알아도 Rust를 알수 있다 할수 있습니다. 가비지 콜렉터도 없지만 C++의 포인터처럼 복사를 최소화하여 성능을 극대화 시킬수있는 새로운 개념입니다. 많은 프로그래머들에게는 생소할수있지만 사실 개념자체는 이미 오래전에 만들어지고 C++에서도 스마트포인터라는 이름으로 20여년전부터 많이 쓰이는 방식이긴 합니다. 문제는 C++에서 이 방식을 사용할경우 변수선언에 코드가 지나치게 길어지기도 해서 일반변수에는 잘안쓰고 class 객체위주로 사용하는 사람이 대부분이었습니다. 문제는 C++ 스마트 포인터는 코드가 길어질뿐만아니라, 익숙치않으면 사용할때 컴파일에러도 많이 발생하고, 정작 유저가 혜택을보는 부분에서는 컴파일러가 에러를 잘 잡아주지못하는 문제도 있습니다. Rust는 기본 개념자체가 모든 힙메모리를 사용하는 변수에 오너십을 적용하고 있어서, 코드가 간결하여 컴파일러가 에러를 확실하게 잡아줍니다. 애플의 Swift나 메타의 move 언어도 같은개념을 사용할수있지만 언어의 기본 시스템은 아닙니다.</p>



<h3 class="wp-block-heading">Stack and Heap</h3>



<p>스택은 자료구조에서 다들 배웠겠지만, 여기서말하는 스택은 조금 다릅니다. 자료구조의 스택처럼 LIFO 개념은 동일합니다만, 여기서 말하는 Stack은 프로그램을 실행시 정적으로 가지는 메모리입니다. C++에서 Vector를 사용할때 Stack처럼 push로 데이터를 추가하고 pop으로 빼낼수있지만 C++ Vector는 가변메모리로써 Heap에 존재하죠. Stack에 저장될수있는 메모리는 컴파일 시점에 메모리의 크기를 정확히 알수 있어야 합니다.</p>



<p>스택메모리는 프로그램 실행시점부터 순차적으로 메모리를 쌓아올라가기 떄문에, 호출비용이 없고 메모리 낭비가 거의 제로에 가깝습니다. 힙메모리는 메모리 조각조각 사이에서 필요로하는 메모리보다 큰공간을 사용하게되므로 메모리 낭비도있고 빈공간을 찾아야하는 호출비용도 존재합니다.<br><br>최적화 기법중에는 stack메모리를 크게할당해둔다음 데이터를 수동으로 stack메모리에서 관리해주는 방법도 있습니다. 하지만 이는 생산성이 떨어지는 단점이 있어서 특별한경우를 제외하고는 잘 사용하지 않습니다. Ownership 개념을위해 짧게 정리하고 넘어갑니다.</p>



<pre class="wp-block-code"><code>fn main() {
    let score: i32 = 100;                                // stack
    let name: String = String::from("김개똥");     // heap
}</code></pre>



<p>name 변수를 일반변수로 설정해도 heap 메모리에 저장되게 됩니다. 만약 문자열을 stack메모리에 올리고싶으면, 아래처럼 사용해야합니다.</p>



<pre class="wp-block-code"><code>let stack_str: &#91;u8; 9] = *b"Hello Rust";</code></pre>



<h3 class="wp-block-heading">Ownership</h3>



<p>오너십은 조건</p>



<ul class="wp-block-list">
<li>각 변수는 오너십을 갖고있다.</li>



<li>오너십은 단 한명만 갖는다.</li>



<li>오너가 스코프를 넘어가는경우 값은 사라진다. &#8211; 가비지콜렉터 대용기능</li>
</ul>



<h4 class="wp-block-heading">scope의 개념</h4>



<pre class="wp-block-code"><code> {                      
        let s = "hello";   // s는 이 라인 이후로 사용 가능

        // s 를 사용
}                            // 여기서부터는 스코프를 떠나서 s는 더이상 사용 불가능</code></pre>



<h4 class="wp-block-heading">소유권 이동</h4>



<p>먼저 아래의 경우 integer 타입 변수는 사이즈를 알고있고, 때문에 x 와 y 모두 5라는값을 스택메모리에 저장하게됩니다.</p>



<pre class="wp-block-code"><code>{
    let x = 5;
    let y = x;
}</code></pre>



<p> 문자열 형식의 경우, 힙메모리를 사용하기때문에 아래처럼 코드를 작성할경우 아래 그림처럼 hello 문자열이 담긴 주소(포인터)가 복사되게 된다. 좋게 말하면 포인터 코드를 알지못해도 포인터를 사용한것처럼 낼수있는것이고. 단점이라면, 포인터를 사용하진않지만 실제로는 포인터개념을 알고있어야 Rust를 잘 사용할수 있다는 이야기 이기도 하다.</p>



<p> s2에 s1을 대입하는 순간 소유권이 s2로 이동해서, s1은 사용불가 -> s1을 사용하려 하면 컴파일 에러</p>



<pre class="wp-block-code"><code>{
    let s1 = String::from("hello");
    let s2 = s1;                   // 이 statement 이후 s1은 사용불가
}</code></pre>



<figure class="wp-block-image is-resized"><img decoding="async" src="https://doc.rust-lang.org/book/img/trpl04-02.svg" alt="Three tables: tables s1 and s2 representing those strings on the
stack, respectively, and both pointing to the same string data on the heap." style="width:448px;height:auto"/></figure>



<h4 class="wp-block-heading">drop 타이밍</h4>



<p>같은 s변수에 문자열을 두번 초기화 하는 경우엔, 2개의 힙메모리가 할당이 되는데 2 번 statement가 실행되는순간 아래 그림처럼 s변수는 ahoy문자열이 저장된 주소를 가리키게된다.</p>



<p>Rust에서는 메모리를 해제하는것을 drop 함수로 진행하는데 drop함수가 호출되는 부분은 4번 scope를 떠나는 순간이므로 hello라는 메모리는 3번 statement가 실행된 이후에도 메모리에는 실제로 남아있다. 이렇게 작동하는 이유는 좀더 복잡한코드에서 1번과 2번 statement사이에서 s의 소유권을 가져가진 않지만 참조로 읽을수있는 다른객체가 존재할수 있기때문이다.</p>



<pre class="wp-block-code"><code>{
    let mut s = String::from("hello");  // 1
    s = String::from("ahoy");            // 2

    println!("{s}, world!");                // 3
}                                             // 4</code></pre>



<figure class="wp-block-image is-resized"><img decoding="async" src="https://doc.rust-lang.org/book/img/trpl04-05.svg" alt="One table representing the string value on the stack, pointing to
the second piece of string data (ahoy) on the heap, with the original string
data (hello) grayed out because it cannot be accessed anymore." style="aspect-ratio:0.7734708763155153;width:427px;height:auto"/></figure>



<h4 class="wp-block-heading">deep copy 깊은 복사</h4>



<p>만약 문자열을 복사 하고싶다면? 아래처럼 clone() 함수를 사용해주면된다.</p>



<pre class="wp-block-code"><code>    let s1 = String::from("hello");
    let s2 = s1.clone();

    println!("s1 = {s1}, s2 = {s2}");</code></pre>



<p>구조체 객체에 저장할때 소유권을 넘겨주면 되지만 여러 객체에 할당하거나 다른이유로 원본(s1)을 유지하고싶으면 clone 명령어로 깊은복사를 해야한다.</p>



<pre class="wp-block-code"><code>struct User {
    username: String,
}

fn main() {
    let current_name = String::from("김개똥");

    // User 구조체가 username의 소유권을 가져야 하므로 복사본을 만듭니다.
    let user1 = User {
        username: current_name.clone(),
    };

    // 여전히 current_name을 다른 곳(예: 로그 출력)에 쓸 수 있습니다.
    println!("가입 신청자: {}", current_name);
}</code></pre>



<h4 class="wp-block-heading">Return Values and Scope 함수 리턴과 스코프</h4>



<p>아래코드는 <a href="https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html">https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html</a> 에서 빌려왔다. 이해해야할 포인트가 몇군데 있다. some_string은 gives_ownersihp 함수에서 선언되었지만, 해당 함수가끝나도 yours 문자열은 drop되지않는다. 소유권이 이미 s1변수로 넘어갔기때문이다. 그리고 s2에서 생성된 hello 문자열은 takes_and_gives_back 함수로 소유권을 전달하지만 해당함수 리턴값으로 소유권을 돌려받는다. 여기서 중요한건 그냥 문자열을 전달하듯 사용했을뿐인데, C++에서 포인터를 통해 문자열을 전달했다가 돌려받은것처럼 메모리 복사가 발생하지 않는다는것이다.</p>



<pre class="wp-block-code"><code>fn main() {
    let s1 = gives_ownership();        // gives_ownership moves its return
                                       // value into s1

    let s2 = String::from("hello");    // s2 comes into scope

    let s3 = takes_and_gives_back(s2); // s2 is moved into
                                       // takes_and_gives_back, which also
                                       // moves its return value into s3
} // Here, s3 goes out of scope and is dropped. s2 was moved, so nothing
  // happens. s1 goes out of scope and is dropped.

fn gives_ownership() -> String {       // gives_ownership will move its
                                       // return value into the function
                                       // that calls it

    let some_string = String::from("yours"); // some_string comes into scope

    some_string                        // some_string is returned and
                                       // moves out to the calling
                                       // function
}

// This function takes a String and returns a String.
fn takes_and_gives_back(a_string: String) -> String {
    // a_string comes into
    // scope

    a_string  // a_string is returned and moves out to the calling function
}</code></pre>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.kggstudio.com/rust10-ownership/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">328</post-id>	</item>
	</channel>
</rss>
