데이터 구조와 컬렉션: 효율적인 데이터 관리
학습 목표: 파이썬의 리스트, 딕셔너리, 튜플이 Rust에서는 어떻게 대응되는지 배웁니다. 특히 파이썬의 클래스를 대체하는 Rust의 구조체(Struct) 시스템과, 힙 메모리를 효율적으로 사용하는 **컬렉션(
Vec,HashMap)**의 활용법을 익힙니다.
1. 튜플과 구조 분해 (Tuples & Destructuring)
파이썬의 튜플과 거의 동일하게 작동하지만, Rust의 튜플은 고정된 크기와 타입을 가집니다.
# [Python] 언패킹
point = (10, 20)
x, y = point
#![allow(unused)] fn main() { // [Rust] 구조 분해 let point = (10, 20); let (x, y) = point; // 인덱스 접근은 대괄호([])가 아닌 점(.)을 사용합니다. let first = point.0; // 10 }
2. 배열(Array)과 슬라이스(Slice)
파이썬의 리스트 슬라이싱과 비슷해 보이지만, Rust의 슬라이스는 복사하지 않고 원본을 바라보는 '뷰(View)' 역할을 합니다.
- 배열 (
[T; N]): 크기가 고정된 스택 할당 데이터. - 슬라이스 (
&[T]): 배열이나 벡터의 일부분을 가리키는 참조자. 파이썬의data[1:4]가 새 리스트를 만드는 것과 달리, Rust의 슬라이싱은 추가 메모리 할당이 없습니다.
3. 구조체 vs 클래스 (Structs vs Classes)
파이썬의 클래스를 Rust에서는 구조체(struct)와 구현체(impl)로 나누어 정의합니다. 상속은 지원하지 않으며, 대신 **트레이트(Trait)**를 통해 기능을 조합합니다.
| 기능 | Python 클래스 | Rust 구조체 | 비고 |
|---|---|---|---|
| 속성 정의 | class 내부에 정의 | struct 내부에 정의 | |
| 메서드 정의 | 클래스 블록 내부 | impl 블록 내부 | |
| 생성자 | __init__ | 보통 fn new() 관례 | |
| 특수 메서드 | __str__, __eq__ | Display, PartialEq 등 트레이트 구현 |
💡 메모리 상의 차이
파이썬 객체는 모든 필드가 힙에 흩어져 있고 헤더 정보가 큽니다. 반면 Rust 구조체는 필드들이 메모리에 연속적으로 배치되어 훨씬 빠르고 가볍습니다.
4. 주요 컬렉션: Vec과 HashMap
Vec<T> (파이썬의 list 대응)
동적으로 크기가 변하는 배열입니다.
- 추가:
push()(파이썬의append) - 제거:
pop() - 포함 확인:
contains()
HashMap<K, V> (파이썬의 dict 대응)
키-값 쌍을 저장하는 대시 맵입니다.
- 삽입:
insert() - 값 가져오기:
get()(결과가Option으로 반환됨) - Entry API: 파이썬의
defaultdict나setdefault처럼 "값이 없으면 넣고, 있으면 가져오기"를 한 번에 처리합니다.
#![allow(unused)] fn main() { // 단어 빈도수 계산 예시 (Entry API) let mut counts = HashMap::new(); for word in sentence.split_whitespace() { *counts.entry(word).or_insert(0) += 1; } }
💡 실무 팁: in 연산자 대신 contains
파이썬의 if x in my_list:는 Rust에서 if my_vec.contains(&x) { ... }로 작성합니다. Rust는 값의 소유권을 넘기지 않기 위해 참조자(&)를 사용한다는 점에 주의하세요.