책책책/토비의 스프링 3.1

[Spring] 예외(Exception) 처리

Deveun 2021. 8. 8. 03:44

토비의 스프링 4장: 예외

예외의 종류와 처리 기법

자바 개발을 하다보면 예외처리가 필요할 때가 있다. 여기서는 발생할 수 있는 예외 종류들과 처리 기법에 대해 알아보자.

 

 

예외 종류

 

(1) Error

: 시스템의 비정상적인 에러가 발생한 경우로, 주보 VM에서 발생하기 대문에 애플리케이션 코드에서는 잡을 수 없다.

(ex- OutOfMemoryError, ThreadDeath... )

 

(2) Exception

: 애플리케이션 코드의 작업중에서 예외사항이 발생한 경우이다.

-> 체크예외

일반적인 예외들이 여기에 포함된다. 자바에서 필수적으로 체크(try-catch)하도록 강요하는 예외들이다. 

-> 언체크예외

주로 개발자가 부주의하면 발생할 수 있는 예외들로, 체크가 필수적이진 않다. RuntimeException클래스를 상속한다. (ex - NullPointerException, IllegalArgumentException ...)

-> 애플리케이션예외

애플리케이션 자체 로직에 의해 의도적으로 발생시키고, 조치를 취하도록 하는 예외이다. (ex - 잔고부족과 같이 비즈니스적인 흐름을 분리시키기 위해 발생시키는 예외)

 

 

예외 처리 방법

 

(1) 예외 복구

: 재시도를 통해서 정상상태로 돌아가도록 하거나 다른 작업 흐름으로 유도하는 처리 방법

 

[예제] 파일 열기 예제 - 3번 재시도 / 횟수를 넘으면 다른 작업 흐름으로 유도

public class Main {
    public static void main(String[] args) {

        int maxRetry = 3;
        FileInputStream fi = null;

        while (maxRetry-- > 0) { // 재시도 --> 예외복구
            try {
                fi = new FileInputStream("file\\location\\file.txt");
                // ...
                return;
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } finally {
                // 리소스 반납
            }
        }
        // 다른 작업 흐름으로 유도 --> 예외복구
    }
}

 

(2) 예외처리 회피

: 자신을 호출한 쪽을 예외를 던져버림. (throws / try-catch내에서 다시 throw)

-> 처리 로직을 수행할 적절한 계층으로 예외를 던지는 것이나, 무작정 다른 계층으로 던지는 것은 무책임할 수 있음.

 

[예제] function을 호출한 외부로 예외처리 회피

public class Main {
    public static void main(String[] args) {

        try {
            function();
        } catch (IOException e) {
            // function 메소드 내부에서 회피한 예외처리
            e.printStackTrace();
        }
    }

    public static void function() throws IOException{

        try {
            FileInputStream fi = new FileInputStream("file\\location\\file.txt");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            throw e; // 메소드를 호출한 외부로 예외처리 회피
        }
    }
}

 

(3) 예외 전환

: 자신을 호출한 쪽으로 적절한 예외로 변환하여 던지는 것.

-> 목적1 - 해당 계층에서 적절한 대처를 할 수 있도록 새로운 예외로 Wrap

-> 목적2 - 예외를 계속 회피하는 것는 의미가 없기 때문에, 다른 계층에 더 넘어가지 않도록 가능한 빨리 런타임 예외로 포장하여 던지는 것.

 

[예제] 파일명 체크를 통해 특정 예외로 전환하거나, 메소드 호출부에서 예외처리를 필수로 하지 않아도 되도록 예외 포장

public class Main {
    public static void main(String[] args) {
        function();
    }

    public static void function(){

        String dir = "file\\location\\file.txt";
        
        try {
            FileInputStream fi = new FileInputStream(dir);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            if(chkDir(dir))
                throw new FileDirectoryException(e); // 새로운 예외로 전환하여 던짐
            else
                throw new RuntimeException(e); // 런타임 예외로 포장
        }
    }
    
    public static boolean chkDir(String dir) {
        // 로직 생략..
    }
}
public class FileDirectoryException extends RuntimeException {
    public FileDirectoryException(Throwable cause) {
        super(cause);
    }
}

 

 

** 교재에서는 JdbcTemplate 클래스를 사용하면서 발생하는 SQLException들에 대해 중점적으로 설명하고 있는데,  해당 게시글에서는 자바의 예외(Exception), 처리방법에 대해 좀 더 쉬운 예제를 만들어 알아보았다. 

 

 

 

[참고서적] http://www.acornpub.co.kr/book/toby-spring3.1-vol1#spring3

 

토비의 스프링 3.1 Vol. 1 스프링의 이해와 원리

스프링의 핵심 프로그래밍 모델의 원리와 이에 적용된 다양한 디자인 패턴, 프로그래밍 기법의 이해를 돕는 책

www.acornpub.co.kr