예외와 예외의 본질
예외는 정말 예상치 못한 오류를 처리하는데 사용되어야하는지, 아니면 일반적인 흐름의 일부로도 허용되는지를 고민하게 된다.
예외의 본질은 정상적인 흐름에서 벗어난 비정상적인 상황을 처리하기 위한 구조이다.
예상할 수 없는 상황은 네트워크 오류, 파일 손실, 메모리 부족이지 않을까?
하지만 아래 두 시나리오를 보면 생각이 달라지지 않을까?
시나리오1
우리는 AI 에게 어떤 일을 시키려고 합니다.
사람 얼굴을 입력시켜서, 닮은꼴인 연예인을 찾아내는 일을 시키려고 합니다.
하지만, 어떤 사람이 강아지나, 고양이 사진을 넣었을 때 이를 예외라고 처리하여, 실행을 중단해야 할까?
우린 더 흥미로워집니다. 이 강아지 사진과 비슷한 연예인 사진이 누굴까?
당신은 사용자로써, 이 앱이 중단되지 않고 계속 실행되길 바랄겁니다.
시나리오2
우리는 자율주행 자동차를 개발하고 있습니다. 목적지를 입력하면, 최단거리를 검색하여 이동하게끔 만들었습니다.
하지만 최단거리에 있는 한 도로가 공사중이라 막혀있습니다.
하지만 자율주행 자동차는 이 길이 정상적인 방향으로 생각하여 진입한다면, 이는 예외입니다.
이 경우 예외가 발생하면 멈추는게 좋은 방향일 겁니다.
결론
이 두 시나리오는 비기술적인 요구 사항입니다.
그래서 다시 본론으로 돌아와서. 예외를 기대한다면, 그게 정말 예외일까요?
이 질문에 대한 답은 위 두 시나리오처럼 개발자가 코드 설계 시 비정상적인 흐름과 정상적인 흐름의 경계를 명확히 구분해야 함을 상기시키죠.
"예외를 기대하고 있다면, 그것은 더 이상 예외가 아니다"
예상 가능한 상황을 예외로 처리하는 습관을 피하고, 상태 기반의 로직 처리를 우선 고려해야 하죠.
예시는 다음과 같습니다.
1. 네트워크 요청
try {
const response = await fetchData()
} catch (error) {
console.error('네트워크 오류 발생:', error)
}
네트워크 요청은 현실적으로 예상 가능한 일입니다.
1-1. 변환된 코드
const response = await fetchData()
if (!response.ok) {
console.error('네트워크 오류 발생:', response.statusText)
}
2. 사용자 입력 검증
try {
const value = JSON.parse(userInput)
} catch (error) {
console.error('잘못된 입력입니다.')
}
입력이 잘못될 가능성을 이미 예상하고 있습니다.
2-1 변환된 코드
if (isValidJSON(userInput)) {
const value = JSON.parse(userInput)
} else {
console.error('잘못된 입력입니다.')
}
종종 중요한 것은 단순히 무엇이 읽기 쉬운가이다