IMCAT.DEV
로그인 가입
Rust 입문 자료구조

Rust 결과 타입 (Result)

Rust 결과 타입 (Result) — 초급

결과 타입 (Result)

1. 도입 (왜 배워야 하는가)

Rust에서는 오류 처리가 매우 중요합니다. 실무에서 프로그램이 예기치 않은 상황에 처했을 때, 어떻게 대처할지를 미리 준비해두는 것이 필수적입니다. Result 타입은 이러한 오류 처리를 위한 Rust의 기본적인 방법으로, 함수가 성공적으로 실행됐는지, 아니면 오류가 발생했는지를 나타냅니다. 만약 이 개념을 모른다면, 프로그램이 크래시하거나 예기치 않은 동작을 하게 되어 사용자의 신뢰를 잃을 수 있습니다. 따라서, Result 타입을 이해하고 활용하는 것은 안정적인 프로그램을 만들기 위한 첫걸음입니다.

2. 핵심 개념 설명

Result 타입은 두 가지 변형으로 구성됩니다: Ok와 Err.
  • Ok(T)는 성공적인 결과를 나타내며, T는 성공적으로 반환할 값의 타입입니다.
  • Err(E)는 오류를 나타내며, E는 오류의 타입입니다.

이것은 마치 일상생활에서의 주문과 같습니다. 음식 주문을 할 때, 음식이 잘 도착하면 "주문 성공"이라는 메시지를 받습니다. 그러나 만약 음식이 잘못 왔다면 "주문 실패"라는 메시지를 받게 됩니다. 여기서 Ok는 "주문 성공", Err는 "주문 실패"에 해당합니다.

용어설명
Result성공 또는 실패를 나타내는 타입
Ok성공적인 결과
Err실패한 결과

3. 기본 코드 예제

다음은 Result 타입을 사용하는 가장 기본적인 예제입니다.

fn divide_numbers(dividend: f64, divisor: f64) -> Result<f64, String> {
    if divisor == 0.0 {
        Err("0으로 나눌 수 없습니다.".to_string()) // 오류 발생
    } else {
        Ok(dividend / divisor) // 성공적인 결과
    }
}

fn main() {
    match divide_numbers(10.0, 2.0) {
        Ok(result) => println!("결과: {}", result), // 결과: 5
        Err(e) => println!("오류: {}", e), // 오류 메시지 출력
    }
}

실행 결과:

결과: 5

코드 한 줄씩 동작 설명:

  1. divide_numbers 함수는 두 개의 매개변수를 받아들이고 Result<f64, String> 타입을 반환합니다.
  2. if 문을 사용하여 분모가 0인지 확인합니다.
  3. 0이라면 Err를 반환하며 오류 메시지를 문자열로 변환합니다.
  4. 그렇지 않으면 Ok로 나눈 결과를 반환합니다.
  5. main 함수에서 match 구문을 사용하여 결과를 처리합니다.
  6. 성공적으로 나누어졌다면 결과를 출력하고, 오류가 발생했으면 오류 메시지를 출력합니다.
  7. 4. 실전 활용 예제

    예제 1: 파일 읽기

    쇼핑몰에서 상품 정보를 파일로부터 읽어올 때, 파일이 없거나 읽는 도중 문제가 발생할 수 있습니다.

    use std::fs::File;
    use std::io::{self, Read};
    
    fn read_file_content(file_path: &str) -> Result<String, io::Error> {
        let mut file = File::open(file_path)?;
        let mut content = String::new();
        file.read_to_string(&mut content)?;
        Ok(content)
    }

    예제 2: 사용자 입력 처리

    사용자로부터 입력을 받을 때, 잘못된 형식의 입력이 들어올 수 있습니다.

    use std::str::FromStr;
    
    fn parse_number(input: &str) -> Result<i32, String> {
        match i32::from_str(input) {
            Ok(num) => Ok(num),
            Err(_) => Err("잘못된 숫자 형식입니다.".to_string()),
        }
    }

    5. 흔한 실수와 주의사항

    실수 1: Result를 무시하기

    가끔 Result 타입을 확인하지 않고 바로 값을 사용하려는 경우가 있습니다.

    잘못된 코드:

    let result = divide_numbers(10.0, 0.0);
    println!("결과: {}", result.unwrap()); // 오류 발생

    올바른 코드:

    match result {
        Ok(value) => println!("결과: {}", value),
        Err(e) => println!("오류: {}", e),
    }

    실수 2: 잘못된 오류 처리

    오류 메시지를 단순히 출력하지 않고, 무시하는 경우.

    잘못된 코드:

    let _ = read_file_content("없는파일.txt");

    올바른 코드:

    if let Err(e) = read_file_content("없는파일.txt") {
        println!("파일 읽기 오류: {}", e);
    }

    6. 정리

  8. Result 타입은 오류 처리를 위한 Rust의 기본적인 방법입니다.
  9. Ok와 Err 변형으로 성공과 실패를 구분합니다.
  10. Result를 무시하지 않고 항상 확인하는 것이 중요합니다.
  11. 파일 읽기나 사용자 입력 처리와 같은 실전에서 유용하게 사용됩니다.
  12. 다음에 학습하면 좋은 주제: Option 타입, 패턴 매칭, 에러 핸들링을 위한 ? 연산자.