소개
변수는 하나의 값을 저장하지만, 많은 프로그램에서는 길이를 변경할 수 있는 순서 있는 목록이 필요합니다. Rust의 Vec<T>는 확장 가능한 시퀀스입니다. 모든 요소의 타입은 T이고, 값의 순서는 유지되며, 벡터가 요소의 소유권을 가집니다.
카페 주문 목록을 만들고, 특정 위치의 값을 안전하게 읽고, 목록을 소비하지 않고 모든 주문을 확인하고, 가변 참조를 통해 저장된 모든 문자열을 수정합니다.
벡터 만들고 확장하기
이 단계에서는 처음에 비어 있는 벡터에 소유된 문자열 3개를 추가합니다.
준비된 프로젝트로 이동해 소스 파일을 엽니다.
cd /home/labex/project/cafe-orders
nano src/main.rs
Vec<String> 선언은 “요소가 소유된 String 값인 벡터”를 의미합니다. 이는 Option<u32>에서 본 컨테이너 형태의 꺾쇠괄호 표기와 같습니다. 여기서 컨테이너에 들어가는 요소의 타입은 String입니다. 이처럼 재사용할 수 있는 타입을 정의하는 방법은 뒤의 제네릭 Lab에서 배웁니다. Vec::new()는 비어 있는 벡터를 만듭니다. 요소를 추가하면 벡터가 변경되므로 바인딩에 mut가 필요합니다.
Step 1 주석을 다음 세 개의 push 호출로 바꿉니다.
orders.push(String::from("Latte"));
orders.push(String::from("Tea"));
orders.push(String::from("Cake"));
push는 요소 하나를 끝에 추가하며, 추가된 순서를 유지합니다. Ctrl+O로 저장하고 Enter를 누른 다음 Ctrl+X로 종료합니다. 코드를 확인하고 실행합니다.
cargo check
cargo run --quiet
출력은 다음과 같아야 합니다.
Order count: 3
Orders: ["Latte", "Tea", "Cake"]
len()은 요소가 3개임을 보여 줍니다. :? 플레이스홀더는 Rust의 디버그 형식을 사용해 전체 벡터를 표시하며, 문자열 주위의 따옴표도 함께 출력합니다.
위치에 안전하게 접근하기
이 단계에서는 범위를 벗어나 패닉이 발생할 위험 없이 벡터의 두 번째 위치를 읽습니다.
벡터의 위치는 0부터 시작하므로 인덱스 1은 두 번째 주문을 가리킵니다. get 메서드는 Option<&String>을 반환합니다. 해당 위치가 있으면 Some 안에 공유 참조가 들어 있고, 위치가 없으면 None이 됩니다. 이 참조를 사용하면 벡터가 요소의 소유권을 계속 유지하는 동안 요소를 읽을 수 있습니다.
소스 파일을 엽니다.
nano src/main.rs
Step 2 주석을 다음 코드로 바꿉니다.
match orders.get(1) {
Some(order) => println!("Second order: {order}"),
None => println!("Second order: missing"),
}
이 코드는 벡터에서 String의 소유권을 이동시키지 않고 요소를 읽습니다. 저장하고 종료한 다음 실행합니다.
cargo run --quiet
출력의 마지막에 다음 줄이 새로 나타나야 합니다.
Second order: Tea
이 줄은 위치 1이 존재하고, 요소를 추가한 순서가 유지되었음을 보여 줍니다.
공유 참조로 반복하기
이 단계에서는 이후에도 벡터를 계속 사용할 수 있도록 유지하면서 모든 주문을 차례로 확인합니다.
&orders를 작성하면 벡터를 for 루프 안으로 이동시키지 않고 빌립니다. 따라서 루프 변수에는 저장된 String 하나를 가리키는 공유 참조가 차례로 들어갑니다.
소스 파일을 엽니다.
nano src/main.rs
Step 3 주석을 다음 루프와 후속 확인 코드로 바꿉니다.
for order in &orders {
println!("Queued: {order}");
}
println!("Stored after display: {}", orders.len());
저장하고 종료한 다음 실행합니다.
cargo run --quiet
다음 줄이 새로 출력되어야 합니다.
Queued: Latte
Queued: Tea
Queued: Cake
Stored after display: 3
루프가 벡터를 빌리고 각 공유 대여를 다음 반복으로 넘어가기 전에 반환하므로, 루프가 끝난 뒤에도 최종 개수를 사용할 수 있습니다.
가변 참조로 수정하기
이 단계에서는 표시 루프가 실행되기 전에 벡터의 각 요소를 가변으로 빌려 제자리에서 수정합니다.
하나의 값에 대해서는 한 번에 하나의 가변 참조만 활성화할 수 있습니다. &mut orders를 사용하는 for 루프는 가변 요소 참조를 하나씩 제공하고, 현재 반복에서 사용한 뒤 다음 요소로 이동하므로 이 규칙을 만족합니다.
소스 파일을 엽니다.
nano src/main.rs
Step 4 주석을 다음 코드로 바꿉니다.
for order in &mut orders {
order.push_str(" - ready");
}
push_str는 빌린 텍스트를 각 소유된 String에 추가합니다. Rust는 이 메서드 호출에서 각 참조가 가리키는 가변 String을 자동으로 사용합니다.
저장하고 종료한 다음 코드를 확인하고 실행합니다.
cargo check
cargo run --quiet
전체 출력은 다음과 같아야 합니다.
Order count: 3
Orders: ["Latte", "Tea", "Cake"]
Second order: Tea
Queued: Latte - ready
Queued: Tea - ready
Queued: Cake - ready
Stored after display: 3
업데이트된 대기열 출력은 모든 요소가 제자리에서 변경되었음을 보여 줍니다. 마지막 개수는 벡터가 동일한 문자열 3개의 소유권을 계속 유지하고 있음을 보여 줍니다.
요약
Vec<String>을 만들고 확장했으며, get으로 특정 위치에 안전하게 접근하고, 벡터를 소비하지 않고 반복하고, 가변 참조를 통해 모든 요소를 수정했습니다.


