예외 및 예외 처리 프로세스 검사
- 11분
C# 애플리케이션의 런타임 오류는 예외라는 메커니즘을 사용하여 관리됩니다. 예외는 시스템 수준 및 애플리케이션 수준 오류 조건을 모두 처리하는 구조적이고 균일하며 형식이 안전한 방법을 제공합니다. 예외는 .NET 런타임 또는 애플리케이션의 코드에 의해 생성됩니다.
예외 처리가 필요한 일반적인 시나리오
예외 처리가 필요한 몇 가지 프로그래밍 시나리오가 있습니다. 이러한 시나리오 중 상당수에는 일종의 데이터 취득이 포함됩니다. 일부 시나리오에는 이 학습의 범위를 벗어난 코딩 기술이 포함되지만 여전히 주목할 가치가 있습니다.
예외 처리가 필요한 일반적인 시나리오는 다음과 같습니다.
사용자 입력: 코드에서 사용자 입력을 처리할 때 예외가 발생할 수 있습니다. 예를 들어 입력 값이 잘못된 형식이거나 범위를 벗어난 경우 예외가 발생합니다.
데이터 처리 및 계산: 코드에서 데이터 계산 또는 변환을 수행할 때 예외가 발생할 수 있습니다. 예를 들어 코드가 0으로 나누거나, 지원되지 않는 형식으로 캐스팅하거나, 범위를 벗어난 값을 할당하려고 할 때 예외가 발생합니다.
파일 입력/출력 작업: 코드가 파일에서 읽거나 파일에 쓸 때 예외가 발생할 수 있습니다. 예를 들어 파일이 없거나, 프로그램에 파일에 액세스할 수 있는 권한이 없거나, 파일이 다른 프로세스에서 사용 중일 때 예외가 발생합니다.
데이터베이스 작업: 코드가 데이터베이스와 상호 작용할 때 예외가 발생할 수 있습니다. 예를 들어 데이터베이스 연결이 끊어지거나 SQL 문에서 구문 오류가 발생하거나 제약 조건 위반이 발생할 때 예외가 발생합니다.
네트워크 통신: 코드가 네트워크를 통해 통신할 때 예외가 발생할 수 있습니다. 예를 들어 네트워크 연결이 끊어지거나, 시간 제한이 발생하거나, 원격 서버가 오류를 반환할 때 예외가 발생합니다.
기타 외부 리소스: 코드가 다른 외부 리소스와 통신할 때 예외가 발생할 수 있습니다. 웹 서비스, REST API 또는 타사 라이브러리는 다양한 이유로 예외를 throw할 수 있습니다. 예를 들어 네트워크 연결 문제, 잘못된 형식의 데이터 등으로 인해 예외가 발생합니다.
예외 처리 키워드, 코드 블록 및 패턴
C#의 예외 처리는 , catch및 finally 키워드를 try사용하여 구현됩니다. 이러한 각 키워드에는 연결된 코드 블록이 있으며 예외 처리 방법에서 특정 목표를 충족하는 데 사용할 수 있습니다. 다음은 그 예입니다.
try
{
// try code block - code that may generate an exception
}
catch
{
// catch code block - code to handle an exception
}
finally
{
// finally code block - code to clean up resources
}
비고
또한 C# 언어를 사용하면 코드에서 키워드를 사용하여 throw 예외 개체를 생성할 수 있습니다. 키워드를 사용하여 throw 예외를 생성하는 것을 포함하는 예외 처리 시나리오는 Microsoft Learn의 별도 모듈에서 다룹니다.
try 코드 블록에는 예외를 발생시킬 수 있는 보호된 코드가 포함됩니다. 블록 내의 코드에서 try 예외가 발생하면 해당 catch 블록에서 예외를 처리합니다.
catch 코드 블록에는 예외가 catch될 때 실행되는 코드가 포함됩니다. 블록은 catch 예외를 처리하거나, 기록하거나, 무시할 수 있습니다.
catch 예외 형식이 발생할 때 또는 특정 유형의 예외가 발생할 때만 실행되도록 블록을 구성할 수 있습니다.
코드 블록에는 finally 예외가 발생하는지 여부를 실행하는 코드가 포함되어 있습니다. 블록은 finally 블록에 할당된 try 모든 리소스를 정리하는 데 자주 사용됩니다. 예를 들어 변수에 올바른 값이나 필요한 값이 할당되었는지 확인합니다.
C# 애플리케이션의 예외 처리는 일반적으로 다음 패턴 중 하나 이상을 사용하여 구현됩니다.
- 패턴은
try-catch블록 뒤에 하나 이상의catch절로 구성try됩니다. 각catch블록은 다른 예외에 대한 처리기를 지정하는 데 사용됩니다. - 패턴은
try-finally블록 뒤에 블록으로finally구성됩니다try. 일반적으로 블록의 문은 컨트롤이finally문을 떠날try때 실행됩니다. - 이 패턴은
try-catch-finally세 가지 유형의 예외 처리 블록을 모두 구현합니다. 패턴의try-catch-finally일반적인 시나리오는 리소스를 가져와 블록에서try사용하고 예외적인 상황이 블록에서catch관리되고 리소스가 해제되거나 블록에서finally관리되는 경우입니다.
코드에서 예외는 어떻게 표현되는가?
예외는 코드에서 개체로 표현됩니다. 즉, 클래스의 인스턴스입니다. .NET 클래스 라이브러리는 다른 .NET 클래스와 마찬가지로 코드에서 액세스되는 예외 클래스를 제공합니다. 코드에서 개체로 사용되는 .NET 클래스의 또 다른 예는 클래스입니다 Random (난수를 만드는 데 사용됨).
보다 정확하게 말하면 예외는 형식이며, 궁극적으로 파생된 System.Exception클래스로 표시됩니다. 파생된 Exception 예외 클래스에는 예외 유형을 식별하고 예외에 대한 세부 정보를 제공하는 속성이 포함된 정보가 포함됩니다. 클래스에 대한 자세한 검사는 이 모듈의 Exception 뒷부분에 포함되어 있습니다.
클래스의 런타임 인스턴스는 일반적으로 개체라고 하므로 예외를 예외 개체라고도 합니다.
비고
서로 다른 용도로 사용되는 경우도 있지만 클래스와 개체는 서로 다릅니다. 클래스는 개체의 형식을 정의하지만 개체 자체가 아닙니다. 개체는 클래스를 기반으로 하는 구체적인 엔터티입니다.
예외 처리 프로세스
예외가 발생하면 .NET 런타임은 예외를 처리할 수 있는 가장 catch 가까운 절을 검색합니다. 이 프로세스는 예외를 throw한 메서드로 시작합니다. 먼저 예외를 발생시킨 코드가 코드 블록 내에 있는지 여부를 확인하기 위해 메서드를 try 검사합니다. 코드가 코드 블록 catch 내에 try 있으면 문과 try 연결된 절이 순서대로 고려됩니다. 절에서 catch 예외를 처리할 수 없는 경우 현재 메서드를 호출한 메서드가 검색됩니다. 이 메서드는 메서드 호출(첫 번째 메서드)이 코드 블록 내에 try 있는지 여부를 확인하기 위해 검사됩니다. 호출이 코드 블록 내에 있는 try 경우 연결된 catch 절이 고려됩니다. 이 검색 프로세스는 현재 예외를 catch 처리할 수 있는 절이 발견될 때까지 계속됩니다.
예외를 catch 처리할 수 있는 절이 발견되면 런타임은 블록의 catch 첫 번째 문으로 제어를 전송할 준비를 합니다. 그러나 블록 실행이 catch 시작되기 전에 런타임은 검색 중에 찾은 문과 try 연결된 모든 finally 블록을 실행합니다. 둘 finally 이상의 블록이 발견되면 예외가 throw된 코드에 가장 가까운 블록부터 시작하여 순서대로 실행됩니다.
예외를 처리하는 절이 없 catch 으면 런타임은 애플리케이션을 종료하고 사용자에게 오류 메시지를 표시합니다.
패턴 내에 중첩된 패턴을 포함하는 try-finally 다음 코드 샘플을 고려합니다.try-catch
try
{
// Step 1: code execution begins
try
{
// Step 2: an exception occurs here
}
finally
{
// Step 4: the system executes the finally code block associated with the try statement where the exception occurred
}
}
catch // Step 3: the system finds a catch clause that can handle the exception
{
// Step 5: the system transfers control to the first line of the catch code block
}
이 예제에서는 다음 프로세스가 발생합니다.
- 실행은 외부
try문의 코드 블록에서 시작됩니다. - 내부
try문의 코드 블록에서 예외가 throw됩니다. - 런타임은 외부
try문과 연결된 절을 찾catch습니다. - 런타임이 코드 블록의 첫 번째 줄로 컨트롤을
catch전송하기 전에 내부try문과 연결된 절을 실행합니다finally. - 그런 다음 런타임은 컨트롤을 코드 블록의
catch첫 번째 줄로 전송하고 예외를 처리하는 코드를 실행합니다.
이 간단한 예제에서는 중첩된 try-catch 패턴과 try-finally 패턴이 단일 메서드 내에 있지만 다른 메서드를 호출하는 메서드 간에 여러 try-catch 패턴이 try-finally 분산될 수 있습니다.
예외 처리 및 호출 스택
예외 처리 및 예외 처리 프로세스에 대해 읽을 때 종종 "호출 스택 해제"라는 용어가 표시됩니다. 이 용어를 이해하려면 호출 스택과 코드 실행 중에 메서드 호출의 "스택"을 추적하는 데 사용되는 방법을 이해해야 합니다.
호출 스택을 블록 타워처럼 생각할 수 있습니다. 타워를 빌드할 때는 한 블록으로 시작합니다. 타워에 블록을 추가할 때마다 기존 블록 위에 배치합니다. 애플리케이션이 디버거에서 실행될 때 애플리케이션의 진입점은 호출 스택(타워의 첫 번째 블록)에 추가된 첫 번째 계층입니다. 메서드가 다른 메서드를 호출할 때마다 새 메서드가 스택의 맨 위에 추가됩니다. 코드가 메서드에서 종료되면 메서드가 호출 스택에서 제거됩니다.
비고
콘솔 애플리케이션의 경우 애플리케이션의 진입점은 최상위 문입니다. Visual Studio Code 호출 스택에서 이 진입점을 메서드라고 Main 합니다.
호출 스택 해제는 C# 프로그램에서 오류가 발생할 때 .NET 런타임에서 사용하는 프로세스입니다. 방금 검토한 프로세스와 동일합니다.
블록 타워 비유로 돌아가서 타워에서 블록을 제거해야 할 때 맨 위에서 시작하여 필요한 블록에 도달할 때까지 각 블록을 제거합니다. 이 프로세스는 스택의 각 호출 계층이 타워의 블록과 같은 호출 스택 해제가 작동하는 방식과 유사합니다. 런타임이 호출 스택을 해제해야 하는 경우 맨 위에서 시작하여 필요한 항목이 있는 호출 계층에 도달할 때까지 각 호출 계층을 제거합니다. 이 경우 필요한 호출 계층은 발생한 예외를 처리할 수 있는 catch 절이 있는 메서드입니다.
요약
이 단원에서 기억해야 하는 몇 가지 중요한 사항은 다음과 같습니다.
- 예외 처리가 필요할 수 있는 일반적인 시나리오에는 사용자 입력, 데이터 처리, 파일 I/O 작업, 데이터베이스 작업 및 네트워크 통신이 포함됩니다.
- C#의 예외 처리는 ,
catch및finally키워드를 사용하여try구현됩니다. 각 키워드에는 특정 용도로 사용되는 연결된 코드 블록이 있습니다. - 예외는 형식으로 표시되고 .NET의
System.Exception클래스에서 파생됩니다. 예외에는 예외 유형을 식별하는 정보와 추가 세부 정보를 제공하는 속성이 포함됩니다. - 예외가 발생하면 .NET 런타임은 이를 처리할 수 있는 가장
catch가까운 절을 검색합니다. 검색은 예외가 throw된 메서드로 시작하고 필요한 경우 호출 스택 아래로 이동합니다.