Menu
Coddy logo textTech

Clone과 Copy

Coddy Rust 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 61개 중 37번째.

Rust에서 값을 another 변수에 할당하면 일반적으로 소유권이 이동합니다. 원래 변수는 유효하지 않게 됩니다. 하지만 두 가지 표준 트레이트인 CloneCopy가 이러한 동작을 변경합니다.

Copy 트레이트는 암시적 비트 단위 복사를 가능하게 합니다. 어떤 타입이 Copy를 구현하면, 이를 다른 변수에 할당할 때 소유권을 이동하는 대신 자동으로 복사본이 생성됩니다:

#[derive(Copy, Clone)]
struct Point {
    x: i32,
    y: i32,
}

let p1 = Point { x: 10, y: 20 };
let p2 = p1;  // p1은 복사되며, 이동되지 않음

println!("{}, {}", p1.x, p2.x);  // 둘 다 유효합니다!

Clone 트레이트는 .clone() 메서드를 통해 explicit 깊은 복사를 제공합니다. Copy를 derive할 때 필요하지만, 명시적인 복사가 필요한 타입에서는 단독으로 사용할 수도 있습니다.

let p3 = p1.clone();  // 명시적 복사

중요한 제한 사항이 있습니다. 모든 필드 또한 Copy를 implement하는 타입에 대해서만 Copy를 derive할 수 있습니다. 정수와 부동 소수점 수 같은 단순한 타입은 Copy이지만, String은 그렇지 않습니다. String은 힙 메모리를 관리합니다. 구조체에 String이 포함되어 있다면 Clone만 derive할 수 있고 Copy는 derive할 수 없습니다.

트레이트동작사용
Copy암시적, 자동스택 전용 단순 데이터
Clone.clone()을 통한 명시적 수행복제 가능한 모든 데이터

기본형 필드를 가진 간단한 구조체의 경우 두 특성을 모두 파생하면 소유권을 걱정하지 않고 값을 자유롭게 할당할 수 있습니다.

challenge icon

챌린지

쉬움

Copy 트레이트와 Clone 트레이트의 차이를 보여 주는 좌표 시스템을 만들어 봅시다! 암시적으로 복사할 수 있는 구조체와 명시적인 클로닝이 필요한 구조체를 각각 하나씩 만들어, 파생하는 트레이트에 따라 Rust가 중복을 서로 다르게 처리하는 방식을 확인합니다.

코드를 두 파일로 나누어 구성합니다:

  • coordinates.rs: 서로 다른 종류의 좌표를 나타내는 두 개의 public 구조체를 Define합니다:
    • GridPoint: public xy fields(둘 다 i32)를 가집니다. primitive type만 포함하므로 CopyClone을 모두 derive하여 할당할 때 암시적으로 복사할 수 있도록 합니다.
    • NamedLocation: public name(String) 및 x/y fields(i32)를 가집니다. String을 포함하므로 Copy가 아닌 Clone만 derive할 수 있습니다. 이 구조체는 중복을 만들려면 명시적인 .clone() 호출이 필요합니다.
  • main.rs: coordinates 모듈을 가져오고 각 구조체가 중복될 때 어떻게 다르게 동작하는지 Demonstrate합니다. 제공된 inputs를 사용해 인스턴스를 만든 다음 다음을 보여 줍니다:
    • GridPoint를 another 변수에 할당해도 두 값이 모두 유효하게 유지됩니다(implicit copy).
    • NamedLocation은 원본을 유효하게 유지하면서 duplicate를 만들려면 .clone()을 사용해야 합니다.

중복한 뒤 두 변수가 모두 유효하다는 것을 증명하기 위해 original 및 copied/cloned 값을 모두 출력해야 합니다:

Original point: ({x}, {y})
Copied point: ({x}, {y})
Original location: {name} at ({x}, {y})
Cloned location: {name} at ({x}, {y})

예를 들어 inputs가 5, 10, Home인 경우:

Original point: (5, 10)
Copied point: (5, 10)
Original location: Home at (5, 10)
Cloned location: Home at (5, 10)

세 개의 inputs를 받습니다: x 좌표(i32로 parse), y 좌표(i32로 parse), 그리고 location name입니다.

직접 해보기

mod coordinates;

use coordinates::{GridPoint, NamedLocation};

fn main() {
    // 입력 읽기
    let mut input1 = String::new();
    std::io::stdin().read_line(&mut input1).expect("Failed to read line");
    let x: i32 = input1.trim().parse().expect("Invalid number");

    let mut input2 = String::new();
    std::io::stdin().read_line(&mut input2).expect("Failed to read line");
    let y: i32 = input2.trim().parse().expect("Invalid number");

    let mut input3 = String::new();
    std::io::stdin().read_line(&mut input3).expect("Failed to read line");
    let name = input3.trim().to_string();

    // TODO: x와 y로 GridPoint 인스턴스 생성

    // TODO: 다른 변수에 할당하여 암시적 복사 시연
    // (GridPoint는 Copy를 구현하므로 자동으로 복사본이 생성됩니다)

    // TODO: 원본과 복사된 포인트 출력
    // Format: "Original point: ({x}, {y})"
    // 형식: "Copied point: ({x}, {y})"

    // TODO: name, x, y로 NamedLocation 인스턴스 생성

    // TODO: 명시적 클론 시연 (NamedLocation은 Clone만 구현하고 Copy는 구현하지 않음)
    // .clone()을 사용하여 복제본 생성

    // TODO: Print original and cloned location
    // Format: "Original location: {name} at ({x}, {y})"
    // Format: "Cloned location: {name} at ({x}, {y})"
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨

직접 연습해 보세요: 온라인 Rust 컴파일러