RUST · 심층 가이드
Rust 에러 처리 완전 정리
Result 기반 처리, 사용자 정의 오류 타입, 입력 검증, 안전한 파싱과 나눗셈, fallback까지 Rust 오류 처리 15가지를 한 편에 모았습니다.
Rust에는 예외가 없습니다. 실패할 수 있는 함수는 Result를 돌려주고, 호출한 쪽이 그것을 반드시 마주 봐야 합니다. try/catch로 감싸 두면 어디선가 알아서 잡히던 흐름이 사라지는 대신, 어떤 함수가 실패할 수 있는지가 시그니처에 그대로 드러납니다. 오류 처리를 나중으로 미룰 수 없게 만드는 설계라고 보면 됩니다.
Result 반환과 안전한 숫자 파싱을 먼저 보면 ? 연산자가 왜 필요한지 자연스럽게 이해됩니다. 이어서 사용자 정의 오류와 도메인 오류 표현을 읽으면 서로 다른 오류 타입을 하나로 모으는 방법이 보이고, 다단계 검증과 fallback 값 사용에서 실패를 흘려보낼지 대체할지 판단하는 기준이 잡힙니다. finally 정리 항목은 Rust에 finally가 없는 대신 Drop이 그 역할을 한다는 점을 보여 줍니다.
덜 알려진 함정은 정수 오버플로입니다. 디버그 빌드에서는 오버플로가 패닉으로 잡히지만 릴리스 빌드에서는 기본 설정상 조용히 감싸 돌아갑니다. 개발 중에는 멀쩡하다가 배포본에서만 값이 이상해지는 전형적인 경로입니다. 경계가 의심스러운 산술에는 checked_add처럼 결과를 Option으로 돌려주는 메서드나 saturating_ 계열을 쓰는 편이 안전합니다.
01try catch 기본
Rust에서 try catch 기본 개념을 코드로 빠르게 확인하는 에러 처리 예제입니다.
Rust code
// try catch 기본
fn require_positive(value: i32) -> Result<i32, String> { if value <= 0 { Err("positive only".to_string()) } else { Ok(value) } }
fn main() {
println!("{:?}", require_positive(1));
}실패를 잡는 것에서 끝내지 말고, 기록하고 복구하는 흐름까지 같이 읽는 것이 중요합니다.
에러를 잡기만 하고 아무 처리도 하지 않으면 문제는 숨어 있고 복구는 더 어려워집니다.
02사용자 정의 오류
Rust에서 사용자 정의 오류 개념을 코드로 빠르게 확인하는 에러 처리 예제입니다.
Rust code
// 사용자 정의 오류
fn main() {
let parsed = "x".parse::<i32>();
println!("{:?}", parsed.err());
}실패를 잡는 것에서 끝내지 말고, 기록하고 복구하는 흐름까지 같이 읽는 것이 중요합니다.
에러를 잡기만 하고 아무 처리도 하지 않으면 문제는 숨어 있고 복구는 더 어려워집니다.
03입력 검증
Rust에서 입력 검증 개념을 코드로 빠르게 확인하는 에러 처리 예제입니다.
Rust code
// 입력 검증
fn require_positive(value: i32) -> Result<i32, String> { if value <= 0 { Err("positive only".to_string()) } else { Ok(value) } }
fn main() {
println!("{:?}", require_positive(3));
}실패를 잡는 것에서 끝내지 말고, 기록하고 복구하는 흐름까지 같이 읽는 것이 중요합니다.
에러를 잡기만 하고 아무 처리도 하지 않으면 문제는 숨어 있고 복구는 더 어려워집니다.
04안전한 숫자 파싱
Rust에서 안전한 숫자 파싱 개념을 코드로 빠르게 확인하는 에러 처리 예제입니다.
Rust code
// 안전한 숫자 파싱
fn main() {
let parsed = "x".parse::<i32>();
println!("{:?}", parsed.err());
}실패를 잡는 것에서 끝내지 말고, 기록하고 복구하는 흐름까지 같이 읽는 것이 중요합니다.
에러를 잡기만 하고 아무 처리도 하지 않으면 문제는 숨어 있고 복구는 더 어려워집니다.
05안전한 나눗셈
Rust에서 안전한 나눗셈 개념을 코드로 빠르게 확인하는 에러 처리 예제입니다.
Rust code
// 안전한 나눗셈
fn require_positive(value: i32) -> Result<i32, String> { if value <= 0 { Err("positive only".to_string()) } else { Ok(value) } }
fn main() {
println!("{:?}", require_positive(5));
}실패를 잡는 것에서 끝내지 말고, 기록하고 복구하는 흐름까지 같이 읽는 것이 중요합니다.
에러를 잡기만 하고 아무 처리도 하지 않으면 문제는 숨어 있고 복구는 더 어려워집니다.
06finally 정리
Rust에서 finally 정리 개념을 코드로 빠르게 확인하는 에러 처리 예제입니다.
Rust code
// finally 정리
fn main() {
let parsed = "x".parse::<i32>();
println!("{:?}", parsed.err());
}실패를 잡는 것에서 끝내지 말고, 기록하고 복구하는 흐름까지 같이 읽는 것이 중요합니다.
에러를 잡기만 하고 아무 처리도 하지 않으면 문제는 숨어 있고 복구는 더 어려워집니다.
07오류 다시 던지기
Rust에서 오류 다시 던지기 개념을 코드로 빠르게 확인하는 에러 처리 예제입니다.
Rust code
// 오류 다시 던지기
fn require_positive(value: i32) -> Result<i32, String> { if value <= 0 { Err("positive only".to_string()) } else { Ok(value) } }
fn main() {
println!("{:?}", require_positive(7));
}실패를 잡는 것에서 끝내지 말고, 기록하고 복구하는 흐름까지 같이 읽는 것이 중요합니다.
에러를 잡기만 하고 아무 처리도 하지 않으면 문제는 숨어 있고 복구는 더 어려워집니다.
08도메인 오류 표현
Rust에서 도메인 오류 표현 개념을 코드로 빠르게 확인하는 에러 처리 예제입니다.
Rust code
// 도메인 오류 표현
fn main() {
let parsed = "x".parse::<i32>();
println!("{:?}", parsed.err());
}실패를 잡는 것에서 끝내지 말고, 기록하고 복구하는 흐름까지 같이 읽는 것이 중요합니다.
에러를 잡기만 하고 아무 처리도 하지 않으면 문제는 숨어 있고 복구는 더 어려워집니다.
09fallback 값 사용
Rust에서 fallback 값 사용 개념을 코드로 빠르게 확인하는 에러 처리 예제입니다.
Rust code
// fallback 값 사용
fn require_positive(value: i32) -> Result<i32, String> { if value <= 0 { Err("positive only".to_string()) } else { Ok(value) } }
fn main() {
println!("{:?}", require_positive(9));
}실패를 잡는 것에서 끝내지 말고, 기록하고 복구하는 흐름까지 같이 읽는 것이 중요합니다.
에러를 잡기만 하고 아무 처리도 하지 않으면 문제는 숨어 있고 복구는 더 어려워집니다.
10assertion
Rust에서 assertion 개념을 코드로 빠르게 확인하는 에러 처리 예제입니다.
Rust code
// assertion
fn main() {
let parsed = "x".parse::<i32>();
println!("{:?}", parsed.err());
}실패를 잡는 것에서 끝내지 말고, 기록하고 복구하는 흐름까지 같이 읽는 것이 중요합니다.
에러를 잡기만 하고 아무 처리도 하지 않으면 문제는 숨어 있고 복구는 더 어려워집니다.
11Result 반환
Rust에서 Result 반환 개념을 코드로 빠르게 확인하는 에러 처리 예제입니다.
Rust code
// Result 반환
fn require_positive(value: i32) -> Result<i32, String> { if value <= 0 { Err("positive only".to_string()) } else { Ok(value) } }
fn main() {
println!("{:?}", require_positive(11));
}실패를 잡는 것에서 끝내지 말고, 기록하고 복구하는 흐름까지 같이 읽는 것이 중요합니다.
에러를 잡기만 하고 아무 처리도 하지 않으면 문제는 숨어 있고 복구는 더 어려워집니다.
12다단계 검증
Rust에서 다단계 검증 개념을 코드로 빠르게 확인하는 에러 처리 예제입니다.
Rust code
// 다단계 검증
fn main() {
let parsed = "x".parse::<i32>();
println!("{:?}", parsed.err());
}실패를 잡는 것에서 끝내지 말고, 기록하고 복구하는 흐름까지 같이 읽는 것이 중요합니다.
에러를 잡기만 하고 아무 처리도 하지 않으면 문제는 숨어 있고 복구는 더 어려워집니다.
13로깅 래퍼
Rust에서 로깅 래퍼 개념을 코드로 빠르게 확인하는 에러 처리 예제입니다.
Rust code
// 로깅 래퍼
fn require_positive(value: i32) -> Result<i32, String> { if value <= 0 { Err("positive only".to_string()) } else { Ok(value) } }
fn main() {
println!("{:?}", require_positive(13));
}실패를 잡는 것에서 끝내지 말고, 기록하고 복구하는 흐름까지 같이 읽는 것이 중요합니다.
에러를 잡기만 하고 아무 처리도 하지 않으면 문제는 숨어 있고 복구는 더 어려워집니다.
14recover 흐름
Rust에서 recover 흐름 개념을 코드로 빠르게 확인하는 에러 처리 예제입니다.
Rust code
// recover 흐름
fn main() {
let parsed = "x".parse::<i32>();
println!("{:?}", parsed.err());
}실패를 잡는 것에서 끝내지 말고, 기록하고 복구하는 흐름까지 같이 읽는 것이 중요합니다.
에러를 잡기만 하고 아무 처리도 하지 않으면 문제는 숨어 있고 복구는 더 어려워집니다.
15입력 가드
Rust에서 입력 가드 개념을 코드로 빠르게 확인하는 에러 처리 예제입니다.
Rust code
// 입력 가드
fn require_positive(value: i32) -> Result<i32, String> { if value <= 0 { Err("positive only".to_string()) } else { Ok(value) } }
fn main() {
println!("{:?}", require_positive(15));
}실패를 잡는 것에서 끝내지 말고, 기록하고 복구하는 흐름까지 같이 읽는 것이 중요합니다.
에러를 잡기만 하고 아무 처리도 하지 않으면 문제는 숨어 있고 복구는 더 어려워집니다.
정리하며
- 예외 대신 Result를 쓰므로 실패 가능성이 시그니처에 드러납니다
- ? 연산자는 오류 타입 변환이 정의돼 있어야 동작합니다
- finally 대신 Drop이 정리 책임을 지므로 자원 해제는 타입에 맡깁니다
- 정수 오버플로는 릴리스 빌드에서 조용히 감싸므로 checked 계열을 씁니다
더 깊이 들어가고 싶다면 Rust 학습 라이브러리에서 다른 주제 가이드를 이어서 보거나, 언어 비교에서 같은 개념이 다른 언어에서 어떻게 표현되는지 확인해 보세요.