Rust가 말아주는 상자: Result

Rust

목록 보기
5/5
post-thumbnail

Result 타입 - 반환값을 감싼 상자

Resultenum타입으로, Ok (정상 결과) 혹은 Err(오류 결과)를 가집니다. 즉, 정상, 오류 둘 중 하나로 평가된다고 보면 쉽습니다. 원형을 보면 다음과 같습니다.

enum Result<T, E> {
	Ok(T),
	Err(E),
}

제네릭으로 표현된 Result<T, E>Ok로 반환하고 싶은 것과 Err로 반환하고 싶은 것을 결정해야 한다는 의미입니다. OkT타입의 값을 감싸서 반환하거나, ErrE타입의 값을 감싸서 반환하는 열거형인 셈입니다.

unwrap - 감쌌다는건 풀어야 한다는 뜻

여기서 감싸다(wrap)는 표현이 자주 쓰이는데요, Ok(1)과 그냥 1의 차이는 무엇일까요?

Ok(1)은 1을 반환하는데 성공했다는 메시지와, 값을 감싼 상자라고 이해하면 쉽습니다. 반면에 1은 말 그대로 그냥 1이라는 값입니다. Ok(1)을 굳이 비유하자면, 내부 동작 메커니즘은 다르지만 자바스크립트의 Promise.resolve(1)과 유사하다고 보면 됩니다. 1이라는 값에 접근하기 위해서는 Promise.resolve(1)await키워드나 .then같은 메서드를 사용해서 fulfill된 값을 추출하는 것 처럼, Rust의 Ok(1) 또한 감싼것을 풀어내는 작업이 필요합니다. 이 역할을 해주는 함수가 바로 unwrap()입니다.

unwrapResult타입이 가지는 함수로, Ok에 감싸진 값 또는 Err에 감싸진 에러를 말 그대로 풀어내는, unwrap 해버리는 함수입니다. unwrap이 호출되는 순간에는 이 상자가 Ok인지 Err인지 모르기 때문에, 풀어낼 대상이 Ok라면 프로그램은 정상 작동하고, Err라면 패닉합니다. 쉬운 예제를 통해 코드레벨에서 살펴보겠습니다.

fn main() {
    // 1. 일반 값
    let number = 1;
    println!("일반 값: {}", number);  // 그냥 1 출력

    // 2. Ok로 감싼 값
    let result = Ok(1);
    println!("Result 타입: {:?}", result);  // Ok(1) 출력
    
    // 3. unwrap으로 값 추출
    let unwrapped = result.unwrap();
    println!("unwrap 후: {}", unwrapped);  // 1 출력
}

만약 unwrap하는 대상이 Err라면, 프로그램은 패닉에 빠지고 종료됩니다.

fn main() {
		let error_result:Result<i32, &str> = Err("에러 발생");
		let value = error_result.unwrap(); //❌ 패닉 발생, 프로그램 종료
}
# 에러 메시지
thread 'main' panicked at src/main.rs:3:34:
called `Result::unwrap()` on an `Err` value: "에러 발생"

이를 방지하기 위해 match라는 흐름 제어 키워드를 사용할 수 있습니다. try-catch문인 셈입니다.

fn main() {
    let result: Result<String, &str> = Err("에러 발생!");
    match result { // result를 풀어본 결과가
        Ok(value) => println!("성공: {}", value), // Ok라면 이거 하고,
        Err(e) => println!("에러: {}", e) // Err라면 이거 해줘요.
    }
}
에러: 에러 발생

expect - 섬세함을 추구한 unwrap

expectunwrap과 동일하게 Result타입 값을 풀어내는 역할을 수행합니다. 하지만 expect는 Rust의 기본 에러 메세지 대신 커스텀 메세지를 예약할 수 있습니다.

fn main() {
	let error_result:Result<i32, &str> = Err("메롱");
	let value = error_result.expect("일부러 발생시킨 에러입니다: "); //❌ 패닉 발생, 프로그램 종료
}
thread 'main' panicked at src/main.rs:4:30:
일부러 발생시킨 에러입니다: : "메롱"

정리

Result 타입 값은 풀어내야 다룰 수 있고, 웬만해선 match 쓰세요

  1. Result는 상자입니다. 상자는 풀어보기 전에 안에 무엇이 들어있는지 모르기 때문에 unwrap 또는 expect로 풀어봐야 내용물을 다룰 수 있습니다.
  2. unwrap, expect는 풀어본 내용이 Err라면 프로그램이 종료됩니다. 이것을 의도한 게 아니라면 match를 써서 패닉을 방지하세요!

0개의 댓글