Swift 예외 처리 기술 배우기: try, catch, throws 사용 방법
Swift 예외 처리 기술 배우기: try, catch, throws 사용 방법
Swift는 안전하고 간결한 예외 처리를 위해 try
, catch
, throws
키워드를 제공합니다. 이 글에서는 이 키워드들이 어떤 역할을 하고, 어떻게 활용할 수 있는지에 대해 살펴보겠습니다. 먼저 예외 처리의 기본 개념을 살펴보고, 다양한 사용 사례를 통해 이해를 깊이도록 하겠습니다.
예외 처리 기본 개념
Swift에서는 함수나 메서드가 오류를 발생시킬 수 있는 경우 이를 명시적으로 선언하고 처리할 수 있습니다. 예외 처리는 주로 함수의 정상적인 흐름을 방해할 수 있는 예외 상황을 처리하는데 사용됩니다. 이를 통해 예기치 못한 오류로 인해 프로그램이 중단되는 것을 방지할 수 있습니다.
Swift에서 예외 처리를 하기 위해서는 세 가지 주요 키워드를 사용합니다:
throws
: 함수가 오류를 던질 수 있음을 표시합니다.try
: 오류가 발생할 수 있는 코드 앞에 사용합니다.catch
: 던져진 오류를 처리합니다.
throws
키워드
throws
키워드는 함수나 메서드가 오류를 던질 수 있음을 나타냅니다. 이는 함수 선언부에서 사용하는데, 함수의 반환 타입 뒤에 throws
키워드를 추가합니다. 예를 들어, 다음은 파일을 읽는 과정에서 오류가 발생할 수 있는 함수를 정의한 것입니다:
swiftfunc readFile(at path: String) throws -> String { // 파일을 읽는 코드 }
이 함수는 파일 경로를 입력으로 받아 파일 내용을 문자열로 반환하려고 하지만, 파일이 존재하지 않거나 읽기 권한이 없는 등의 상황에서 오류를 던질 수 있습니다.
try
키워드
try
키워드는 오류를 던질 수 있는 함수를 호출할 때 사용됩니다. try
키워드는 오류가 발생할 수 있는 코드 블록 앞에 위치하여 예외 처리를 위한 준비가 되었음을 나타냅니다. 예를 들어, readFile
함수를 사용하는 코드에서 다음과 같이 사용할 수 있습니다:
swiftlet filePath = "path/to/file.txt" let fileContent: String do { fileContent = try readFile(at: filePath) } catch { print("파일을 읽는 도중 오류 발생: \(error)") }
여기서 try
키워드는 readFile
함수가 오류를 던질 수 있다는 것을 명시합니다. 실제로 오류가 발생하면 catch
블록으로 제어가 이동합니다.
do-catch
구문
do-catch
구문은 오류 처리의 핵심 구성 요소입니다. do
블록 내에서 오류가 발생할 수 있는 코드를 실행하고, catch
블록 내에서 발생한 오류를 처리합니다. 예를 들어, 다음은 파일을 읽는 예제입니다:
swiftfunc readFileContents() { let filePath = "path/to/file.txt" do { let content = try readFile(at: filePath) print(content) } catch let error as FileError { switch error { case .notFound: print("파일을 찾을 수 없습니다.") case .noPermission: print("파일을 읽을 권한이 없습니다.") default: print("알 수 없는 오류가 발생했습니다: \(error)") } } catch { print("기타 오류 발생: \(error)") } }
여기서는 여러 종류의 오류를 처리하기 위해 catch
블록 안에 오류 타입을 명시적으로 구분하여 처리하고 있습니다. 이는 오류의 종류에 따라 적절한 대응을 할 수 있도록 도와줍니다.
rethrows
키워드
rethrows
키워드는 함수가 인자로 받은 클로저가 오류를 던질 경우, 해당 오류를 다시 던질 수 있음을 나타냅니다. rethrows
키워드는 주로 고차 함수(high-order function)에서 사용됩니다. 예를 들어, 다음은 오류를 던질 수 있는 클로저를 인자로 받는 함수입니다:
swiftfunc performOperation(with closure: () throws -> Void) rethrows { try closure() }
이 함수는 closure
가 오류를 던질 경우, 이를 다시 호출자에게 던질 수 있습니다. 이렇게 하면 오류 처리 로직을 재사용 가능하게 작성할 수 있습니다.
실제 사용 사례
파일 처리
파일 시스템과 상호작용할 때는 다양한 예외 상황이 발생할 수 있습니다. 파일이 존재하지 않거나, 파일을 읽을 권한이 없거나, 파일 읽기/쓰기 중 오류가 발생할 수 있습니다. 아래는 파일을 읽는 예제입니다:
swiftenum FileError: Error { case notFound case noPermission } func readFile(at path: String) throws -> String { // 실제 파일 읽기 코드 (예외 처리를 위해 단순화됨) guard path == "valid/path" else { throw FileError.notFound } return "파일 내용" } let filePath = "valid/path" do { let content = try readFile(at: filePath) print(content) } catch FileError.notFound { print("파일을 찾을 수 없습니다.") } catch FileError.noPermission { print("파일을 읽을 권한이 없습니다.") } catch { print("알 수 없는 오류가 발생했습니다: \(error)") }
네트워크 요청
네트워크 작업도 많은 예외 상황을 포함합니다. 예를 들어, 서버가 응답하지 않거나, 네트워크 연결이 끊기거나, 데이터가 사용할 수 없는 형식일 수 있습니다. 다음은 네트워크 요청의 예제입니다:
swiftenum NetworkError: Error { case badURL case requestFailed case unknown } func fetchData(from urlString: String) throws -> Data { guard let url = URL(string: urlString) else { throw NetworkError.badURL } // 실제 네트워크 요청 코드 단순화됨 guard let data = Data(base64Encoded: "response data") else { throw NetworkError.requestFailed } return data } let urlString = "http://valid.url" do { let data = try fetchData(from: urlString) print("데이터 받음: \(data)") } catch NetworkError.badURL { print("잘못된 URL입니다.") } catch NetworkError.requestFailed { print("네트워크 요청에 실패했습니다.") } catch { print("알 수 없는 오류가 발생했습니다: \(error)") }
결론
Swift의 예외 처리 시스템은 매우 강력하면서도 간결하게 사용할 수 있습니다. try
, catch
, throws
, rethrows
키워드를 이용하여 오류를 명확하게 처리할 수 있습니다. 이를 통해 코드의 신뢰성을 높이고, 예외 상황에서도 안정적으로 동작하는 애플리케이션을 만들 수 있습니다. 이러한 예외 처리 기술을 제대로 이해하고 활용하면, 더욱 견고한 Swift 애플리케이션을 개발할 수 있을 것입니다.