삽질의 현장/- .NET

#038_닷넷(.NET)_.Net Framework 기본 - 예외 처리

shovelman 2015. 10. 29. 02:55


안녕하세요 삽잡이입니다.

이번 시간에는 C#에서 제공하는 예외처리에 대해서 알아보려고합니다.


예외처리란 

어떤 얘기치 못한 실시간에 '얘기치 못한 예외상황'이 발생하면 처리하는 작업을 말합니다.

예외처리는 실시간에 발생하지요...



예외처리는 크게 서버와 클라이언트로 나뉩니다.


서버에서는

예외 클래스를 정의, 예외 클래스를 throw (예외 던지기라고도 하지요...)

이 두가지의 과정을 거칩니다.


클라이언트는 try를 합니다...

즉, function을 수행하다가 예외가 발생하면 catch 한다 이겁니다.

이를 try - catch 문이라고도 하지요...


그런데, 여기까지는 C++ 문법입니다.

여기에 C#에서는 하나가 더 추가 되지요... finally 입니다.

이 곳에는 '어떤 상황에서든' 즉, 예외가 나던 안나던 처리할 수 있는 코드를 입력합니다.


C++까지는 단지,

서버 처리에서는 

프로그램의 오류값 반환, 오류 메시지 전송, 로그 남김, 프로그램 종료 알림

클라이언트 처리에서는 

오류 메시지, 오류 값, 정수, 로그 파일등을 열어보거나

프로그램을 종료하며 클라이언트가 대체하던지 정도의 처리만 있었습니다.


하지만, 객체 지향에 입각한 C#에서는 

모든 것을 객체화 하여 정보를 가지고, 다형성과 상속에 의해 일괄적으로 다룰 수 있지 않습니까?

따라서 구조적인 예외처리가 가능해졌습니다.


서버 쪽에서는 클라이언트에게 어떠한 문제가 발생할 경우에 대한 예외 상황을 정의를 합니다.

이 서버에는 많은 정보들을 포함하고 있지요...

예를 들어 형식 변환이 안되면 형식 변환에 대한 예외에 대한 정보를 담고 있다 

이 소리입니다...



숫자 문자(digit)외에 다른 문자가 포함되어있어

int형으로 변환을 할 수 없게 된다면? 

Parse() 메서드는 예외를 던집니다. 


우리가 만든 메서드라면 서버를 건들 수 있지만,

Parse()와 같은 메서드는 제공해주는 메서드이기에 우리가 건들 수 없습니다.

따라서, 우리는 Client 족에서 예외처리를 해줘야합니다.


Parse()와 같은 기존 메서드들은 대부분 예외가 정의되어있는 함수를 제공해줄 것입니다.


아무튼... 모든 서비스마다 예외를 던진다는 것이 아닙니다.

따라서 MSDN에서 예외들을 확인할 수 있습니다.



Parse()라는 메서드는 저 세가지의 예외를 제공해주는군요...


따라서 프로그램의 예외처리를 위해서 위의 세가지 예외를 모두 처리해보도록 하겠습니다.




try는 '예외를 검사' 하는 것입니다.

따라서 예외가 발생하면 예외가 발생한 문장 이후는 출력되지 않지요...

따라서, try문에는 코드가 종속적인 것들만 모여야합니다.

독립적인 문장은 밖으로 빼버려야하지요...


예외가 발생하면 출력할 수 없는 문장들은 상관이 없지만,

예외와 관련없는 문장들 즉, 독립적인 코드들은 try에 묶이면 안된다는 것입니다.


예외 발생시에만 예외가 발생하고,

예외가 발생하지 않는 경우 try - catch 문이 없듯이 동작하는 것이

바로, 예외처리의 핵심입니다.


try - catch 문은 혹시나 모를 예외 상황을 위해 존재하는 것입니다.

사실은 실질적인 코드에 포함되지 않는 것이지요...

만약, 예외 상황이 발생하면 동작하는 것이구요...


message에는 예외가 발생한 자세한 상황 정보등이 들어있습니다.


그런데, Parse() 메서드는 예외가 세가지이니 다행이지,

만약 예외가 수 없이 많은 메서드를 쓸 때에는 어떻게 해야할까요...


모든 사용자와 시스템에서 정의한 예외들은 

궁극적으로 System.Exception 클래스를 상속받습니다.

즉, 모든 예외들을 Exception 하나로 처리할 수 있다 이겁니다.



Exception 클래스는 최상위 부모입니다.

메시지들은 모두 '다형적인 메시지'로 만들어져 있기 때문에 이게 가능한 것입니다.


정리하자면,

다형성을 이용해서 하나의 단위로 처리할 수 있다는 것이

바로 구조적인 예외처리의 장점 중 하나라는 것입니다.



만약, DB를 열었을 때를 생각해봅시다.

그런데 DB를 열었을 때 예외 상황이 발생하게 되면 어떻게 될까요...

DB를 여는 것 까지는 좋았는데... 닫는 일은..?


이처럼 예외가 발생하던 하지 않던 '반드시 실행되어야하는'

즉, DB와 같이 마무리 작업이 필요한 부분은 finally 블럭에 구현하는 것입니다.


예를 들어 항상 쌍으로 이루어지는 작업들

음... 메모리 할당 및 제거, DB 열기 및 닫기, 리소스 얻기 및 반환 등등 

이러한 작업들의 마무리는 finally에 하는 것이 맞다 이겁니다.


Exception는 두 가지로 나눌 수 있습니다.

즉, 예외 클래스로 정의하기 이전에 두 가지로 나뉜다는 소리입니다.



사실 약속일 뿐, 권장 사항입니다...

뭐 99%가 System Exception입니다.


Application Exception을 발생시키고 싶다면, 

예외 적인 상황에 대해 만들 수 있습니다.


예외에 대한 클래스도 형식이 있을 것입니다.

이 예외에 대해서는 우리는 Exception Class의 자식인

Application Exception 클래스를 상속 받아서 구현할 수 있습니다.


 

message는 오버라이드를 하지 않는다면,

기본 적인 메시지만 발생하는 것을 참고하시길 바랍니다.


또한, 속성도 특수한 메서드이기 때문에 

오버라이드가 가능한 사실도 참고하시길 바랍니다.


사실, 구현보다는 대부분 활용하는 부분이 많습니다.


이번 시간은 여기까지 하도록 하겠습니다.


이상 삽잡이였습니다!