프로그램을 작성하면서 예외 처리는 항상 까다롭고 귀찮다.
하지만 그만큼 중요하다.
나도 서버를 만들 때 마다 어떤 방식으로 예외처리를 해야 정확하고 깔끔할까 항상 고민한다.
주의할 점들을 알아보자.
예외는 진짜 예외 상황에만 사용하자
1. 예외는 예외 상황에 쓸 용도로 설계되었으므로 JVM 구현자가 최적화를 하지 않았을 수 있다.
2. try-catch 블록 안에 넣으면 JVM이 적용할 수 있는 최적화가 제한된다.
3. 배열을 순회하는 관용구는 중복 검사를 수행하지 않게 최적화한다.
예외는 예외상황에서만 사용하고, 일상적인 제어 흐름용으로 사용하지 마라.
잘 설계된 API라면 클라이언트가 정상적인 제어 흐름에서 예외를 사용할 일이 없게 해야한다.
필요 없는 검사 예외 사용은 피하라
검사 예외를 잘 사용하면 발생한 문제를 프로그래머가 처리하여 안전성을 높여준다.
하지만 과하게 쓰면 오히려 불편하게 된다.
어떤 메서드가 검사 예외를 던질 수 있게 선언되었다면, 이를 호출하는 쪽에서 catch 블록을 두거나 throw 해야한다.
이는 클라이언트에게 부담을 준다. 또한 예외를 던지는 메서드는 스트림 안에서 직접 사용할 수 없기 때문에 자바 8부터 부담이 더 커졌다.
검사 예외를 회피하는 가장 쉬운 방법은 적절한 결과 타입을 담은 옵셔널을 반환하거나 메서드를 쪼개는 것이다.
try {
obj.action(args);
} catch (TheCheckedException e) {
... // 예외 상황에 대처한다.
}
if (obj.actionPermitted(args)) {
obj.action(args);
} else {
...
}
표준 예외를 사용하라
많이 쓰이는 예외
- IllegalArgumentException : 호출자가 인수로 부적절한 값을 넘길 때 던지는 예외
- IllegalStateException : 대상 객체의 상태가 호출된 메서드를 수행하기에 적절하지 않을 때
- NullPointerException : null 값을 허용하지 않는 메서드에 null을 건낼 때
- IndexOutOfBoundsException : 시퀀스의 허용 범위를 넘을 때
- ConcurrentModificationException : 단일 스레드에서 사용하려고 설계한 객체를 여러 스레드가 동시에 수정할 때
- UnsupportedOperationException : 클라이언트가 요청한 동작을 대상 객체가 지원하지 않을 때
Exception, RuntimeException, Throwable, Error 와 같은 상위 클래스는 직접 재사용하지 말자.
다른 예외의 상위 클래스 이기 때문에 안정적으로 테스트 할 수 없다.
커스텀 예외 사용
회사에서 서버를 개발 할 땐 항상 커스텀 예외를 사용했다.
Exception을 상속받아 메서드를 재정의해서 좀 더 예외를 세부적으로 표시 할 수 있도록 message를 enum으로 정의해서 사용했다.
또한 서버에서 사용되는 라이브러리를 개발 할 때도, 커스텀 예외는 예외처리를 세심히 해준다면
문제점을 쉽게 찾아내고, 디버깅 할 수 있도록 해주었다.
커스텀 예외에 대해 알아보자
1. 예외 이름 자체가 정보를 전달할 수 있다
NoSuchElementException 보다는 PostNotFoundException 이 더 정확하다.
2. 더 상세하게 예외 정보를 제공할 수 있다
public class IllegalIndexException extends IndexOutOfBoundsException {
private static final String message = "범위를 벗어났습니다.";
public IllegalIndexException(List<?> target, int index) {
super(message + " size: " + target.size() + " index: " + index);
}
}
3. 예외의 응집도 향상
예외에 필요한 메시지, 전달할 정보의 데이터 등등을 한 곳에서 관리가 가능하다.
4. 정확하게 위치 파악이 가능하다
커스텀화를 시켰기 때문에 어떤 상황에서 발생했는지 특정할 수 있다.
5. 예외 생성 비용을 절감한다.
stackTrace를 생략할 수 있는 상황에서는 재정의를 통해 생성 비용을 줄일 수 있다.
또한, 예외를 재정의하면서 실패와 관련된 정보를 예외에 추가해 줄 수 있다.
디버깅을 위해 소스를 따로 수정해야하는 수고를 줄여줄 수 있고 문제점을 파악하는 시간을 단축시켜줄 수 있다.
메서드가 던지는 모든 예외를 문서화하자
예외는 매우 중요한 정보이다.
검사 예외는 항상 따로따로 선언하고, 각 예외 발생 상황을 자바독의 @throws 태그로 정확히 문서화하자.
참고 : https://tecoble.techcourse.co.kr/post/2020-08-17-custom-exception/
'JAVA > 이펙티브 자바' 카테고리의 다른 글
Java. 오버로딩, 오버라이딩은 신중히 사용하자 ( 다중 정의 ) (0) | 2024.03.06 |
---|---|
Java. 명명규칙은 통용되는 것으로 지키자. (1) | 2024.03.06 |
Java. 불변 사용 시 적시에 방어적 복사본을 만들자 (0) | 2024.03.06 |
Java. 스트림이란? (2) | 2024.01.02 |
43. 람다보다는 메서드 참조를 사용하라 ( 람다 표현식과 메서드 참조 ) (0) | 2023.08.02 |