본문 바로가기
Study/C#

C# 6편: 예외 처리와 디버깅으로 안정적인 프로그램 작성하기

by wawManager 2024. 10. 25.
728x90

 

1. 예외(Exception)란?

프로그램을 실행하다 보면 의도치 않은 오류가 발생할 수 있습니다. 이러한 오류를 **예외(Exception)**라고 부르며, 예외가 발생하면 프로그램이 비정상적으로 종료될 수 있습니다. C#에서는 이러한 예외를 처리하여 프로그램이 안전하게 종료되거나, 적절한 대응을 할 수 있도록 도와줍니다.

예외 처리는 try-catch-finally 블록을 사용하여 구현할 수 있습니다.

일반적인 예외 상황

  • 사용자가 입력한 값이 잘못된 경우
  • 네트워크 연결 실패
  • 파일을 찾을 수 없는 경우
  • 데이터베이스 오류 등

2. try-catch 구문

try-catch 구문은 프로그램에서 발생할 수 있는 예외를 처리하기 위한 구조입니다.

  • try: 예외가 발생할 수 있는 코드를 포함합니다.
  • catch: 예외가 발생했을 때의 처리 코드를 작성합니다.

기본 구문

try
{
    // 예외가 발생할 가능성이 있는 코드
}
catch (Exception ex)
{
    // 예외가 발생했을 때 실행될 코드
    Console.WriteLine(ex.Message);
}

예시: 0으로 나누기 예외 처리

try
{
    int number = 10;
    int divisor = 0;
    int result = number / divisor; // 0으로 나누기 예외 발생
}
catch (DivideByZeroException ex)
{
    Console.WriteLine("0으로 나눌 수 없습니다: " + ex.Message);
}

위 코드는 0으로 나누려 할 때 DivideByZeroException 예외가 발생하고, 이를 catch 블록에서 처리합니다.

3. 여러 예외 처리

C#에서는 다양한 예외 타입을 처리할 수 있도록 다중 catch 블록을 사용할 수 있습니다. 각 catch 블록에서 다른 유형의 예외를 처리할 수 있습니다.

예시: 여러 예외 처리

try
{
    int[] numbers = { 1, 2, 3 };
    Console.WriteLine(numbers[10]); // IndexOutOfRangeException 발생
}
catch (IndexOutOfRangeException ex)
{
    Console.WriteLine("인덱스 범위를 벗어났습니다: " + ex.Message);
}
catch (DivideByZeroException ex)
{
    Console.WriteLine("0으로 나눌 수 없습니다.");
}
catch (Exception ex)
{
    Console.WriteLine("예상치 못한 오류가 발생했습니다: " + ex.Message);
}

여기서 IndexOutOfRangeExceptionDivideByZeroException을 각각 처리하고, 그 외의 예외는 마지막 catch 블록에서 처리합니다.

4. finally 블록

finally 블록은 예외 발생 여부와 상관없이 항상 실행되는 코드를 작성할 수 있는 영역입니다. 주로 파일, 네트워크 연결 해제 또는 자원 해제와 같은 작업을 할 때 사용합니다.

예시: finally 블록 사용

try
{
    int number = 10;
    int divisor = 0;
    int result = number / divisor;
}
catch (DivideByZeroException ex)
{
    Console.WriteLine("0으로 나눌 수 없습니다.");
}
finally
{
    Console.WriteLine("프로그램이 종료됩니다.");
}

finally 블록은 예외가 발생하든 그렇지 않든 실행됩니다.

5. 사용자 정의 예외

C#에서는 기본적으로 제공되는 예외 클래스 외에, 필요에 따라 사용자 정의 예외를 만들 수 있습니다. 사용자 정의 예외는 Exception 클래스를 상속받아 만듭니다.

사용자 정의 예외 클래스

class InvalidAgeException : Exception
{
    public InvalidAgeException(string message) : base(message)
    {
    }
}

사용자 정의 예외 사용 예시

class Person
{
    public int Age { get; set; }

    public void SetAge(int age)
    {
        if (age < 0)
        {
            throw new InvalidAgeException("나이는 음수가 될 수 없습니다.");
        }
        Age = age;
    }
}

class Program
{
    static void Main(string[] args)
    {
        Person person = new Person();
        try
        {
            person.SetAge(-1); // 사용자 정의 예외 발생
        }
        catch (InvalidAgeException ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

이 코드는 나이를 음수로 설정하려고 할 때 InvalidAgeException을 던집니다.

6. 예외 던지기(throw)

throw 키워드를 사용하여 예외를 명시적으로 발생시킬 수 있습니다. 예외를 발생시켜 호출자에게 처리하도록 하거나, 사용자 정의 예외를 던질 때 사용됩니다.

예시: 예외 던지기

int Divide(int a, int b)
{
    if (b == 0)
    {
        throw new DivideByZeroException("0으로 나눌 수 없습니다.");
    }
    return a / b;
}

try
{
    int result = Divide(10, 0);
}
catch (DivideByZeroException ex)
{
    Console.WriteLine(ex.Message);
}

7. 디버깅(Debugging)

디버깅은 프로그램에서 발생하는 문제를 찾아 수정하는 과정입니다. C#에서는 Visual Studio와 같은 개발 도구를 통해 디버깅 기능을 제공합니다.

디버깅 기법

  • 중단점(Breakpoint): 프로그램 실행 중 특정 지점에서 중지하여 변수 값을 확인하고, 코드의 흐름을 추적할 수 있습니다.
  • 단계별 실행(Step Over/Into/Out): 코드를 한 줄씩 실행하거나, 함수 내로 들어가거나 빠져나오는 등의 제어를 할 수 있습니다.
  • 워치(Watch): 특정 변수의 값을 모니터링하고, 그 변수가 어떻게 변하는지 추적합니다.
  • 로컬 변수 창: 현재 스코프 내의 모든 변수를 모니터링하고, 그 값을 실시간으로 확인할 수 있습니다.

중단점 설정

Visual Studio에서 중단점을 설정하려면 코드 왼쪽 줄 번호를 클릭하면 됩니다. 실행 중 해당 줄에 도달하면 프로그램이 일시 중단됩니다.

8. 실습 예제: 예외 처리와 디버깅

다음은 사용자 입력을 받아 나누기 연산을 수행하고, 예외 처리 및 디버깅 기능을 사용하는 예제입니다.

using System;

class Program
{
    static void Main(string[] args)
    {
        try
        {
            Console.Write("첫 번째 숫자를 입력하세요: ");
            int num1 = Convert.ToInt32(Console.ReadLine());

            Console.Write("두 번째 숫자를 입력하세요: ");
            int num2 = Convert.ToInt32(Console.ReadLine());

            int result = Divide(num1, num2);
            Console.WriteLine($"결과: {result}");
        }
        catch (FormatException ex)
        {
            Console.WriteLine("숫자가 아닌 값을 입력했습니다. " + ex.Message);
        }
        catch (DivideByZeroException ex)
        {
            Console.WriteLine("0으로 나눌 수 없습니다. " + ex.Message);
        }
        finally
        {
            Console.WriteLine("프로그램이 종료됩니다.");
        }
    }

    static int Divide(int a, int b)
    {
        return a / b;
    }
}
  1. FormatException: 사용자가 숫자가 아닌 값을 입력했을 때 처리.
  2. DivideByZeroException: 0으로 나누려 할 때 처리.
  3. finally: 예외와 상관없이 항상 프로그램 종료 메시지 출력.

9. 디버깅 실습

  1. 중단점 설정: Divide 메서드가 호출되는 줄에 중단점을 설정합니다.
  2. 단계별 실행: 디버깅 모드에서 프로그램을 한 줄씩 실행하여 Divide 메서드의 입력 값과 결과를 추적합니다.
  3. 변수 확인: 로컬 변수 창 또는 워치를 사용해 a와 b 변수의 값을 실시간으로 확인합니다.

10. 요약

  • try-catch-finally 구문을 사용하여 프로그램의 예외를 안전하게 처리할 수 있습니다.
  • throw 키워드를 사용하여 명시적으로 예외를 발생시키거나 사용자 정의 예외를 던질 수 있습니다.
  • 디버깅은 코드의 오류를 찾고 수정하는 중요한 과정으로, 중단점과 변수 추적 등을 통해 프로그램 흐름을 분석할 수 있습니다.

다음 편에서는 C#에서 **파일 입출력(IO)**을 다루며, 파일을 읽고 쓰는 방법에 대해 학습하겠습니다.

728x90