RUST 20일 과정
Day 3: Ownership & Borrowing
@thiskorea
2025. 1. 6. 13:36
Day 3: Ownership & Borrowing
1. 수업 개요
- 주제: Rust의 핵심 철학인 Ownership(소유권)과 Borrowing(빌려 쓰기) 개념 이해
- 학습 목표:
- Rust에서의 스택과 힙, 메모리 구조를 파악한다.
- Ownership 규칙을 이해하고, Move/Copy가 어떻게 작동하는지 예제를 통해 확인한다.
- Borrowing(&, &mut)을 통해 변수(메모리)를 안전하게 공유하는 방식을 익힌다.
- 문자열 슬라이스 등 Slice 개념을 이해하고 실습해본다.
2. 이론
스택(Stack)과 힙(Heap)
- 스택: 함수 호출 시 빠르게 할당/해제되는 정적 메모리 구역
- 힙: 동적 메모리 할당이 이루어지는 공간 (Box, String, Vec 등은 힙 메모리를 사용)
Ownership(소유권) 규칙
- 규칙 1: 각 값(value)은 오직 하나의 Owner(소유자) 변수만 가진다.
- 규칙 2: Owner(소유자)가 스코프를 벗어나면, 그 값은 자동으로 메모리 해제된다(Drop).
- 예시:
{
let s = String::from("Hello");
// 여기서 s는 "Hello" 문자열의 소유자
}
// 스코프 밖으로 나가면 s는 Drop되어 메모리가 해제됨
Move(이동)와 Copy(복사)
- Move: 힙 데이터를 가진 변수를 다른 변수에 할당할 때, 소유권이 넘어간다.
let s1 = String::from("Rust");
let s2 = s1;
// s1 -> s2 로 소유권이 이동(Move)
// 이제 s1은 유효하지 않음
let x = 5;
let y = x;
// x와 y 모두 유효
Borrowing(대여, 참조)
- 불변 참조(&): 읽기 전용 접근
- 가변 참조(&mut): 읽고/쓰기가 모두 가능하지만, 특정 시점에 오직 하나만 허용
fn main() {
let mut s = String::from("Hello");
// 불변 참조
let r1 = &s;
let r2 = &s;
// 가변 참조
let r3 = &mut s;
// 불변 참조와 가변 참조를 동시에 사용하는 것은 컴파일 에러
}
- 동시에 여러 불변 참조는 가능
- 가변 참조는 한 번에 하나만 가능 (데이터 레이스 방지)
- 참조는 유효 범위 내에서만 사용 가능 (Owner 스코프가 끝나면 무효)
Slice(슬라이스) 기초
- 문자열이나 배열의 특정 구간을 참조하는 방법
&str
,[T]
등의 슬라이스
let greeting = String::from("Hello Rust");
let hello = &greeting[0..5]; // "Hello"
let rust = &greeting[6..]; // "Rust"
// greeting이 스코프를 벗어나면 hello, rust도 사용 불가
3. 실습
Move, Copy 개념 실습
String
타입 변수를 선언하고, 다른 변수에 대입해본다.- 소유권이 이동한 뒤 원래 변수를 사용하면 컴파일 에러가 발생함을 확인한다.
- 정수형 변수를 복사할 땐 문제가 없음을 비교해본다.
Borrowing 실습
fn main() {
let s1 = String::from("Borrow me");
let len = calculate_length(&s1);
println!("'{}'의 길이는 {}", s1, len);
}
fn calculate_length(s: &String) -> usize {
s.len()
}
문자열 슬라이스 실습
- 문자열의 특정 구간을 슬라이스로 추출해 출력
- 슬라이스로 반환하는 함수를 작성해보기:
fn first_word(s: &String) -> &str {
// 공백이나 특정 문자를 만나기 전까지의 단어를 슬라이스로 반환
}
4. 마무리 및 과제
오늘 배운 내용 정리
- Ownership: 소유권과 스코프가 연동되어 메모리 관리가 자동화됨
- Move/Copy: 힙 데이터 vs 스택 데이터
- Borrowing: 불변 참조 & 가변 참조 사용 시 주의 사항
- Slice(슬라이스) 개념과 문자열 슬라이스 활용
과제(실습 문제)
- 다음 코드에서 발생하는 에러를 해결해보자:
- 문자열 슬라이스를 이용해 문장에서 첫 단어만 추출하는 함수를 완성하고, 테스트
- Move와 Copy가 각각 어떻게 다른지, 예시 코드를 작성해 GitHub에 올리기(가능하다면).
fn main() {
let mut text = String::from("Day3");
let ref1 = &text;
let ref2 = &mut text;
println!("{}", ref1);
println!("{}", ref2);
}
학습 팁
- Rust 컴파일러의 에러 메시지를 꼼꼼히 읽으면, Ownership & Borrowing에서 발생하는 문제를 빠르게 찾을 수 있음.
- 문자열 슬라이스(
&str
)를 잘 활용하면, 데이터를 복사하지 않고도 특정 부분을 효율적으로 처리 가능. - 이 개념들을 이해해두면 이후에 Struct, Enum 등 더 복잡한 데이터 구조를 다룰 때 훨씬 수월해진다.
5. 수업 진행 예시 타임라인 (총 50분 수업 기준)
- 10분: 이론: 스택/힙, Ownership & Borrowing 개념 설명
- 20분: 실습: Move/Copy, 참조 & 가변 참조, 슬라이스 예제 코딩 & 테스트
- 10분: 에러 메시지 분석 및 디버깅(에러 예시 코드 함께 수정해보기)
- 5분: 수업 정리, 질의응답
- 5분: 과제 안내 및 마무리
정리: Rust의 Ownership & Borrowing은 런타임에 비용을 추가하지 않고도 메모리 안전성을 보장하는 핵심 메커니즘입니다.