I'm FanJae.

[20260518] C# ( Exception ) 본문

Unity/Unity 초격차캠프

[20260518] C# ( Exception )

FanJae 2026. 5. 18. 17:55

1. 정의

 

예외(Exception)는 프로그램 실행 중 발생하는 예상치 못한 오류 상황을 의미한다.

(1) 예시

- 잘못된 사용자 입력
- 파일이 존재하지 않음
- 네트워크 연결 끊김
- 배열 범위를 벗어난 접근
- null 객체 접근

- 위와 같은 상황이 발생했을 때 프로그램이 강제 종료되지 않도록 처리하는 것이 예외 처리(Exception Handling)이다.


2. 예외 처리가 필요한 이유

- 프로그램은 항상 개발자의 의도대로만 동작하지 않는다.

- 여러 가지 외부 요인 때문에 오류가 발생할 수 있다.

(1) 사용자 입력 오류

int number = int.Parse("abc");

- 숫자가 아닌 값을 입력하면 예외가 발생한다.

(2) 파일 관련 오류

public SaveData? Load() // 불러오기
{
    // 파일 없으면 null 리턴
    if (!File.Exists(SaveFilePath))
        return null;

    try
    {
        // 파일 전체 읽어옴
        string json = File.ReadAllText(SaveFilePath);
        return JsonSerializer.Deserialize<SaveData>(json);
    }
    catch (IOException) // 파일 입출력 자체 실패
    {
        return null;
    }
    catch (UnauthorizedAccessException) // 접근 권한 문제 
    {
        return null;
    }
    catch (JsonException) // 파싱 실패 
    {
        return null;
    }
}

- 프로젝트에서 파일을 불러올 때, 파일이 없으면, 읽는 작업을 하면 안된다.

(3) 네트워크 오류

- 서버 연결 실패나 인터넷 끊김 등이 있는 경우에 대한 처리가 필요하다.

(4) 하드웨어 / 시스템 문제

- 메모리 부족이나 장치 접근 실패 등에 대한 처리가 필요하다.


3. 예외 처리를 하지 않으면 발생하는 문제

namespace ExceptionExample
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("숫자를 입력하세요 : ");

            string input = Console.ReadLine();

            // 숫자가 아닌 값을 입력하면 예외 발생
            int number = int.Parse(input);

            Console.WriteLine($"입력한 숫자 : {number}");

            Console.WriteLine("프로그램 정상 종료");
        }
    }
}

- 예외처리를 해주지 않으면 오류가 뜨면서 강제 종료된다.

- 이렇게 되면 사용자에게 문제점이 무엇인지 알려주기가 어렵고, 프로그램 흐름이 중단된다.


4. 사용 예시

try
{
    // 예외가 발생할 가능성이 있는 코드
}
catch (예외 타입)
{
   // 예외 발생 시 실행
}
finally
{
   // 무조건 실행
}

(1) try

- 예외가 발생할 가능성이 있는 코드를 작성하는 영역이다.

try
{
   string dat = Console.ReadLine();
	 int value = int.Parse(dat);
}

- 위와 같이 예외가 발생할 수 있는 코드를 try에 넣어준다.

 

(2) catch

-try 안에서 예외가 발생하면, 그 예외 타입과 일치하는 catch 블록이 실행된다.

try
{
    string data = Console.ReadLine();
    int value = int.Parse(data);
}
catch (FormatException) // 숫자 형식 관련 Exception
{
    Console.WriteLine("숫자 형식이 아닙니다.");
}
catch (OverflowException) // 숫자 범위 관련 Exception
{
    Console.WriteLine("숫자 범위를 초과했습니다.");
}

(3) finally

finally
{
    Console.WriteLine("입력 처리를 종료합니다.");
}

- fianlly 에는 보통 반드시 실행되어야 하는 문장을 넣으면 된다.

- 예외 발생 여부와 관계 없이 반드시 실행되어야 하는 작업으로, 리소스 정리나 마무리 작업에 사용한다.

 

try
{
    file = File.Open("test.txt", FileMode.Open);
}
catch (FileNotFoundException)
{
    Console.WriteLine("파일이 존재하지 않습니다.");
}
finally
{
    if(file != null)
    {
        file.Close();
    }
}

5. 자주 발생하는 예외와 유의사항

(1) 컴파일러 생성 예외

- https://learn.microsoft.com/ko-kr/dotnet/csharp/fundamentals/exceptions/compiler-generated-exceptions

아래 예외들이 실행 중 발생할 수 있는 대표적인 예외이다.

- IndexOutOfRangeException - 배열 범위 초과
- DivideByZeroException - 0으로 나눔
- NullReferenceException - null 객체 접근
- InvalidCastException - 잘못된 형 변환
- OverflowException - 숫자 범위 초과
- StackOverflowException - 재귀 과다 호출
- OutOfMemoryException - 메모리 부족
- FileNotFoundException - 파일 없음

 


(2) 유의사항 1. 예외 처리보다 사전 검사가 좋은 경우가 있다.

- 모든 상황을 try-catch로 처리하는 것은 좋은 방식이 아니다.

- 간단한 경우 사전에 검사하는 것이 더 효율적이다.

① 이유

- 예외가 발생하지 않으면 부담이 크지 않지만, 예외가 실제로 발생하면 아래와 같은 작업이 일어나게 된다.

- 예외 객체의 생성
- 호출 스택 정보 수집
- 적절한 catch 탐색의 과정

- 따라서, 예상하기 어려운 비정상적인 상황에 대한 처리를 try, catch에 맡겨야 한다.

 

② 예시

(1) 사용자 입력 검증

try
{
    int number = int.Parse(input);
}
catch (FormatException)
{
    Console.WriteLine("숫자를 입력하세요.");
}

- 숫자 입력 여부는 예측 가능하다. 이는 TryParse로 처리하는게 좋다.

if (int.TryParse(input, out int number))
{
    Console.WriteLine(number);
}
else
{
    Console.WriteLine("숫자를 입력하세요.");
}

 

(2) 배열 인덱스 범위 검사

try
{
    Console.WriteLine(arr[index]);
}
catch (IndexOutOfRangeException)
{
    Console.WriteLine("잘못된 인덱스입니다.");
}
if (index >= 0 && index < arr.Length)
{
    Console.WriteLine(arr[index]);
}
else
{
    Console.WriteLine("잘못된 인덱스입니다.");
}

- 배열에서 잘못된 인덱스를 검증할 때 배열 범위 안에 있는지 미리 확인할 수 있는데, try,catch 보다 인덱스 값에 대한 if 처리가 낫다.

 

③ 外

NullReferenceException - if(player == null) 과 같은 null 체크
DivideByZeroException - if문으로 0으로 나눌 수 없음 처리

 


(3) 유의사항 2. catch로 해결 하면 안되는 예외

일부 예외는 발생한 시점에서 복구 가능한 상황이 아닐 수 있다.

- StackOverflowException , OutOfMemoryException 과 같은 예외가 발생한 경우, 해당 오류가 발생한 원인을 찾아야지 이를 catch로 잡는 식으로 해결하면 안된다.


6. Exception도 클래스다.

- C#에서 다뤄지는 모든 Exception 클래스는 Exception이라는 클래스를 상속 받고 있다.

public class Exception
{
    public string Message;    // 예외 원인 설명
    public string StackTrace; // 예외가 발생한 호출 흐름
}

(1) Message

catch(Exception ex)
{
    Console.WriteLine(ex.Message);
}

- Message는 무슨 문제가 발생했는지 확인할 때 사용할 수 있다.

 

(2) StackTrace

- StackTrace 는 예외가 발생하기까지 어떤 메서드를 거쳐왔는지 보여준다.

catch(Exception ex)
{
    Console.WriteLine(ex.StackTrace);
}

- 이를 통해서 어디서 문제가 발생했는지 찾을 때 사용할 수 있다.


7. Exception 사용시 주의점

(1) 빈 catch을 사용하지 않는다.

catch
{

}

- 사용하는 것 자체는 문제가 되지 않지만, 오류 원인을 알기 어렵다.

 

(2) Exception을 남용하지 않는다.

catch (Exception ex)
{

}

- 모든 예외를 Exception 하나로 처리하면, 디버깅 하기가 까다로워 진다.

(3) Exception은 흐름 제어 용도가 아니다.

- 예측 가능한 오류라면 사전 검사 작업으로 처리해야한다.


8. 정리

- 예외(Exception)은 실행 중 발생하는 비정상 상황이다.
- 예외 처리는 프로그램 비정상 종료를 막기 위해 사용한다.
- try-catch-finally 구조로 처리한다.
- finally는 예외 여부와 관계 없이 반드시 실행된다.
- 모든 예외는 Exception 클래스를 상속 받는다.
- Exception은 비용이 큰 작업으로, 간단한 상황은 예외 처리 보다 사전 검사가 더 효율적이다.

※ 즉, Exception은 예상하지 못한 상황을 처리할 때 사용할 수 있다.


 

'Unity > Unity 초격차캠프' 카테고리의 다른 글

[20260519] C# 정리 ( Lambda Expression )  (0) 2026.05.19
[20260518] Git 용어 정리  (0) 2026.05.18
[20260515] C# ( Event )  (0) 2026.05.15
[20260515] C# ( Func )  (0) 2026.05.15
[20260515] C# ( Action )  (0) 2026.05.15
Comments