Rust - 예외 처리 방법 (Exception handling)

러스트의 에러와 예외 처리 방법에 대해서 알아보겠습니다.

1. 러스트의 에러

러스트는 두가지 에러가 있습니다.

  • 복구 가능한 에러(Recoverable Error)
  • 복구 불가능한 에러(Unrecoverable Error)

복구 가능한 에러는 프로그램에서 문제가 발생한 것을 캐치하고 예외 처리를 할 수 있습니다.

반면에, 복구 불가능한 에러는 에러를 발생시키며 프로그램이 종료됩니다.

2. 복구 불가능한 에러(Unrecoverable Error)

복구 불가능한 에러는 에러 발생 즉시 프로그램이 종료되며, 개발자에게 문제가 발생했음을 알리며 디버깅 정보를 제공합니다.

panic!() 함수

panic!(msg)을 사용하여 복구 불가능한 에러를 명시적으로 발생시킬 수 있습니다.

  • 프로그램 동작 중, 예상하지 못한 동작을 할 때 panic 함수로 프로그램을 즉시 종료시킬 수 있음
fn main() {
    panic!("Something wrong, crash");
}

위의 코드를 실행하면 에러가 발생하여 프로그램이 종료되면서 인자로 전달된 메시지와 콜스택이 함께 출력됩니다.

thread 'main' panicked at 'Something wrong, crash', src/main.rs:2:5
stack backtrace:
   0: rust_begin_unwind
             at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library/std/src/panicking.rs:579:5
   1: core::panicking::panic_fmt
             at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library/core/src/panicking.rs:64:14
   2: RustExample::main
             at ./src/main.rs:2:5
   3: core::ops::function::FnOnce::call_once
             at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library/core/src/ops/function.rs:250:5

잘못된 참조로 발생하는 panic!() 에러

명시적으로 panic!()을 호출하지 않아도, 프로그램 실행 중 잘못된 참조를 하면 내부에서 panic!() 에러가 발생합니다.

  • 아래 예제는 존재하지 않는 index 99의 값을 참조 시도 시 panic 발생
fn main() {
    let v = vec![1, 2, 3];
    v[99];
}

Output:

thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 99', src/main.rs:3:5
stack backtrace:
   0: rust_begin_unwind
             at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library/std/src/panicking.rs:579:5
   1: core::panicking::panic_fmt
             at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library/core/src/panicking.rs:64:14
   2: core::panicking::panic_bounds_check
             at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library/core/src/panicking.rs:159:5
   3: <usize as core::slice::index::SliceIndex<[T]>>::index
             at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library/core/src/slice/index.rs:260:10
   4: core::slice::index::<impl core::ops::index::Index<I> for [T]>::index
             at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library/core/src/slice/index.rs:18:9
   5: <alloc::vec::Vec<T,A> as core::ops::index::Index<I>>::index
             at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library/alloc/src/vec/mod.rs:2703:9
   6: RustExample::main
             at ./src/main.rs:3:5

2. 복구 가능한 에러(Recoverable Error)

일부 함수들은 수행 결과를 Result로 리턴합니다.

Result는 함수의 성공 여부를 OkErr로 표현하며, Ok는 정상적인 리턴 값이 포함되며, Err은 에러가 포함됩니다.

즉, Result로부터 실행 결과가 성공했는지 체크하고 결과 값을 꺼내서 사용해야 합니다.

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

File open 예제

File::open(path)은 path의 파일을 열고 Result<File>로 결과를 리턴합니다.

  • File이 존재하면 리턴 값은 Ok(file)이 되고, 존재하지 않으면 Err(error)가 됩니다.
  • match 문을 이용하여 Result Ok일 때 File을 변수에 할당하며, Err일 때는 panic을 발생시켜 프로그램을 종료시킴
use std::fs::File;

fn main() {
    let f = File::open("hello.txt");

    let f: File = match f {
        Ok(file) => file,
        Err(error) => {
            panic!("There was a problem opening the file: {:?}", error)
        },
    };
}

unwrap()으로 예외처리

위의 예제는 match를 사용하여 코드가 좀 길어졌는데, unwrap()을 사용하면 아래와 같이 짧게 구현할 수 있습니다.

  • unwrap()은 Result가 Ok일 때 File 값을 리턴하여 변수에 할당하며, Err일 때 panic!을 발생시킴
use std::fs::File;

fn main() {
    let f = File::open("hello.txt");

    let f: File = f.unwrap();
}

파일이 존재하지 않을 때 아래와 같이 panic이 발생합니다.

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 2, kind: NotFound, message: "No such file or directory" }', src/main.rs:6:21
stack backtrace:

expect()으로 예외처리

expect()unwrap()과 동일한 역할을 합니다. 하지만 expect()의 경우, panic이 발생했을 때 함께 보여줄 메시지를 인자로 전달할 수 있습니다.

use std::fs::File;

fn main() {
    let f = File::open("hello.txt");

    let f: File = f.expect("something wrong, crash");
}

파일이 존재하지 않을 때 아래와 같이 panic이 발생합니다.

thread 'main' panicked at 'something wrong, crash: Os { code: 2, kind: NotFound, message: "No such file or directory" }', src/main.rs:6:21
stack backtrace:
Loading script...

Related Posts

codechachaCopyright ©2019 codechacha