예외 처리
예외 처리
실패를 무시하지 않고, 잃어버리지 않고, 올바른 곳에서 처리하는 방법을 익힌다. 이 레슨을 끝내면 예외 계층을 설계하고, try-with-resources로 자원을 안전하게 닫고, 실무 안티패턴을 피할 수 있다.
1. 왜 배우는가
프로그램은 반드시 실패한다. 네트워크가 끊기고, 파일이 없고, DB 커넥션이 고갈되고, 사용자가 잘못된 값을 넣는다. 실패 자체는 막을 수 없다. 문제는 실패를 어떻게 다루느냐다.
잘못 다루면 (1) 실패가 조용히 삼켜져 데이터가 깨진 채로 계속 진행되거나, (2) 스택트레이스가 사라져 원인을 영원히 못 찾거나, (3) 열어 둔 파일과 커넥션이 새어 나가 서버가 몇 시간 뒤에 죽는다. 장애 대응 경험이 있는 개발자라면 이 세 가지를 전부 겪어 봤을 것이다.
Java의 예외 메커니즘은 "실패를 타입으로 표현하고, 호출 스택을 따라 전파하며, 원하는 지점에서 잡는다"는 일관된 모델을 제공한다. 이 모델을 정확히 이해하면 finally와 return이 만났을 때 무슨 일이 일어나는지, try-with-resources가 여러 자원을 어떤 순서로 닫는지, 왜 catch (Exception e) {}가 최악의 코드인지를 설명할 수 있다.
실무에서는 특히 사용자 정의 예외 계층 설계가 중요하다. OrderNotFoundException, InsufficientStockException, PaymentDeclinedException을 어떻게 구조화하느냐가 API 에러 응답의 일관성, 로깅의 품질, 트랜잭션 롤백 정책을 결정한다.
Spring의 @ControllerAdvice, @Transactional(rollbackFor=...) 같은 기능은 모두 예외 계층 위에서 동작한다.