자바 표준 예외와 커스텀 예외 장단점

헙크·2023년 4월 7일
1

예외

목록 보기
1/1
post-thumbnail

1. 표준 예외란?

자바에서 제공하는 예외 클래스다.

특징

  1. 자바 개발자라면 누구나 사용할 수 있는 표준이기 때문에, 다른 개발자들이 이를 보고 어떤 예외 상황인지 이해하기 쉽다.
  2. 기본적으로 예외 발생시 생성자에 에러 메시지를 넣을 수 있기 때문에, 어떤 상황에 에러가 발생했는지 추후에 exception.getMessage()를 통해 간단하게 파악할 수 있다.

단점

  1. 혹여나 자신의 상황에 정확히 맞지 않는 예외가 존재하지 않을 수 있다.

  2. 특정 예외 상황만을 걸러내기 어렵다.

    → 상위에서 한 번만 catch를 한다고 가정하면, 수많은 IllegalArgumentException 중 “이름 입력”에서 발생한 예외만을 골라내 처리하기 어렵다.

  3. 예외 클래스의 생성자로 String만 넘겨줄 수 있다. 다른 객체를 생성자의 매개변수에 넘겨줄 수 없어 구체적인 예외 상황을 알기 어렵다.

2. 커스텀 예외란?

자바에서 제공하는 예외를 상속해 직접 만든 예외 클래스다.

특징

  1. 클래스의 이름만으로 의미 전달이 가능하다.

  2. 커스텀 예외 클래스 내부에서 특별한 후처리가 가능하다.

    • 가령 공통된 예외 메시지 포맷으로 출력하게 할 수 있다.
    • 인자로 넘겨 받은 객체를 필드에 저장해서, 추후에 사용할 수 있다. 혹은 로그를 남길 수도 있다.
    public class CustomLadderHeightException extends NumberFormatException {
    		private static final String message = "숫자만 입력 가능합니다.";
    
    		public CustomLadderHeightException(String string) {
    				super(message + "Invalid height : " + string);
    				// logger.error("!!");
    		}
    }
  3. 예외 발생 상황을 개발자가 정확히 알 수 있다.

    → 커스텀 예외이기 때문에, catch 문의 타입으로 사용한다면 구체적인 예외 상황을 정확하게 잡아 처리할 수 있다.

  4. 표준 예외가 문자열만을 저장할 수 있는 것과는 달리, 커스텀 예외에는 필요한 객체들을 저장하여 사용할 수 있다. 이를 통해 조금 더 상세한 예외 정보를 제공할 수 있다.

    public class IllegalIndexException extends IndexOutOfBoundsException {
        private static final String message = "범위를 벗어났습니다.";
    
        public IllegalIndexException(List<?> target, int index) {
            super(message + " size: "  + target.size() + " index: " + index);
        }
    }
  5. 예외 생성 비용을 줄일 수 있다.

    자바는 예외가 발생하면 기본적으로 stack trace를 찍어주기 위한 정보를 생성한다. JVM은 예외 발생 시 call stack에 있는 메서드 리스트를 저장한다. 이를 통해 예외가 발생한 정확한 위치를 파악할 수 있다. 하지만 메서드 리스트를 저장하고 콘솔에 출력하는 데에는 많은 생성 비용이 든다.

    예외가 발생하면 비싼 비용을 들여서 stack trace를 생성하는데, 우리가 catch문으로 예외를 잡아 정상 흐름으로 바꾼다면 stack trace를 사용하지 않음에도 불구하고 생성하는 것이고, 이는 성능에 영향을 줄 수 있다.

    따라서 Throwable의 메서드인 fillInStackTrace를 오버라이딩해 간단하게 출력하거나 출력 자체를 하지 않음으로써 콘솔에 출력하는 생성비용을 줄일 수 있다.

    public class IllegalIndexException extends IndexOutOfBoundsException {
    		...
    
    		@Override
    		public synchronized Throwable fillInStackTrace() {
    		    return this;
    		}
    }

    혹은 다음과 같이 Throwable생성자를 사용하면 stack trace를 억제할 수 있다.

    // Throwable에서 제공하는 생성자 중 하나
    Throwable(
    		String message, 
    		Throwable cause, 
    		boolean enableSuppression,
    		boolean writableStackTrace
    )

    다음과 같이 정의하여 예외를 억제할 수도, 억제하지 않을 수도 있다.

    private static class CustomCountInputException extends RuntimeException {
        private static final String message = "숫자만 입력 가능합니다.";
    
        private boolean suppressStacktrace = false;
    
        public CustomCountInputException(String message, boolean suppressStacktrace) {
            super(message, null, suppressStacktrace, !suppressStacktrace);
        }
    }
    
    main {
    		void exceptionHere() {
    				// throw new IllegalIndexException("NotSuppresed", false);
    				throw new IllegalIndexException("suppresed", true);
    		}
    }

단점

  1. 커스텀 예외를 많이 생성하면, 관리해야할 클래스가 많아진다.
  2. 다른 사람이 봤을 때, 이름만으로 이해가 가지 않는다면 구현 클래스를 직접 봐야하는 수고로움이 생긴다.

참고

custom exception을 언제 써야 할까?

Java Exception 생성 비용은 비싸다. : NHN Cloud Meetup

Which part of throwing an Exception is expensive?

[Solved] Exception without stack trace in Java

고려해보면 좋을 것들

  1. 커스텀 예외 클래스에 도메인 정보를 넘겨줘도 될까?
  2. 예외 생성 비용이 항상 많이 들까?

0개의 댓글