오늘은 C#의 예외처리에 대해 알아보겠습니다. 


예외를 적절하게 사용하면 프로그램 실행 중간에 에러가 터져도 프로그램이 꺼지지 않고 넘길 수 있습니다. 하지만 굳이 예외가 필요없는 곳인데도 불구하고 과도하게 사용 할 경우 성능 저하를 불러 올 수 있습니다.


다음과 같은 형식으로 예외 처리를 할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
static void Main(string[] args)
{
    // try 문 안에서 예외를 던져야 예외를 catch 할 수 있습니다.
    try
    {
        // 생성자에 Message를 넣을 수 있습니다.
        throw new Exception("예외를 던집니다.");
    }
    // try 문 안에서 throw 된 예외를 catch 문에서 받습니다.
    catch (Exception ex)
    {
        // 예외 클래스의 Message 변수로 예외처리 
        //변수의 생성자에 넣은 메시지를 얻어 올 수 있습니다.
        Console.WriteLine(ex.Message);
    }
}
 
cs


출력 결과.


예외를 던집니다.

계속하려면 아무 키나 누르십시오 . . .


만약 throw 뒤에 다른 코드가 있다면 어떻게 될까요?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
static void Main(string[] args)
{
    // try 문 안에서 예외를 던져야 예외를 catch 할 수 있습니다.
    try
    {
        throw new Exception("예외를 던집니다.");
 
        Console.WriteLine("출력");
    }
    // try 문 안에서 throw 된 예외를 catch 문에서 받습니다.
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
}
 
cs


출력 결과.


예외를 던집니다.

계속하려면 아무 키나 누르십시오 . . .


출력 결과를 보면 알 수 있듯이 try문 내에 예외가 던져진 곳 다음 코드는 실행이 안되는 것을 알 수 있습니다.


다음과 같은 상황에서는 어느 catch문이 실행될까요?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
static void TestFunc()
    try
    {
        throw new Exception("예외");
    }
    catch (Exception ex)
    {
        Console.WriteLine("TestFunc " + ex.Message);
    }
 
}
 
static void Main(string[] args)
{
    // try 문 안에서 예외를 던져야 예외를 catch 할 수 있습니다.
    try
    {
        // 예외처리 구문이 있는 함수를 호출합니다.
        TestFunc();
    }
    // try 문 안에서 throw 된 예외를 catch 문에서 받습니다.
    catch (Exception ex)
    {
        Console.WriteLine("MainFunc" + ex.Message);
    }
}
 
cs


출력 결과.


TestFunc 예외

계속하려면 아무 키나 누르십시오 . . .


TestFunc 함수 내에 예외가 출력되었습니다. 결과를 보면 가장 가까운 catch (가까운 스택) 문에 점프하는 걸 볼 수 있습니다. 


근데 제가 처음에 너무 과도하게 사용하면 성능 저하가 있을 수도 있다고 적어놨습니다. 왜 그럴까요?


아래 코드를 봅시다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
static void TestFunc01()
{
    TestFunc02();
 
}
 
static void TestFunc02()
{
    TestFunc03();
 
}
 
static void TestFunc03()
{
    TestFunc04();
}
 
static void TestFunc04()
{
    throw new Exception("예외");
}
 
 
static void Main(string[] args)
{
    // try 문 안에서 예외를 던져야 예외를 catch 할 수 있습니다.
    try
    {
        // 예외처리 구문이 있는 함수를 호출합니다.
        TestFunc01();
    }
    // try 문 안에서 throw 된 예외를 catch 문에서 받습니다.
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
}
 
cs


위 코드의 콜 스택은 어떻게 될까요.


예외 발생 전

TestFunc01 -> TestFunc02 -> TestFunc03 -> TestFunc04 -> 예외 발생!


예외 발생 후

Test04 -> Test03 -> Test02 -> Test01 -> catch 문!.


예외가 발생하면 catch문이 있는 곳 까지 콜 스택이 되돌려집니다.

물론 위와 같은 코드는 한 번만 실행되기 때문에 성능 저하가 없을 수도 있습니다.


하지만 


서버 같이 항상 실행되는 경우 저런 예외처리 구문이 많으면 성능 저하가 생길 수 도 있습니다.


단 많은 .Net Framework에서는 예외처리를 사용하여 에러를 확인해 할 때가 있습니다.

예를 들면 C# System.Net에 서버 API들은 대부분의 오류를 예외처리로 던져줍니다. 


그렇기 때문에 신중하게 사용하는 것이 중요합니다.



+ Recent posts