🦀
에러 처리
에러 처리 · 선수: 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 로 스택 트레이스
과제
- 배열 인덱스 초과를 일부러 일으켜 panic 메시지와 스택 트레이스 확인
- assert_eq! 로 작성한 간단한 테스트 함수가 의도대로 panic 을 일으키는지 확인
- Cargo.toml 의 release 프로필을 abort 로 바꾸고 빌드 크기 비교