안녕하세요, 매들린입니다!
제가 지난 토요일 'let us go' iOS 컨퍼런스에 다녀왔는데요,
특히 감명받았던 곰튀김님의 스피치를 듣고, 제가 이해하고 적용한 내용을 공유해보고자 합니다!
(곰튀김님의 스피치를 듣고 쓰는 글이지만, 제 피셜로 작성해서, 틀린 내용은 언제든지 피드백 부탁드립니다🙏🏻)
우선 Swift에서의 Exception, 그러니까 예외는 Error이다.
이 에러를 어떻게 처리하느냐가 예외를 처리하는 것과 일맥상통한다고 볼 수 있겠다.
특히, 예외라는 건.. 예측할 수 없는 것들이기에, 개발 과정에서 예외 처리를 다양한 경우에 대해 해두는 것이 좋다. 그리고 에러를 어떻게 관리하느냐는 우리가 만드는 서비스의 질을 결정할 수 있다.
하여튼 Swift에서 예외처리를 사용자 친화적으로 다루는 방법에 대해 이야기해보고자 한다.
특히, 네트워크 연결 문제와 같이, 사용자가 직접 해결할 수 없는 문제에 대해 어떻게 더 나은 경험을 제공할 수 있을지에 대해 말해보자.
이는 에러를 발생시킬 수 있는 코드를 'try'로 실행하고,
'catch' 블록에서 에러를 잡아 처리하는 구조이다.
이렇게 코드의 흐름을 명확하게 유지하면서, 예외 처리를 도와준다.
func fetchDataFromServer() throws {
// 여기서 에러가 발생할 수 있는 코드
}
do {
try fetchDataFromServer()
} catch {
print("데이터를 가져오는 중 오류가 발생했습니다.")
}
-> 서버에서 데이터를 가져오는 함수가 에러를 던질 경우, 그 에러를 잡아내고 콘솔에 메시지를 출력한다.
그리고 네트워크 연결 오류를 처리할 때, 보통 사용하는 방법을 코드로 나타내보겠다.
enum NetworkError: Error {
case disconnected
case timeout
}
func fetchData() throws {
// 네트워크 연결 상태를 체크하는 가상의 코드
let isConnected = false
if !isConnected {
throw NetworkError.disconnected
}
}
do {
try fetchData()
} catch NetworkError.disconnected {
print("네트워크 연결이 끊겼습니다.")
} catch {
print("알 수 없는 오류가 발생했습니다.")
}
앱에서 네트워크 오류가 발생했다고 생각해보자. 수많은 경우의 네트워크 오류는 아무리 자세히, 쉽게 설명해도 유저가 굳이 알 필요가 없다.
내가 한게 올바른 주소인지, 접근 권한이 없는지, 알 수 없는 오류가 발생했는지, .. 이런 구체적인 상황보다는 유저 입장에서 "그래서 내가 뭐 어떻게 해야하는데?"를 알려주는 것이 더 중요하다.
네트워크 에러가 나서, 그래서 유저는 어떤 조치를 취해야 하는지, 그 다음 액션을 잘 안내해주는 것이 좋겠다.
우리는 UserFriendlyError라는 커스텀 에러 프로토콜을 만들어 사용할 수 있다. 이 프로토콜은 Error, CustomStringConvertible, LocalizedError를 준수하며, 사용자에게 보여줄 메시지를 더 친근하게 제공할 수 있도록 한다.
예를 들어, 네트워크 연결이 끊겼을 때 사용자에게 다음과 같은 메시지를 제공할 수 있다: "인터넷 연결이 원활하지 않습니다. 연결 상태를 확인하고 다시 시도해주세요."
이 프로토콜을 채택하면, 에러에 대한 설명(errorDescription)을 제공할 수 있다. 이를 통해 개발자는 에러를 더 세분화하여, 발생 가능한 다양한 시나리오를 고려한 메시지를 정의할 수 있다. 또한, do-catch 구문 내에서 여러 catch 블록을 사용하여 다양한 에러 유형에 대해 다른 처리를 할 수 있다.
LocalizedError는 사용자에게 직접 보여주기 위한 것이 아니라, 개발자가 에러를 더 잘 이해하고 처리할 수 있도록 돕는 것이다. 하지만, 이를 통해 사용자 친화적인 메시지로 변환하는 것이 중요하다.
enum NetworkError: Error, LocalizedError {
case disconnected
case timeout
var errorDescription: String? {
switch self {
case .disconnected:
return "인터넷 연결이 끊겼습니다. 연결 상태를 확인해주세요."
case .timeout:
return "요청 시간이 초과되었습니다. 나중에 다시 시도해주세요."
}
}
}
func fetchData() throws {
let isConnected = false
if !isConnected {
throw NetworkError.disconnected
}
}
do {
try fetchData()
} catch let error as LocalizedError {
print(error.errorDescription ?? "알 수 없는 오류가 발생했습니다.")
}
CustomStringConvertible 프로토콜은 타입에 대한 사용자 정의 설명을 제공할 수 있게 해주는 스위프트의 기본 프로토콜이다. 이를 구현함으로써 인스턴스를 문자열로 변환할 때 원하는 형태로 출력을 정의할 수 있습니다. 이는 로깅이나 디버깅 때 매우 유용하게 사용된다.
아래는 NetworkError 열거형에 CustomStringConvertible을 적용한 예시이다. 이를 통해 에러 메시지를 보다 상세하게 제공하면서, 개발자가 문제를 더 쉽게 이해하고 디버깅할 수 있도록 돕는다.
enum NetworkError: Error, LocalizedError, CustomStringConvertible {
case disconnected
case timeout
// LocalizedError 프로토콜 구현
var errorDescription: String? {
switch self {
case .disconnected:
return "인터넷 연결이 끊겼습니다. 연결 상태를 확인해주세요."
case .timeout:
return "요청 시간이 초과되었습니다. 나중에 다시 시도해주세요."
}
}
// CustomStringConvertible 프로토콜 구현
var description: String {
switch self {
case .disconnected:
return "NetworkError: 연결 끊김"
case .timeout:
return "NetworkError: 시간 초과"
}
}
}
func fetchData() throws {
let isConnected = false
if !isConnected {
throw NetworkError.disconnected
}
}
do {
try fetchData()
} catch let error as LocalizedError {
print(error.errorDescription ?? "알 수 없는 오류가 발생했습니다.")
print(error) // CustomStringConvertible을 통한 출력
}
이 코드에서 NetworkError는 LocalizedError와 CustomStringConvertible 두 프로토콜을 준수한다. errorDescription은 사용자에게 보여줄 오류 메시지에 사용되고,
description은 개발자가 로깅이나 디버깅을 할 때 보게 될 오류이다.
CustomStringConvertible의 description 프로퍼티를 통해, 에러를 문자열로 출력할 때 "NetworkError: 연결 끊김" 또는 "NetworkError: 시간 초과"와 같이 더 구체적인 정보를 제공할 수 있다.
이는 개발 과정에서 문제를 더 빠르게 진단하고 해결하는 데 도움을 줍니다.
스위프트에서의 예외 처리는 단순히 에러를 잡아내고 로깅하는 것 이상이다. 사용자에게 더 나은 경험을 제공하고, 개발자가 에러를 더 효율적으로 관리할 수 있도록 해보자!
네트워크 문제에 대한 예외 처리를 할 때도 이러한 베스트 프랙티스를 적용할 수 있다. 아래는 네트워크 문제를 예로 든 좋은 예외 처리 습관이다:
이렇게 구체적으로 문제를 설명해주면 사용자가 왜 네트워크 문제가 발생했는지 이해하고, 어떻게 해결해야 할지 알 수 있다.
사용자가 기술 용어를 몰라도 이해할 수 있도록, 보다 친절하고 일상적인 언어로 오류 메시지를 제공한다.
이렇게 로그를 남기면, 나중에 문제가 발생했을 때 원인을 더 빠르게 찾아내고 해결할 수 있다.
이런 습관을 네트워크 문제 처리에 적용하면, 사용자는 현재 상황을 더 잘 이해하고, 필요한 조치를 취할 수 있게 됩니다. 동시에 개발자는 문제 해결에 필요한 구체적인 정보를 로그에서 쉽게 찾아낼 수 있다. 이 모든 것이 앱의 안정성을 높이고, 사용자 경험을 개선하는 데 큰 도움이 된다.
잘봤습니당