Java 예외 계층 - 활용

예외를 잡아서 처리할 때 예외 계층을 활용할 수 있다.

만약, NetworkClient 수 많은 예외가 발생한다면?
이런 경우 모든 예외를 하나하나 잡아서 처리하는 것은 시간이 매우 오래 걸릴 것이다.

이전에 예외 계층에서 try ~ catch ~ catch... 이어서 출력한 것을 떠올려 보자.

try {
    client.connect();
    client.send(data);
} catch (ConnectException e) {
    System.out.println("[Error] Connect Failed address: " + e.getAddress() + ", message: " + e.getMessage());
} catch (SendException e) {
    System.out.println("[Error] Send Failed message: " + e.getSendData() + ", message: " + e.getMessage());
} finally {
    client.disconnect();
}

catch문으로 계속 이어서 예외를 잡으면 불필요한 표시로 가독성이 떨어진다.

그렇다면 새롭게 예외 처리하도록 개선 시도해보자.

예외 처리에 중요, 보통, 낮음으로 나누어주자

  • Network에서 연결 오류는 중요한 편이다.
    • ConnectException 예외 발생 시 명확한 메시지가 필요하다.
      • [Connect Error] Address: ...
    • 나머지 에러에 대한 메시지는 단순하게 출력한다.
      • [Network Error] Message: ...
    • 그 외의 문구는 다음과 같이 출력한다.
      • [Unknown Error] Message: ...

NetworkService.class

try {
    client.connect();
    client.send(data);
} catch (ConnectException e) {
    System.out.println("[Connect Error] Connect Failed. address: " + e.getAddress() + ", message: " + e.getMessage());
} catch (NetworkClientException e) {
    System.out.println("[Network Error] Send Failed. message: " + e.getMessage());
} catch (Exception e) {
    System.out.println("[Unknown Error] Failed. message: " + e.getMessage());
} finally {
    client.disconnect();
}

Send Message data: error1
[Connect Error] Connect Failed. address: http://kiioio.com is Connect Open Failed, message: http://kiioio.com
http://kiioio.com Connect Closed Success

Send Message data: error2
http://kiioio.com Connect Open Success
[Network Error] Send Failed. message: http://kiioio.comSend Failederror2
http://kiioio.com Connect Closed Success

Send Message data: ap
http://kiioio.com Connect Open Success
http://kiioio.com Send Message data: ap
http://kiioio.com Connect Closed Success

코드를 살펴보면 알겠지만 catch 건너뛸 때마다 예외 계층 구조로 만든 것이 자기의 부모 예외로 이동한다. 왜냐면 부모는 자식을 모두 담고 있기 때문에 포괄적으로 예외를 잡아준다.

  • catch 문은 처음 마주치는 것부터 동작한다.
  • catch 문으로 예외를 넘어갈수록 부모 예외 객체로 잡아주어야 한다.
    • 반대로 한 경우 컴파일 오류 발생함.

catch 문 예외 계층 둘 중 하나 잡기

catch 에는 예외 계층 하나가 아닌 아니라 여러 개 예외 객체를 넣을 수 있다.

try {
    client.connect();
    client.send(data);
} catch (ConnectException | SendException e) {
    System.out.println("[Connect Error or Network Error] Failed. message: " + e.getMessage());
} finally {
    client.disconnect();
}
  • 공통 예외를 한번에 잡아준다. 이 경우 ConnectException, SendException 각자의 멤버필드를 사용할 수 없다.
  • 멤버 필드를 사용 해야한다면 둘의 부모인 NetworkClientException 멤버필드를 사용해주어야 한다.

예외 활용 정리

  • 예외 계층화로 다양하게 만들 수 있고 세밀한 동작을 깔끔하게 처리할 수 있다.
  • 또는 공통 예외로 여러 예외를 넣어서 catch 키워드 하나로 잡을 수 있다.
💡
다양한 동작으로 이끌어나갈지 공통 처리할지는 적절하게 사용해주도록한다.