챗봇을 개발하면서 예외, 오류 처리 등 이용자 경험에 필수적으로 포함되어야 하는 부분에 대해 구현하기 위해 일단 발생할 수 있는 상황을 정리해 에러 핸들링을 나열하고 이 핸들링을 통해 특정 상황에 맞는 Toast 메세지를 날려주는 로직을 구현하려고 한다!
먼저 최대한 기능별 모듈화를 통해 프로젝트를 쪼개 구현하고 있기 때문에 에러 핸들러 패키지를 만들어서 사용하는 방식을 사용해보자!
이 글에서는 대표적인 사례로 인터넷 연결이 끊겼을때 상황을 가정해 로직 구현을 해보려고 한다.
public enum NetworkError: Error { case networkError(code: Int, underlying: Error?) case noInternetConnection case yesInternetConnection case timeout case invalidResponse case unknown(underlying: Error?) public var localizedDescription: String { switch self { case .networkError(let code, _): return "네트워크 오류가 발생했습니다. 오류 코드: \\(code)" case .noInternetConnection: return "인터넷 연결이 없습니다." case .yesInternetConnection: return "인터넷 연결되었습니다." case .timeout: return "네트워크 요청 시간이 초과되었습니다." case .invalidResponse: return "잘못된 응답을 받았습니다." case .unknown: return "알 수 없는 네트워크 오류가 발생했습니다." } } }
각 상황 별로 네트워크 연결 관련 상황을 바탕으로 enum을 통해 해당 내용을 리스트업한 다음 해당 내용을 가져가 토스트 메세지에 localizedDescription을 각 상황에 맞게 넣어줄 수 있도록 하려고 한다.
그 다음 토스트 메세지를 호출하는 로직을 프로토콜을 활용해 추상화 한다.
public protocol ToastNotifying { @MainActor func showToast(message: String) }
MainActor를 활용해 UI 업데이트와 관련 된 해당 로직이 안정적으로 메인 스레드에서 실행됨을 보장할 수 있도록 했다.
public func showToast(message: String) { withAnimation(.spring(response: 0.3)) { toastMessage = message } DispatchQueue.main.asyncAfter(deadline: .now() + 2.5) { [weak self] in withAnimation(.easeOut(duration: 0.2)) { self?.toastMessage = nil } } }
그 다음 Toast메세지가 등장한 다음 2.5 초 뒤 사라질 수 있도록 해당 로직을 넣어주면 토스트 메세지에 대한 로직 구현이 쉽게 완료된다.
검색해보니 앱을 사용하면서 네트워크가 연결되어있는지 여부를 추적할 수 있는 방법은 NWPathMonitor를 활용해 연결 상태 변화를 감지하는 방법이 있는 것 같아 이 방법으로 한번 적용해보려고 한다.
공식문서를 확인해보니 NWPathMonitor 내 pathUpdateHandler를 활용하면 현재 단말기의 네트워크 상태 값을 전달 받을 수 있다고 한다!

이를 바탕으로 상태에 맞게 메세지를 전달해보자
private let monitor: NWPathMonitor private let queue = DispatchQueue(label: "NetworkMonitorQueue") @Published public var isConnected: Bool = true private init() { monitor = NWPathMonitor() monitor.pathUpdateHandler = { [weak self] path in let newStatus = (path.status == .satisfied) Task { @MainActor [weak self] in guard let self = self else { return } if self.isConnected != newStatus { self.isConnected = newStatus if newStatus { await ErrorHandler.shared.toastNotifier.showToast(message: NetworkError.yesInternetConnection.localizedDescription) } else { await ErrorHandler.shared.toastNotifier.showToast(message: NetworkError.noInternetConnection.localizedDescription) } } } } } public func startMonitoring() { monitor.start(queue: queue) } public func stopMonitoring() { monitor.cancel() }
별도의 Queue를 활용해 네트워크 모니터링 업무를 수행하도록 맞춰주게 되면 현재 상태를 전달받으면서 각 상황에 맞는 메세지를 넣어주면 이렇게 각각 상황에 맞는 메세지를 넣을 수 있게 된다.
이 내용을 바탕으로 앱단으로 넘어가 앱 델리게이트 내
class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { Task { @MainActor in NetworkMonitor.shared.startMonitoring() } return true } }
네트워크 모니터링을 시작할 수 있도록 전역으로 선언해주면 이제 앱에서 네트워크 상태를 감지하고 해당 값을 통해 토스트 메세지가 정상적으로 뜰 수 있게 된다. ( 원하는 뷰에 선언만 해주면 됨 )
토스트 메세지를 통해 해당 앱의 오류 상태를 이용자에게 전달할 수 있게 됐지만 일단 할 수 있도록만 구현해보았고 조금 더 효율적으로 구현할 수 있는 방법에 대해서 확인해보고 적용해 내용을 추가해야겠다!
'◽️ Programming > iOS' 카테고리의 다른 글
Tuist Scaffold로 모듈 생성 자동화 하기 + 외부 Dependencies 추가하기 (0) | 2025.04.22 |
---|---|
Tuist를 활용해 TMA 구조 설계하기 (0) | 2025.04.14 |
Static Dispatch, Dynamic Dispatch (2/2) (0) | 2025.03.04 |
Static Dispatch & Dynamic Dispatch (1/2) (0) | 2025.02.28 |
Sendable에 대해서 알아보자 (0) | 2025.02.24 |