러스트의 신뢰성에 대한 약속은 에러 처리에도 확장되어 있습니다.
에러는 소프트웨어에서 피할 수 없는 현실이며, 따라서 러스트는 무언가 잘못되었을 경우에 대한 처리를 위한 몇 가지 기능을 갖추고 있습니다.
러스트는 에러를 두 가지 범주로 묶습니다:
- 복구 가능한(recoverable) 에러
- 복구 가능한 에러는 사용자에게 문제를 보고하고 연산을 재시도하는 것이 보통 합리적인 경우인데, 이를테면 파일을 찾지 못하는 에러가 그렇습니다.
- 복구 불가능한(unrecoverable) 에러
- 복구 불가능한 에러는 언제나 버그의 증상이 나타나는데, 예를 들면 배열의 끝을 넘어선 위치의 값에 접근하려고 시도하는 경우가 그렇습니다.
대부분의 언어들은 이 두 종류의 에러를 분간하지 않으며 예외 처리(exception)
와 같은 메카니즘을 이용하여 같은 방식으로 둘 다 처리합니다.
러스트는 예외 처리 기능이 없습니다.
- 복구 가능한 에러를 위한
Result<T, E>
값과 - 복구 불가능한 에러가 발생했을 때 실행을 멈추는
panic!
매크로를 가지고 있습니다.
이번 장에서는 panic!
을 호출하는 것을 먼저 다룬 뒤, Result<T, E>
값을 반환하는 것에 대해 이야기 하겠습니다.
추가로, 에러로부터 복구을 시도할지 아니면 실행을 멈출지를 결정할 때 고려할 것에 대해 탐구해 보겠습니다.
panic!
과 함께하는 복구 불가능한 에러
- 러스트는
panic!
매크로를 가지고 있습니다. - 이 매크로가 실행되면, 여러분의 프로그램은 실패 메세지를 출력하고, 스택을 되감고 청소하고, 그 후 종료됩니다.
- 이런 일이 발생하는 가장 흔한 상황은 어떤 종류의 버그가 발견되었고 프로그래머가 이 에러를 어떻게 처리할지가 명확하지 않을 때 입니다.
panic!
에 응하여 스택을 되감거나 그만두기
기본적으로,
panic!
이 발생하면, 프로그램은 되감기(unwinding) 를 시작하는데, 이는 러스트가 패닉을 마주친 각 함수로부터 스택을 거꾸로 훑어가면서 데이터를 제거한다는 뜻이지만, 이 훑어가기 및 제거는 일이 많습니다.다른 대안으로는 즉시 그만두기(abort) 가 있는데, 이는 데이터 제거 없이 프로그램을 끝내는 것입니다. 프로그램이 사용하고 있던 메모리는 운영체제에 의해 청소될 필요가 있을 것입니다. 여러분의 프로젝트 내에서 결과 바이너리가 가능한 작아지기를 원한다면, 여러분의 Cargo.toml 내에서 적합한
[profile]
섹션에panic = 'abort'
를 추가함으로써 되감기를 그만두기로 바꿀 수 있습니다.예를 들면, 여러분이 릴리즈 모드 내에서는 패닉 상에서 그만두기를 쓰고 싶다면, 다음을 추가하세요:
[profile.release] panic = 'abort'
단순한 프로그램 내에서 panic!
호출을 시도해 봅시다:
panic!("crash and burn");
panic!
의 호출이 마지막 세 줄의 에러 메세지를 야기합니다.- 위 예제의 경우, 가리키고 있는 줄은 우리 코드 부분이고, 해당 줄로 가면
panic!
매크로 호출을 보게 됩니다. - 그 외의 경우들에서는,
panic!
호출이 우리가 호출한 코드 내에 있을 수도 있습니다. - 에러 메세지에 의해 보고되는 파일 이름과 라인 번호는
panic!
매크로가 호출된 다른 누군가의 코드일 것이며, 궁극적으로panic!
을 이끌어낸 것이 우리 코드 라인이 아닐 것입니다. - 문제를 일으킨 코드 부분을 발견하기 위해서
panic!
호출이 발생된 함수에 대한 백트레이스(backtrace)를 사용할 수 있습니다. - 백트레이스가 무엇인가에 대해서는 뒤에 더 자세히 다를 것입니다.