[Java] try catch문을 코드에서 사용해보자.

Date:     Last Updated:

포스팅을 위해서 참고한 블로그 1. 예외처리 2. 예외처리가 발생하는 위치와 코드의 흐름 3. 예외처리 (종류와 범위)

  • 해당 블로그가 깔끔하고 간결하게 예외처리를 설명해주어서 이해가 더 쉽게 되었다.

자바에서는 오류를 오류(Error)와 예외(Exception)로 나눈다.

  • 오류(Error)는 시스템이 종료될 수준의 심각한 문제를 의미한다.
  • 예외(Exception) 개발자의 실수나 사용자의 영향에 의해서 발생하는 수습 가능한 문제를 의미한다.

자바에서의 예외는 크게 2개로 나눌 수 있다.

    1. Compile Error
    1. Runtime Error
  • 컴파일 에러는 컴파일 시점에서 컴파일러가 잡아주기 때문에 이때 발생하는 오류는 수정하면 되고 그렇게 큰 문제는 되지 않는다. 수정하지 않으면 컴파일 자체가 되지 않기 때문이다.
  • 중요한 것은 Runtime Error이다. Runtime Error는 또 2가지로 나뉜다.
  • -a. Error: Error는 보통 메모리 부족같은 복구할 수 없는 심각한 오류이고
  • -b. Exception: Excetion은 제일 많이 볼 수 있는 것은 NPE (NullPointException) 같은 복구가 가능한 오류이다.

우연치 않게 예외처리를 많이 하게 되다.

  • 보통 프로그래밍 언어를 처음 배우면 Exception이라는 예외처리 문법을 배우긴 배운다. (나는 그걸 잘 쓰지 못했다.)
  • 나만 그런지 모르겠지만 언어를 배우고 나서 프로그램을 만들게 되면 내가 원하는 방식으로 프로그램을 만들게 된다.
  • 그러면 어떤 예외가 발생했을 때 예외를 핸들링하는 것보다는 그 예외 자체가 안나게 하는 방식으로 코딩을 했어서 예외처리 코드를 사용하는 것이 적었다.
  • 그러다 이번에 프로젝트를 하면서 웹사이트를 크롤링 할 필요가 있었는데 크롤링은 남이 만든 것을 찾고 읽고 하는 것이어서 예외처리를 해야할 부분이 많았다.
  • 가령 A, B, C 페이지에는 1번 버튼이 존재했는데 D,E 페이지에는 존재하지 않는 경우가 그랬다. 이런 것은 사실 if문으로도 처리가 가능한 것들도 있었는데
  • if문으로 처리 불가능한 부분이 있어서(보통은 외부 라이브러리 함수 예외) 필수적으로 try catch로 예외처리가 필요했다.

Java console프로그램을 기준으로 try catch을 main메서드 한곳에만 써도 모든 예외를 “확인” 하는 것은 가능하다.

  • exception을 배울때는 “이런 문법이 있다.” 라는 느낌으로 배워서 그런지 어느 부분에서 예외를 어떻게 어디에서 처리해야 하는지 헷갈리는 부분이 정말 많았다. 그런 부분을 상단에 적은 블로그가 꽤 많이 해소 시켜주었다.
  • 더욱 더 알게 된것은 자바 콘솔 프로그램을 기준으로 try catch문 딱 한개만으로도 모든 예외를 “확인” 하는 것은 가능했다. 물론 어느정도의 처리도 가능하다.
  • 다만 왜 try catch라는 것이 따로 문법으로 존재하고 throw new Exception이 존재하고 에러의 발생시점과 처리시점이 중요하다는 것을 이번 기회에 조금 더 깨닫게 되었다.
  • 아래 코드를 보자.

1.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Playground {

    static void method1(){
        method2();
    }

    static void method2(){
        throw new Exception("error method 3"); 
    }

    public static void main(String[ ] args) {
        method1();
    }
}
  • 이 코드에서 예외가 나는 부분이 정확히 어디이고 그 예외는 어느 부분에서 핸들링하고 있을까?
  • 예외발생 지점은 method2이지만 핸들링해서 처리해주는 부분은 없다. 그리고 method2에서 “error method 3” 발생함과 동시에 프로그램은 죽는다.

2.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Playground {

    static void method1(){
        method2();
    }

    static void method2(){
        throw new Exception("error method 3"); 
    }

    public static void main(String[ ] args) {
        try {
            method1();
        } catch (Exception e) {
            System.out.println(e.toString());
        }
    }
}
  • 코드가 살짝 바뀌었다. 예외가 나는 부분이 정확히 어디이고 그 예외는 어느 부분에서 핸들링하고 있을까?
  • 예외발생 지점은 동일하게 method2이고, main 메서드에서 핸들링을 하려고 한다. 다만 이 코드도 바로 위의 1번 코드와 동일하게 예외가 발생함과 동시에 죽는다.
  • main메서드에서 try catch문으로 예외처리를 하고 있는 것처럼 보이지만 발생하는 예외를 감싼 try catch문도 없고 예외가 발생한 메서드를 호출한 함수에게 예외를 전달하는 throws 문도 없기 때문이다.

  • 여기서 알 수 있는 것은 예외가 발생하면 해당 예외를 감싸고 있는 try catch문에서 처리를 하거나 예외가 발생한 메서드에서 호출한 메서드에게 예외를 반드시 전달해야 한다는 것이다.
  • 그렇지 않으면 프로그램은 그대로 죽는다.

3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Playground {

    static void method1() throws Exception{
        method2();
    }

    static void method2() throws Exception{
        throw new Exception("error method 3"); 

        System.out.println("예외처리 성공!");
        importantMethod();
    }

    public static void main(String[ ] args) {
        try {
            method1();
        } catch (Exception e) {
            System.out.println(e.toString());
        }
    }
}
  • method2에서 발생한 예외를 드디어 main에서 처리할 수 있게 되었다. 다만 method2는 method1이 호출했기 때문에 1과 2 모두 throws Exception을 써야만 main의 try catch문에서 예외를 처리 할 수 있다.
  • 하지만 지금 코드는 또 예외를 발생시킨다. 이유는 method2에서 발생한 throw new Exception(“error method 3”);는 main에서 처리하겠지만 그 뒤에 남겨진 System.out.println(“예외처리 성공!”);importantMethod(); 이 두개의 메서드가 죽은 코드가 되어서 절대로 실행이 되지 않기 때문에 또 예외가 발생한다.
  • importantMethod(); 이름 그대로 이 메서드는 매우 중요한 작업을 하고 있다. 그런데 바로 위에서 예외가 발생되어서 실행되지 않는다면 힘들게 예외처리한 이유가 사라진다.
  • 이것을 importantMethod(); 실행되도록 변경해보자.

4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Playground {

    static void method1(){
        method2();
    }

    static void method2(){
        try {
            throw new Exception("error method 3"); 
        } catch (Exception e) {
            System.out.println(e.toString());
        }
        
        System.out.println("예외처리 성공!");
        importantMethod();
    }

    public static void main(String[ ] args) {
        method1();
    }
}
  • 매우 중요한 작업 importantMethod(); 를 실행시키기 위해선 method2내부에서 예외처리를 해주어야 한다.
  • main에 있던 예외처리를 method2 내부로 옮기고 method2와 method1의 throws 문을 없애주었다.
  • 결과적으로 말하고 싶은 것은 예외처리는 예외처리 그 자체로도 중요하지만 어디서 예외가 발생하고, 발생된 예외를 어디서 처리해주는 것도 아주아주 중요하다는 것이다.

크롤링 코드를 만들면서 정말 중요한것을 배운 것 같다.

  • 앞으로는 예외가 없도록 코딩을 하는 것도 중요하겠지만 예외가 날만한 부분이 있다면 주저없이 예외처리를 하도록 노력하자.
  • 당연히 처음에는 잘 안되겠지만 계속 적용하다보면 언젠가 자연스럽게 적용되어지겠지.

Leave a comment