NeuroWhAI의 잡블로그

[Rust] 중첩 Result 사용. 본문

개발 및 공부/언어

[Rust] 중첩 Result 사용.

NeuroWhAI 2020. 4. 9. 22:01


http://sled.rs/errors

 

Error Handling in a Correctness-Critical Rust Project

sled home documentation support blog introduction to sled motivating experiences error handling in Rust Error Handling in a Correctness-Critical Rust Project Let’s begin with two excerpts from the paper Simple Testing Can Prevent Most Critical Failures: An

sled.rs

에러를 올바르게 다루는 방법에 대한 글에서 나온 중첩 Result 사용 예가 인상깊어서 가져왔습니다.

 

보통의 Rust 에러 처리 방식은 아래와 같습니다.

enum Error {
  Io(std::io::Error),
  CompareAndSwap(CompareAndSwapError),
}

에러 타입을 선언하고

fn compare_and_swap(
  &mut self,
  key: Key,
  old_value: Value,
  new_value: Value
) -> Result<(), sled::Error>

Result와 함께 씁니다.

그런데 여기 문제가 있습니다.

CompareAndSwap 에러는 지극히 정상적인 상황에서도 발생 가능한 것이고 올바르게 즉시 처리되어줘야 합니다.

Io 에러는 그렇지 않아서 시스템을 종료시켜야 한다고 합시다.

위 시나리오를 올바르게 다루려면 아래와 같이 에러를 처리해야 합니다.

let result = sled.compare_and_swap(
  "dogs",
  "pickles",
  "catfood"
);
match result {
  Ok(()) => {},
  Err(sled::Error::Io(io_error)) =>
    return Err(io_error.into()), // 비정상적인 상황!
  Err(sled::Error::CompareAndSwap(cas_error)) => {
    // 예상된 에러 처리.
  }
}

근데 사람은 실수를 할 수 있기 때문에 compare_and_swap 함수를 쓸 때 저런 에러 처리 루틴을 까먹고 못 지킬 수 있습니다.

그냥 `unwrap`을 써버리거나 `try!`나 `?`로 에러 종류에 상관없이 밖으로 전파시킬 우려가 있죠.

이걸 중첩 Result로 해결할 수 있다고 합니다.

fn compare_and_swap(
  &mut self,
  key: Key,
  old_value: Value,
  new_value: Value
) -> Result<Result<(), CompareAndSwapError>, sled::Error>

이렇게 보기 안 좋게 바꾸는 것입니다.

그러면 에러 처리 루틴이 아래와 같이 단순화됩니다.

// try `?`를 써도 문제 없음.
let cas_result = sled.compare_and_swap(
  "dogs",
  "pickles",
  "catfood"
)?;

if let Err(cas_error) = cas_result {
    // 예상된 에러 처리.
}

`?`로 가장 바깥의 Result를 처리하면 비정상적인 상황(IO 에러)일 때만 오류가 밖으로 전파되고 그 외의 성공 상태나 예상된 에러일 땐 내부 실행 흐름이 유지됩니다.

그러니 다음에 얻은 내부 Result를 이용하여 예상된 에러를 처리해주면 됩니다.

반환형이 눈에 띄고 의도를 잘 보여주며 제대로 된 형식으로 처리하지 않으면 컴파일 경고나 에러를 볼 것이라 제대로 된 형태로 에러를 처리할 수 밖에 없게 됩니다.

 

'개발 및 공부 > 언어' 카테고리의 다른 글

[Rust] do-while  (0) 2020.05.03
[Rust] Generics와 Associated Types  (0) 2020.04.04
[Rust] 직접 block_on 함수 만들기 (포스팅 소개)  (0) 2020.01.31
[C++] Concept 맛보기  (1) 2020.01.10
[Rust] Pin과 Unpin 설명.  (0) 2019.09.26


Comments