Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Drop

Drop 트레이트는 drop이라는 하나의 메서드만을 가집니다. 이 메서드는 객체가 스코프를 벗어날 때 자동으로 호출됩니다. Drop 트레이트의 주요 용도는 구현체 인스턴스가 소유한 리소스를 해제하는 것입니다.

Box, Vec, String, File, 그리고 Process는 리소스를 해제하기 위해 Drop 트레이트를 구현하는 몇 가지 타입의 예입니다. Drop 트레이트는 임의의 사용자 정의 데이터 타입에 대해 수동으로 구현될 수도 있습니다.

다음 예제는 drop 함수가 호출될 때 알림을 주기 위해 콘솔 출력을 추가합니다.

struct Droppable {
    name: &'static str,
}

// 이 간단한 `drop` 구현은 콘솔에 출력을 추가합니다.
impl Drop for Droppable {
    fn drop(&mut self) {
        println!("> {}를 해제합니다", self.name);
    }
}

fn main() {
    let _a = Droppable { name: "a" };

    // 블록 A
    {
        let _b = Droppable { name: "b" };

        // 블록 B
        {
            let _c = Droppable { name: "c" };
            let _d = Droppable { name: "d" };

            println!("블록 B를 나가는 중");
        }
        println!("방금 블록 B를 나갔습니다");

        println!("블록 A를 나가는 중");
    }
    println!("방금 블록 A를 나갔습니다");

    // 변수는 `drop` 함수를 사용하여 수동으로 해제할 수 있습니다.
    drop(_a);
    // TODO ^ 이 줄을 주석 처리해 보세요.

    println!("메인 함수 끝");

    // `_a`는 여기서 다시 `drop`되지 않습니다. 이미 (수동으로) `drop`되었기 때문입니다.
}

더 실용적인 예로, Drop 트레이트를 사용하여 더 이상 필요하지 않은 임시 파일을 자동으로 정리하는 방법은 다음과 같습니다:

use std::fs::File;
use std::path::PathBuf;

struct TempFile {
    file: File,
    path: PathBuf,
}

impl TempFile {
    fn new(path: PathBuf) -> std::io::Result<Self> {
        // 참고: `File::create()`는 기존 파일을 덮어씁니다.
        let file = File::create(&path)?;

        Ok(Self { file, path })
    }
}

// `TempFile`이 drop될 때:
// 1. 먼저, 우리가 작성한 drop 구현이 파일 시스템에서 파일 이름을 제거합니다.
// 2. 그런 다음, `File`의 drop이 파일을 닫고 디스크에서 기본 콘텐츠를 제거합니다.
impl Drop for TempFile {
    fn drop(&mut self) {
        if let Err(e) = std::fs::remove_file(&self.path) {
            eprintln!("임시 파일을 제거하는 데 실패했습니다: {}", e);
        }
        println!("> 임시 파일을 해제했습니다: {:?}", self.path);
        // `File`의 drop은 이 구조체의 필드이므로 여기서 암시적으로 호출됩니다.
    }
}

fn main() -> std::io::Result<()> {
    // drop 동작을 시연하기 위해 새 스코프를 생성합니다.
    {
        let temp = TempFile::new("test.txt".into())?;
        println!("임시 파일이 생성되었습니다");
        // `temp`가 스코프를 벗어날 때 파일이 자동으로 정리됩니다.
    }
    println!("스코프 종료 - 파일이 정리되어야 합니다");

    // 필요하다면 수동으로 drop할 수도 있습니다.
    let temp2 = TempFile::new("another_test.txt".into())?;
    drop(temp2); // 파일을 명시적으로 drop합니다.
    println!("수동으로 파일을 drop했습니다");

    Ok(())
}