← Rust 강의 목록으로
🦀
에러 처리
에러 처리 · 선수: 16강

17. panic! 과 unrecoverable 에러

panic 은 "여기서부터 회복은 불가능하니 즉시 멈춤" 을 알리는 메커니즘입니다. 배열 범위 초과·integer division by zero·unwrap on None 등이 자동으로 panic 을 일으킵니다. 이 강의에서 panic 의 동작 원리, unwind vs abort, 그리고 panic 을 언제 명시적으로 호출해야 하는지 정리합니다.

Rustpanicunwrapassert에러 처리
소요 시간
약 1시간
난이도
📊 중급
선수 조건
🎯 16강
결과물
panic 은 "여기서부터 회복은 불가능하니 즉시 멈춤" 을 알리는 메커니즘입니다. 배열 범위 초과·integer division by zero·unwrap on None 등이 자동으로 panic 을 일으킵니다. 이 강의에서 panic 의 동작 원리, unwind vs abort, 그리고 panic 을 언제 명시적으로 호출해야 하는지 정리합니다.

이 강의에서 배우는 것

  • 1panic 이 일어나는 자동 상황들을 안다
  • 2panic!("msg") 매크로로 명시적 패닉을 일으킨다
  • 3unwind vs abort 의 차이를 안다
  • 4assert!·assert_eq!·debug_assert! 매크로를 사용한다
  • 5Result 처리 vs panic 사용 기준을 안다

소개

panic 은 다른 언어의 unchecked 예외와 비슷하지만 메시지가 명확하고 스택 트레이스가 깔끔합니다. 대부분의 panic 은 **버그를 즉시 드러내는 안전망** 입니다 — 디버그 빌드의 정수 오버플로우, .unwrap() 의 None 등.

핵심 개념

1) panic 이 자동 발생하는 상황

  • 배열·슬라이스 범위 초과 인덱싱
  • 정수 overflow (debug 빌드)
  • 0 으로 정수 나누기
  • Option::unwrap() on None / Result::unwrap() on Err
  • RefCell 빌림 규칙 런타임 위반

2) 명시적 panic

rust
panic!("의도된 종료 — TODO: implement");
assert!(n > 0, "n 은 양수여야 함");
assert_eq!(actual, expected, "값이 다릅니다");

3) unwind vs abort

전략동작기본
unwind스택 풀며 Drop 호출, 자원 해제dev/release 기본
abort즉시 종료, Drop 호출 안 함Cargo.toml panic = "abort" 로 변경 가능 (바이너리 작아짐)

4) 사용 기준 — panic vs Result

  • **panic** — 회복 불가능한 버그·invariant 위반 (계속 실행하면 더 큰 문제)
  • **Result** — 사용자 입력·외부 IO 등 정상적으로 실패할 수 있는 상황

핵심 예제

rust
fn divide(a: i32, b: i32) -> i32 {
    assert!(b != 0, "0 으로 나눌 수 없음");
    a / b
}

fn main() {
    println!("{}", divide(10, 2)); // 5
    println!("{}", divide(10, 0)); // thread 'main' panicked at '0 으로 나눌 수 없음'
}

디버그용 assertion — release 빌드에서는 제거됨:

rust
fn process(v: &[i32]) {
    debug_assert!(!v.is_empty(), "빈 슬라이스 들어옴");
    // ... 실제 처리
}

Cargo.toml 로 panic 전략 변경:

toml
[profile.release]
panic = "abort"     # 바이너리 크기 줄이기, Drop 호출 안 함

스택 트레이스 보기:

bash
RUST_BACKTRACE=1 cargo run
# panic 위치까지의 호출 스택이 자세히 출력

자주 하는 실수

Q. .unwrap() 도 panic 인가요?

A. 네, None/Err 이면 panic. 그래서 사용자 입력·IO 결과엔 .unwrap() 대신 ? 나 .unwrap_or() 가 좋습니다.

Q. panic 을 catch 할 수 있나요?

A. `std::panic::catch_unwind` 가 있지만 일반적인 에러 처리 도구가 아닙니다 — FFI 경계나 스레드 격리 같은 특수 상황용. 일상 코드는 Result 로.

Q. debug_assert! 가 release 에서 사라지는데 신뢰해도 되나요?

A. 개발 단계 검증용입니다. **실제로 영향을 미쳐야 하는 검증은 assert!** 를 쓰세요 — release 에서도 살아있습니다.

정리

  • panic = 회복 불가, 즉시 멈춤
  • 배열 초과·overflow·.unwrap on None 등이 자동 발생
  • 명시적 panic 은 panic!·assert!·assert_eq! 매크로
  • 버그/invariant 위반엔 panic, 정상 실패 가능엔 Result
  • RUST_BACKTRACE=1 로 스택 트레이스

과제

  1. 배열 인덱스 초과를 일부러 일으켜 panic 메시지와 스택 트레이스 확인
  2. assert_eq! 로 작성한 간단한 테스트 함수가 의도대로 panic 을 일으키는지 확인
  3. Cargo.toml 의 release 프로필을 abort 로 바꾸고 빌드 크기 비교
예제 코드 / 강의 자료

전체 강의 자료와 예제 코드는 GitHub에서 자유롭게 받아볼 수 있습니다.

GitHub에서 보기 ↗