# 에러 처리 - unwrap, expect 활용

Rust에서 Result나 Option 타입을 활용한 에러 처리는 안정적이고 명시적인 방식으로 이루어진다. 하지만 모든 상황에서 명시적인 매칭(match)을 사용하거나 ? 연산자를 사용하는 것이 아니라, 때에 따라 간단한 처리가 필요할 수도 있다. 이럴 때 많이 쓰이는 메서드가 unwrap과 expect이다. 두 메서드 모두 내부적으로 에러(또는 None)를 만나면 즉시 프로그램이 패닉(panic)을 일으키지만, 그 과정과 메시지 출력 측면에서 차이가 있다. 여기서는 unwrap과 expect가 어떻게 동작하는지, 어떤 차이가 있는지, 그리고 실제 코드에서 어떤 주의점을 가지고 사용해야 하는지에 대해 구체적으로 살펴본다.

Rust의 Option 타입이나 Result 타입은 안전한 에러 처리 메커니즘을 제공한다. 그런데 가끔씩 이 값이 반드시 Some이거나 Ok라고 가정하고 코드를 단순화하고 싶을 때 unwrap을 쓸 수 있다. 예를 들어 Option 타입을 반환하는 함수가 있을 때, 로직상 None이 나올 수 없는 확실한 경우라면 unwrap으로 안전하게 String 값을 꺼낼 수 있다. 하지만 이 가정이 틀렸다면(실제로 None이 반환되었다면) 그 즉시 패닉이 발생하고, 프로그램은 종료된다. Result 타입에 대해서도 마찬가지로 unwrap은 내부의 Ok 값을 꺼내고, Err인 경우에는 패닉을 일으킨다.

예시 코드를 통해 확인해보자.

```
fn main() {
    let maybe_number = Some(10);
    let number = maybe_number.unwrap();
    println!("값: {}", number);

    let result: Result<&str, &str> = Ok("정상 처리");
    let msg = result.unwrap();
    println!("메시지: {}", msg);
}
```

위와 같이 동작하는 경우에는 아무런 문제가 없다. Option에는 Some(10)이 들어 있고, Result에는 Ok("정상 처리")가 들어 있으므로 unwrap은 정상적으로 값을 꺼낸다. 그러나 None이나 Err가 들어 있었다면 프로그램은 패닉을 일으키고 즉시 종료될 것이다. 예를 들어 다음처럼 Err가 있는 Result를 unwrap하면 어떻게 되는지 살펴보자.

```
fn main() {
    let result: Result<&str, &str> = Err("에러 발생");
    let msg = result.unwrap();
    println!("메시지: {}", msg); // 여기에 도달하지 못하고 패닉 발생
}
```

실행하면 “called `Result::unwrap()` on an `Err` value: "에러 발생"”라는 메시지가 뜨면서 프로그램이 종료된다. 이처럼 unwrap은 에러 상황에 대한 구체적인 메시지를 설정할 수 없고, 단지 기본적인 패닉 메시지에 Err의 내용을 그대로 출력한다. 이런 특징 때문에 디버깅을 할 때는 에러 원인을 좀 더 구체적으로 남기고 싶은 상황이 생길 수 있는데, 그럴 때 사용되는 메서드가 expect이다.

expect는 unwrap과 동일하게 내부적으로 Ok면 값을 반환하고, Err면 패닉을 일으키지만, 사용자가 직접 작성한 커스텀 메시지를 남긴다는 점이 다르다. 따라서 가독성 높은 에러 로그를 남기고 싶을 때 expect를 사용하면 유용하다. 예제 코드를 보자.

```
fn main() {
    let result: Result<&str, &str> = Err("네트워크 오류");
    let msg = result.expect("데이터를 정상적으로 받아야 한다.");
    println!("메시지: {}", msg);
}
```

이 코드를 실행하면 패닉이 발생하면서 “데이터를 정상적으로 받아야 한다.: "네트워크 오류"”라는 메시지를 출력한다. 이렇게 커스텀 메시지를 삽입하면 어떤 상황에서 에러가 발생했는지 더욱 쉽게 파악할 수 있다. 큰 규모의 프로젝트에서 디버깅을 해야 할 때는 이 메시지가 문제 해결 시간을 단축시키는 데 도움을 준다.

unwrap과 expect 모두 “해당 값이 반드시 존재한다고 가정”하고 패닉을 일으키는 메서드이므로, 실제 프로덕션 코드에서는 신중하게 사용해야 한다. 테스트 코드나 예시 코드, 혹은 정말로 해당 값이 없으면 논리적으로 의미가 없는 상황에서만 사용을 권장한다. 가령 임시 스크립트나 프로토타이핑을 할 때는 unwrap과 expect가 매우 유용하다. 하지만 실제 애플리케이션 로직에서 모든 오류 상황을 패닉으로 처리하면 프로그램이 갑작스럽게 종료되어 사용자 경험이 훼손될 수 있다. 따라서 대다수의 경우에는 Result나 Option에 대해 match 문을 쓰거나 ? 연산자를 통해 정상적인 에러 처리를 하는 것이 더욱 바람직하다.

만약 실패 가능성이 있는 로직에서 “반드시 에러를 처리해야 한다”는 요구사항이 있다면, unwrap이나 expect 대신 match 문으로 세분화된 로직을 작성해야 한다. 예를 들어 파일 I/O나 네트워크 호출은 성공과 실패 경우가 다양하며, 단순 패닉이 아닌 에러 복구나 사용자 안내가 필요하다. 이런 상황에서 unwrap을 남발하면 디버깅과 유지보수를 어렵게 만들 뿐 아니라 사용자에게도 좋지 않은 경험을 제공한다.

정리하자면, unwrap과 expect는 빠르고 간단하게 에러를 처리할 수 있도록 해주지만, 결국에는 패닉을 일으킨다는 사실을 인지해야 한다. 개발 속도를 높이거나 테스트를 빠르게 작성할 때는 편리하지만, 프로덕션 수준의 코드를 작성할 때는 그 사용 범위를 제한하는 것이 좋다. 특히 expect를 사용하면 문제가 발생했을 때 좀 더 구체적인 정보를 제공할 수 있다는 장점이 있으므로, “반드시 여기서는 Err가 나와서는 안 된다”는 가정이 명확하다면 unwrap보다 expect를 사용하는 편이 낫다. 그러나 최종적으로는 대부분의 에러 상황을 별도의 로직으로 처리하거나 적절한 에러 타입을 반환하여 안정성을 보장하는 것을 권장한다.
