Error와 Exception
Java는 오류가 발생하거나 발생할 여지가 있는 여러 상황에 대한 예외를 만들어 두었습니다.
오류(Error)
시스템이 종료되어야 할 수준의 상황과 같이 수습할 수 없는 심각한 문제를 의미합니다. OutOfMemory나 StackOverFlow처럼 일단 발생하면 복구할 수 없는 오류입니다. 예측하여 방지할 수 없는 영역입니다.
예외(Exception)
개발자가 구현한 로직에서 발생한 실수나 사용자에 의해 발생하는 영역으로 오류와 달리 개발자기 미리 예측하여 방지할 수 있습니다.
오류와 예외 모두 Throwable을 상속 받습니다.Throwable 클래스 내부의 설명을 인용하여 설명하자면 Java 언어의 모든 오류 및 예외의 슈퍼클래스입니다. 예외 상황이 발생했음을 나타내기 위해 일반적으로 오류와 예외라는 두 가지 하위 클래스의 인스턴스를 사용하고 일반적으로 이러한 인스턴스는 관련 정보(stacTrace)를 포함하여 예외적인 상황에서 생성됩니다. 오류에 대한 자세한 정보를 제공하는 메시지 문자열(message)도 포함될 수 있습니다.
Exception과 Runtime Exception
개발자가 직접 처리할 수 있는 예외에는 Exception을 상속받는 클래스들과 Exception의 일종이지만 RuntimeException을 상속 받는 클래스들이 있습니다. 이 둘을 기준으로 CheckedException과 UnCheckedException을 구분하고 다른 처리를 하게 됩니다. 그 차이를 알아보도록 하겠습니다.
Checked Exception
- 컴파일 시점에 확인 가능합니다.
- 반드시 예외 처리를 해줘야 합니다.
- 트랜잭션 처리 시 예외가 발생하여도 롤백 하지 않습니다.
- IOException, ClassNotFoundException 등등...
UnChecked Exception
- 런타임 시점에 확인 가능합니다.
- 명시적으로 하지 않아도 됩니다.
- 트랜잭션 처리 시 예외가 발생하면 롤백 해야합니다.
- NullPointException, ClassCastException 등등...
Checked와 UnChecked의 가장 명확한 구분 기준은 '꼭 처리를 해야 하는가'입니다. Checked Exception이 발생 할 가능성이 있는 메서드라면 반드시 try/catch로 감싸거나 throw로 던져서 처리해야 합니다. 반면 UnChecked Exception은 명시적으로 예외처리를 하지 않아도 됩니다.
예외의 사용과 처리
앞에서 예외의 종류를 알아봤습니다. 이제 예외의 사용과 처리에 대해 알아보겠습니다. 발생한 예외가 프로그램에 지장을 주지 않더라도 예외에 대한 처리를 하도록 해야합니다. 트래킹 로그를 찍어 기록을 남기거나 예외 처리 방법들로 처리하여 항상 인지하고 있는 것이 좋습니다.또 개발자는 상황에 따라 throw 예약어를 통해 Exception을 강제로 발생 시킬 수 있습니다. 또 발생한 예외에 대해 try-catch, try-catch-finally, try-with-resources 등을 사용하여 처리할 수 있습니다.
//try-catch
try {
...
} catch(Exception e) {
...
}
//try-catch-finally
try {
...
} catch(Exception1 e1) {
...
} catch(Exception2 e2) {
...
} finally {
...
}
//try-with-resources
try(SampleResource resource = new SampleResource()) {
...
} catch(Exception e) {
...
}
try-with-resources
Java7부터 지원하는 문법으로 AutoClosable을 구현하는 구현체를 try문의 인자로 전달할 경우 구문이 끝날 때, 알아서 자원을 해제해 주는 방식입니다. File I/O에서 InputStream, OutStream 등 자원들을 finally에서 null로 할당 해제해주던 구문을 쉽게 처리할 수 있게 해주는 방식입니다.
예외 처리 방법
예외 복구
- 예외 상황을 파악하고 문제를 해결해서 정상 상태로 돌려놓는 방법입니다.
- 예외를 잡아서 일정 시간, 조건만큼 대기하고 다시 재시도를 반복합니다.
- 최대 재시도 횟수를 넘기게 되는 경우 예외를 발생시킵니다.
final int MAX_RETRY = 100; public Object someMethod() { int maxRetry = MAX_RETRY; while(maxRetry > 0) { try { ... } catch(SomeException e) { // 로그 출력. 정해진 시간만큼 대기한다. } finally { // 리소스 반납 및 정리 작업 } } // 최대 재시도 횟수를 넘기면 직접 예외를 발생시킨다. throw new RetryFailedException(); }
예외 처리 회피
- 예외 처리를 직접 담당하지 않고 호출한 쪽으로 던져 회피하는 방법입니다.
- 예외 처리의 필요성이 있다면 어느정도 처리하고 던지는 것이 좋습니다.
- 긴밀하게 역할을 분담하고 있는 관계가 아니라면 예외를 그냥 던지는 것은 무책임합니다.
- File I/O 관련 예제에서 많이 볼 수 있는 방식입니다.
// 예시 1 public void add() throws SQLException { // ...생략 } // 예시 2 public void add() throws SQLException { try { // ... 생략 } catch(SQLException e) { // 로그를 출력하고 다시 날린다! throw e; } }
예외 전환
- 예외 회피와 비슷하게 메서드 밖으로 예외를 던지지만, 그냥 던지지 않고 적절한 예외로 전환해서 넘기는 방법입니다.
- 조금 더 명확한 의미로 전달하기 위해 적합한 의미를 가진 예외로 변경합니다.
- 예외 처리를 단순하게 만드이 위해 포장할 수 있습니다.
// 조금 더 명확한 예외로 던진다. public void add(User user) throws DuplicateUserIdException, SQLException { try { // ...생략 } catch(SQLException e) { if(e.getErrorCode() == MysqlErrorNumbers.ER_DUP_ENTRY) { throw DuplicateUserIdException(); } else throw e; } } // 예외를 단순하게 포장한다. public void someMethod() { try { // ...생략 } catch(NamingException ne) { throw new EJBException(ne); } catch(SQLException se) { throw new EJBException(se); } catch(RemoteException re) { throw new EJBException(re); } }
참고자료
'Language > Java' 카테고리의 다른 글
함수형 인터페이스 (Functional Interface) (1) | 2023.01.31 |
---|---|
람다식 (Lamda Expression) (0) | 2023.01.31 |
[Java] Collection - (2) List란? (0) | 2021.11.12 |
[Java] Collection - (1) Collection Framework란? (0) | 2021.11.12 |
[Java] 반복문 (0) | 2021.11.06 |
댓글