Swift Error Handling
안녕하세요. 개발자 AboutTech입니다. 이번 포스팅에서는 스위프트 언어를 사용한 아이폰 앱 개발에서 에러를 어떻게 처리할 수 있는지 알아보도록 하겠습니다. 모든게 완벽한 코딩이라면 에러가 발생할 일도 없을 것입니다. 하지만 현실에서는 앱을 사용하던 중에 네트워크가 꺼질 수도 있고, 사용자가 예상치 못한 지점에서 앱이 정상작동하지 않는 경우가 무수히 많습니다.
개발자도 사용자도 예상하지 못한 에러가 발생했을 때 예기치 못한 심각한 오류로 사용자 경험이 훼손되지 않게 하기 위해서는 적절한 그리고 우아한 에러 처리가 필수입니다. 아이폰 앱 개발에 사용되는 스위프트에서는 에러 핸들링 작업을 위해 guard, defer, do-catch, 그리고 throwing method 기능을 제공하면서 한결 쉽게 에러 핸들링을 할 수 있도록 지원하고 있습니다.
Throwing vs Catching
Swift 언어에서 에러를 처리하는 방법은 크게 2가지로 구분됩니다. 먼저 함수 내에서 에러가 발생한 경우 에러를 인위적으로 발생시키는 Throwing이 첫번째 입니다. 에러를 던지는 경우에는 Error 프로토콜을 준수하는 값으로 다음 로직을 처리할 수 있는 코딩이 필요하겠죠?
두번째 에러 핸들링 방법은 실제로 에러가 되었을 때 에러를 Catching 하는 방법입니다. 이 때 사용하는 키워드가 do - catch 문입니다.
Error 만들기
앱에서 에러가 발생하는 가장 흔한 상황은 인터넷 연결이 원활하지 못한 엘레베이터나 지하철에서 핸드폰을 사용하는 경우입니다. 이 때 다운로드를 하던 중 인터넷이 끊기게 되면 파일 전송이 완료되지 못하는 경우가 생깁니다. 만약 파일이나 동영상이 스트리밍 파이프라인으로 들어오다가 인터넷이 끊기면 전체 파일이 전송되지 못했기 때문에 이에 대한 로직을 구성해줘야 합니다.
먼저 파일 전송 에러가 발생했을 때의 상황을 열거형 enum으로 구현합니다. 파일이 없는 경우 부터 연결이 끊어졌을 때 까지 다양한 상황을 열거형으로 구성합니다.
enum FileTransferError: Error {
case fileNotFound
case permissionDenied
case connectionLost
case fileCorrupted
}
이제 함수 내에서 에러가 발생하는 경우 에러를 던져야(throwing) 합니다. 에러를 던지는 함수를 제작합니다. 함수 내에서 에러를 던지기 위해서는 if - else 분기문을 처리했을 때 보다 guard 구문을 사용하는 것이 빠르고 편리합니다.
func simulateFileTransfer(connectionExists: Bool) throws {
// 연결이 끊겨서 에러가 나는 경우
guard connectionExists else {
throw FileTransferError.connectionLost
}
// 에러가 나오지 않았을 때 정상 코드
}
마지막으로 에러를 던지는 함수에서 에러가 발생했을 때 던진 에러를 잡아주는 Catching 구문을 완성합니다. 이 때 에러 메서드를 던질 수도 있는 함수를 호출할 때는 try 키워드를 사용해주셔야 합니다.
func handleFileTransfer() {
do {
try simulateFileTransfer(connectionExists: true)
print("File transfer successful.")
} catch FileTransferError.connectionLost {
print("Connection lost during file transfer.")
} catch {
print("An unexpected error occurred: \(error)")
}
}
마지막 catch 문은 catch all의 의미를 가지고 있습니다. 즉 앞선 에러를 모두 처리하지 못하는 예외 상황의 예외 상황이 나올 경우에 마지막까지 에러를 처리할 수 있는 구문입니다.
에러를 catching 할 때 do-catch 구문을 사용할 필요 없이 절대로 에러가 발생하지 않는다고 고려되는 에러 쓰로잉 메서드를 사용하는 경우에는 (!) 마크를 사용해 에러 캐칭을 비활성화할 수 있습니다. 하지만 모든 에러를 100% 예상하기는 불가능하기 때문에 가급적 사용하지 않는 것을 권장드립니다.
func handleFileTransfer() {
try! simulateFileTransfer(connectionExists: true)
}
let error로 에러 객체에 접근하기
catch 문에서 에러 객체에 직접적으로 접근하기 위해서는 let error로 상수로 에러 객체를 사용할수도 있습니다.
func handleFileTransfer() {
do {
try simulateFileTransfer(connectionExists: true)
print("File transfer successful.")
} catch let error as FileTransferError {
switch error {
case .fileNotFound:
print("File not found: \(error.localizedDescription)")
case .permissionDenied:
print("Permission denied: \(error.localizedDescription)")
case .connectionLost:
print("Connection lost during file transfer: \(error.localizedDescription)")
case .fileCorrupted:
print("File corrupted: \(error.localizedDescription)")
}
} catch {
print("An unexpected error occurred: \(error.localizedDescription)")
}
}
defer 구문으로 에러 캐칭 유예하는 방법
Swift에서 에러 처리는 try, do-catch로 간단하게 처리할 수 있습니다. 다만 에러 처리를 하는 catching 과정에서 특수한 로직을 처리하고 제어권을 반환하기 위해서 defer 구문을 처리할 수 있습니다. 예를 들어 인터넷 연결이 끊어졌을 때 불완전한 파일을 삭제하는 로직이 필요할 수 있습니다.
func handleFileTransfer() {
defer {
print("임시 파일을 제거합니다.)
}
do {
try simulateFileTransfer(connectionExists: true)
print("File transfer successful.")
} catch let error as FileTransferError {
switch error {
case .fileNotFound:
print("File not found: \(error.localizedDescription)")
case .permissionDenied:
print("Permission denied: \(error.localizedDescription)")
case .connectionLost:
print("Connection lost during file transfer: \(error.localizedDescription)")
case .fileCorrupted:
print("File corrupted: \(error.localizedDescription)")
}
} catch {
print("An unexpected error occurred: \(error.localizedDescription)")
}
}
이번 포스팅에서는 Swift 에러처리하는 방법에 대해 알아보았습니다. 항상 자신의 코드가 완벽하게 구현될 것이라는 자부심을 가지는 것 보다는 예외 상황을 처리하고 유저가 겪게 되는 상황을 예상하고, 피드백을 받아 발생된 에러를 예외처리하는 습관을 가지도록 합시다.
🚀️ 도움이 되셨다면 구독과 좋아요 부탁드립니다 👍️
'Programming > Swift' 카테고리의 다른 글
[iOS Swift] SwiftUI란? UIkit vs SwiftUI 비교 (0) | 2024.01.16 |
---|---|
[iOS Swift5] 프로퍼티 래퍼 Property Wrapper? (0) | 2024.01.13 |
[iOS Swift5] Collection, 배열과 딕셔너리, Set 기본 (2) | 2024.01.11 |
[iOS Swift5] 열거형 구조체 기본 기초 (0) | 2024.01.10 |
[iOS Swift5] 객체지향 프로그래밍 기초 클래스 프로토콜 익스텐션 (0) | 2024.01.09 |
댓글