Right now do !

[C#기초]응용 프로그램의 예외 처리-1편 예외(Exception)의 개념

by 지금당장해

10년 이상을 닷넷과 C#을 사용하여 개발한 경험을 바탕으로 응용 프로그램 예외 처리에 대한 글을 연재 하려 한다. 예전에 예외라는 개념이 없었던 언어들은 함수를 호출해서 잘 처리 되었는지를 보통 함수의 반환 값으로 넘겨 줬다. 그리고 막상 결과는 Call by Reference방식으로 반환 하는 경우가 많았다. 초기 윈도우즈를 발표했들 당시 MS가 개발자들에게 공개한 API(Win32 API)들이 그러 했다.


원래 함수라는 것이 수학에서 나온 것일 터인데 먹은데로 다시 값을 넘겨서 그것을 활용하는 구조가 프로그램 언어론 학자가 아니더라도 보기 좋지 못했을 뿐더러 반환 값으로 함수의 정상 처리 여부의 상태를 반환한다는 것도 한계가 있다. 예를들어 어떤 함수가 Http Request를 이용하여 원격 요청을 해서 받은 결과로 뭔가를 처리 해야 한다고 했을때 같은 오류지만 404.X와 500.X는 엄연히 다른 것이기에 이 함수는 Boolean을 반환 할 것이 아니라, 여러 오류 상태를 반환할 수 있게 열거형으로 정의 해야 한다. 뭐 이렇게 하면 되지... 뭣이 더 필요한디 라고 나는 반문하였다. (아주 어릴적에... ) 예외는 이와 더불어 여러 정보를 추가 정보를 구성할 수도 있으며 원천이 되는 예외를 포함시켜 상위 예외를 재정의 해서 호출자게 넘겨 줄 수 있다. 


요즘 신입사원들은 워낙 공부를 많이 하고 와서 뭐 예외 쯤이야 모두 잘 알고 입사하지만 옛날에는 자바나 자바스크립트 제어문 정도만 겨우 배우고 오시는 분들도 있었다. 이런 분들께 예외를 설명하기 제일 좋은 표현이 오류를 호출자에게 던지는거야(throw), 제2의 리턴이라고 봐도 되 .... 근데 함수 리턴하고 차이 점은 말이야 try ... catch 문을 사용해서 잡지 않으면 그냥 통과 해버려, 마치 외야수가 땅볼로 잡은 공을 홈을 향해 던지는데 중간 내야수가 굳이 잡지 않으면 포수(catcher)에게 가듯이 ... 그리고 예외가 발생하여 throw가 일어나면 이후 호출 Statement는 모두 무시된다. 마치 함수 중간에 return 을 만난것 같이 이후 모든것이 무효다. 




 이 throw의 시점은 개발자가 결정한다. 파일을 써야 하는데 인자로 넘긴 경로가 존재 하지 않거나, 계좌에 송금을 해야 하는데 인자로 넘어온 수가 1보다 작거나 예외를 throw해야 하는 경우는 다양하다. 그러나 이런 부분을 모두 예외 객체를 만들어 Throw해야 하는지 아니면 이런 문제가 발생 한 시점에서 사용자에게 메시지박스로 알려야 할지 이와 더불어 오류 내용을 다양한 방법으로 Logging을 할지 이 모두 개발자가 결정 해야 할 문제다.  


아래 코드는 위 개념을 코드로 옮겨 본 것이다.


 
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("=예외처리 개념=======================");
            double result = -1;
            try
            {
                result = fnA("hong", 0);
            }
            catch (Exception ex)
            {
                // 프로그램의 진입점 함수이다 여기서 어떤 처리를 해야 하는가는 개발자의 몪이다.
                throw ex;
            }

            Console.WriteLine("=====================================");
            Console.WriteLine(string.Format("Balance:{0}", result));
            Console.WriteLine("=====================================");
        }

        static double fnA(string account, double amt)
        {
            double curr = fnB(account);

            if (amt < 1)
            {
                // 아래 코드와 같이 논리적인 문제로 예외를 발생시키는 경우 외에도 예외를 호출자에게 집어 던져야 하는 이유
                // 는 다양하다.
                // 호출하려는 함수 또는 문장에서 예외가 발생하는 것을 잡았는데 호출자에게 이를 알려야 하는 경우 등
                throw  new Exception("금액은 1보다 작을 수 없습니다.");
            }

            return curr + amt;

        }

        static double fnB(string account)
        {
            return 1000000;
        }

    }


헌데 위 코드와 같이 Main함수에서 조차 예외를 throw를 한다면 또는 애시당초 그 어디에서도 예외를 헨들링 하지 않는다면 그 예외는 어떻게 될까? Figure 1-1에서 Main 함수에서 throw된 예외 객체가 호출한 측으로 전달되는 이 상황, 이를 다음 연재글에서 다루도록 하겠다.

블로그의 정보

지금 당장 해!!!

지금당장해

활동하기