자바에서 개발을 하다 보면 OOOException이라는 내용을 콘솔에서 많이 보게 됩니다.
뭔가 위험해 보이는 빨간색의 글자에서 나오는 분위기 때문에 그런지 우리는 흔히 이것을 에러라고 많이들 이야기하는데요, 사실은 에러가 아니라 예외라고 부르는 녀석입니다.
그럼 이 예외는 무엇이고, 어려와는 무엇이 다른지 알아보도록 하겠습니다.
예외와 에러에 대해서 먼저 알아보도록 하겠습니다.
사전적 의미로 보면 에러(Error)는 문법이나 메모리 사용 문제로 실행에 문제가 생겨 발생하는 오류이고 예외(Exception)는 사용자의 오 조작이나 외부 문제로 발생하는 오류라고 정의하고 있습니다.
즉, 개발자가 개발하다 생기는 것이 에러라고 한다면, 예외는 만들 때에는 멀쩡했지만 외부 환경에 의해서 오류가 일어나는 것이라고 이해하시면 됩니다.
이 표를 보면 예외와 에러의 차이를 조금 더 구분하기 쉬우실 겁니다.
보면 에러는 개발자의 실수, 예외는 사용자의 실수 또는 외부환경에 생기는 것을 확인할 수 있습니다.
예외는 환경 변화나 사용자의 실수로 인해 멀쩡하던 프로그램의 동작이 멈춰버릴 수 있습니다.
그렇기에 많은 인원이 한 번에 쓰는 온라인 프로그램의 경우 한 사람의 실수로 애꿎은 다른 사용자도 사용을 못하는 경우가 발생할 수 있습니다.
JAVA에서는 이런 상황에 프로그램이 멈추지 않고 동작하기 위한 예외 처리라는 것을 합니다.
말 그대로 외부 요인에 의해서 예외가 발생했을 때 이렇게 처리한다는 것을 명시해 놓는 것이죠!
그래서 예외 처리는 예외가 발생할 것 같은 곳을 지정하고, 예외 발생 시 처리할 내용을 적어 놓는 형식으로 작성합니다.
그럼 try 영역에 코드가 실행되다가 예외가 발생하면 catch 블록으로 넘어가게 됩니다.
그런데, 예외가 발생하던 하지 않던 무조건 해야 할 일이 있을 수도 있겠죠?
그럴 경우는 finally 영역에 명시해 주면 됩니다.
그럼 try 안의 내용을 무사하게 끝내던지, 도중에 catch 내용을 실행하던지 결국 finally 내용을 실행하게 됩니다.
그럼 try, catch, finally의 내용을 우리에게 익숙한 상황과 비교해 보겠습니다.
우선 김대리가 박 부장에게 보고서를 올릴 경우 무언가 잘못될 수도 있습니다. 예를 들면 작성 당시와 보고서 결재 시기의 환경이 달라져서 수정이 필요할 수도 있겠군요.
만약 그러한 부분이 발견된다면 catch에 있는 내용인 오류 부분을 지적하고 수정하라고 할 것입니다.
그렇지 않다면 try 부분이 끝까지 실행될 것입니다.
그리고 어찌 되었던 본인의 자리로 다시 되돌아가야 하겠죠?
이제 예외 처리 방법에 대해서 대략적으로 이해가 가시나요?
이런 예외는 사실 굉장히 많습니다.
우리가 다 알지 못하는 예외도 많이 있습니다.
하지만 일단 이것만 기억해 주셔도 좋습니다.
예외는 최상위 예외 클래스가 있고, 이를 상속받는 실행 예외 클래스가 존재합니다.
일반예외와 실행예외, 이 둘의 차이는 무엇일까요?
일반 예외는 우리가 프로그램을 실행하기 전에 발견할 수 있는 예외들입니다.
그래서 특정 예외의 필요성을 자동으로 알려줍니다.(위의 그림 참조)
하지만 실행 예외는 그렇지 않습니다.
일단 실행한 후에 그 상황이 되어야만 알 수 있습니다.
그래서 개발자의 입장에서는 이 실행 예외를 미리 알아차리고 예외처리를 하는 것이 중요합니다.
그렇기 때문에 우리는 가장 많이 나타나는 실행 예외 몇 가지 정도는 알아 둘 필요가 있습니다.
그런데 이런 예외가 코드에서 하나만 발생하면 좋겠지만 그렇지 않은 경우들도 많습니다.
이 경우 위와 같이 00 예외 발생 시 특정 catch를 실행하도록 예외처리를 할 수 있습니다.
예외마다 각기 다른 처리를 해 주고 싶을 땐 유용하겠지만, 한 코드에서 많은 예외가 일어날 가능성이 있다면 catch 문이 굉장히 길어질 수 있겠군요.
그래서 JAVA 1.7부터는 multi catch 지원합니다.
00 예외 또는 00 예외 발생 시 특정 catch를 실행할 수 있도록 말이죠!
모아서 처리할 수 있으니 조금 더 편리하겠죠?
하지만 우리는 다른 방법으로 조금 더 예외처리를 단순하게 할 수 있습니다.
모든 예외는 Exception의 자식이죠? 부모의 자식들은 부모의 형태에 들어갈 수 있다.
그렇습니다, 다형성이죠! 다형성을 이용하면 catch 하나만으로 모든 예외를 받아 낼 수 있습니다.
이렇게 try에서 처리하는 코드 중에 특정한 예외가 발생 시 catch에서 처리하도록 하는 예외 처리에 대해서 알아보았습니다.
하지만 가끔은 이런 예외를 스스로 처리하지 않고 떠넘기는 경우도 있습니다.
어떤 경우인지 알아볼까요? 예를 들면 팀장님이 한 직원에게 업무지시를 내렸습니다.
그러던 중 직원이 실수를 해서 일을 그르쳤습니다.
팀장님에게 혼나기도 싫고, 그냥 스스로 해결할 수 있는 문제 같기에 스스로 처리할 수도 있겠죠?
이것이 우리가 앞에서 배운 try-catch를 이용한 예외처리 방법입니다.
하지만 스스로 처리가 어려울 것 같을 때, 나에게 일을 시킨 상사에게 보고를 해서 처리하도록 할 수 있습니다. 이것을 우리는 throws 방식이라고 합니다.
이 throws 방식은 나에게 일을 시킨 상사에게만 넘길 수 있습니다.
클래스 다이어그램으로 표시하자면 a() 메서드가 b() 메서드를 호출하고, b() 메서드가 c() 메서드를 호출하는 상황이라고 보시면 됩니다.
그렇기에 c()에서 throws를 사용하면 해당 예외가 b() 에게로 넘어가고, b() 메서드가 throws 하면 a() 에게로 넘기는 구조가 됩니다.
물론 도중에 누군가가 ‘내가 책임지겠소!’ 하고 try-catch를 한다면 더 이상 thows로 전가되지 않게 됩니다.
throws는 책임을 전가하는 것이라는 설명을 써서 부정적으로 느껴지실 수 있습니다. 하지만 실제로 사용하는 상황을 보면 합리적이다는 것을 느끼실 수 있습니다.
지금까지 예를 든 상황은 1:1 관계였습니다.
하지만 실제로는 하나의 상사에 여러 부하직원이 있기 마련이죠!
그렇기 때문에 부하직원들이 일을 하다가 같은 실수가 나는 것에 대해 각각 처리하는 것보다는, 상사가 한 번에 처리해 주는 것이 더욱 업무 효율이 좋을 것입니다.
예외처리에 대해서 정리해 볼까요?
예외는 사용자나 환경에 의해서 문제가 일어나는 것을 말하고, 이것 때문에 프로그램이 멈춰 애꿎은 사용자들이 피해를 입지 않게 하기 위한 것이 예외처리라고 했습니다.
예외는 프로그래밍 중에 알 수 있는 일반 예외와 프로그램이 실행되어 상황이 발생해야만 알 수 있는 실행 예외가 있다고 했고요.
그리고 이 처리는 스스로 그 자리에서 처리되는 try-catch와 자신에게 일을 시킨 메서드에게 전가하는 throws라는 것이 있다고도 했습니다.
또한 다형성을 활용하여 예외처리가 어떻게 간단해졌는지도 알아보았죠?
다음시간에는 또 다른 개념을 배워보도록 하겠습니다.