ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Java Exception Handling (e.printStackTrace())
    JAVA/자바공부 2023. 10. 20. 01:20

    업무 중 코파일럿에 의해 Exception catch문과 e.printStackTrace()가 자동으로 생성되는 일이 있었다.
    팀장님의 이거 쓰면 안되요! 라는 리뷰가 달렸는데, 왜 안될까?


    Exception이란 무엇일까? 

    e.printStackTrace의 정체는 무얼까?

    google image

     

    Exception 정의

    • 프로그램 실행중 정상적인 흐름을 방해하는 이벤트
    • 일반적으로 Exception이 발생하면 현재 코드 블럭이나 메서드의 동작이 멈춘다.

    Exception의 역사

    • 약 40년 전 최초 프로그래밍 언어에는 Exception이라는 개념이 없었다.
    • C 언어에서는 비정상적인 종료를 알리고자 -1 또는 null을 반환하는 방식으로 동작했다.
      • 함수를 호출하고 실수로 -1, null 값 확인을 놓치는 실수들이 속출
    • 1985년, C++ 언어가 등장해 C의 문제를 해결하기 위해 Exception이라는 개념을 사용했다.
      • 비정상적인 종료가 발생하면 어디서 프로그램이 종료했는지 call stack을 쌓았다.
      • 그러나, 어떤 함수가 정확히 어떤 예외를 던지는지 알아 볼 수 없는 문제가 있었다.
    • 1995년, Java 등장 비정상적인 종료를 잡아내기 위해, 특정 함수에서 어떤 Exception이 발생하는지 Checked Exception 개념을 도입
      • recoverable한 예외에 한해서 Checked Exception을 던질 수 있게 되었다.

     

    Java의 Exception 계층

    java.lang.Throwable; // 예외 최상위 클래스
    java.lang.Error; // JVM의 low-level exceptiom 데표 (ex. OutOfMemoryError, StackOverflowError)
    java.lang.Exception; // app 내부의 예외 event (ex. RuntimeException, IOException)
    
    • 모든 예외는 최상위 부모 Throwable을 상속한다. (아래 3개의 기본 메서드를 사용할 수 있다.)
      • String getMessage(); returns the detailed string message of this exception object;
      • Throwable getCause(); returns the cause of this exception or null if the cause is nonexistent or unknown;
      • printStackTrace(); prints the stack trace on the standard error stream.

    Exception 계층 구조 - jetbrains 제공

    Checked Exception vs Unchecked Exception 

    • 컴파일러의 시선에서 2가지로 나뉜다.
      • Checked Exception
        • 컴파일러가 checked 가능한 에러 java.lang.Exception; (RuntimeException 자식 클래스를 제외한 모든 Exception)
        • Checked Exception에는 메서드() 뒤에 throws 선언과 try-catch를 의무적으로 사용해야한다. (안쓰면 컴파일 에러)
    class Config {
       public static Date getLastPromoDate() throws ParseException, IOException {
         Properties props = new Properties();
         try (Reader reader = new FileReader("config.properties")) {
            props.load(reader);
         }
         SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
         return format.parse(props.getProperty("last.promo.date"));
       }
    }
    • Unchecked Exception
      • 프로그램 실행중 발생하는 컴파일러가 check 불가한 에러이다.
      • RuntimeException과 그 자손 예외 클래스

     

    RuntimeException을 상속 커스텀해서 사용하자

    • 현대 Web에서는 UncheckedException 사용이 권장 된다. 
    • checked exception은 현대 개발 환경에 맞지 않다. 분산 환경에서 외부 시스템, 수 많은 라이브러리에서 checked exception을 사용한다고 상상해보자. checked exception은 메서드에 throws를 선언하고 try-catch가 필수적으로 필요하다. 즉 구현 계층에 외부 의존성이 생긴다. 
    • Checked Exception은 복구 불가한 에러이다. 개발자가 직접적으로 컨트롤하지 않는다. 

    책 - 클린코드 (로버틴 마틴 C)

     

    • Checked Exception으로 개발하면 catch 문을 비워두는 사례 자주 생기는데 이는 지양한다. (Diaper Pattern으로 이름도 있음)
    public void applyDiscount(Order order, Customer customer) {
     try {
       if (order.getOfferDate().before(Config.getLastPromoDate())) {
          System.out.println("APPLYING DISCOUNT");
          order.setPrice(order.getPrice() * (100 - 2 * customer.getMemberCard().getFidelityDiscount()) / 100);
       } else {
          System.out.println("NO DISCOUNT");
       }
     } catch (Exception e) {
       // TODO <- 나중에 어떤 에러 던지려 했었는지 까먹거나, 작성자가 퇴사함
     }
    }
    

    결론

    • RuntimeException을 커스텀해서 잘 사용해보자
    • e.printStackTrace()는 Throwable 객체에서 제공하는 exception call stack이다.
    • e.printStackTrace()를 사용하면 log file에 Error가 쌓이지 않기 때문에 쓰면 안된다.

     

    참고

    반응형
Designed by Tistory.