[iOS] URLSession 코드 비교 시리즈 03 : async/await

Emily·2025년 5월 22일
0

URLSession

목록 보기
3/3

이번엔 Swift Concurrency 문법을 사용한 코드로 네트워크 통신을 해볼 것이다. Swift Concurrency 문법이 궁금하다면 해당 내용을 정리한 포스팅을 참고하면 된다.

01) fetchTodos 메소드 정의

동시성 코드에서는 일 처리에 대한 결과를 기다릴 때 await를 사용하고, 에러를 발생시킬 때 throw 키워드를 사용한다.

func fetchTodos() async throws -> [Todo] {
    let urlString = "https://jsonplaceholder.typicode.com/todos"
    
    // 1. URL 유효성 체크
    guard let url = URL(string: urlString) else {
        throw CustomError.invalidURL
    }
    
    // 2. 네트워크 요청 : async 메소드인 data 사용
    let (data, response) = try await URLSession.shared.data(for: URLRequest(url: url))
    
    // 3. esponse를 HTTPURLResponse로 타입 캐스팅
    guard let response = response as? HTTPURLResponse else {
        throw CustomError.invalidResponse
    }
    
    // 4. 응답 코드 체크 (200번대여야 통신 성공)
    guard (200..<300).contains(response.statusCode) else {
        throw CustomError.badResponse(response.statusCode)
    }
    
    // 5. 디코딩
    do {
        let decodedData = try JSONDecoder().decode([Todo].self, from: data)
        return decodedData
    } catch {
        throw CustomError.decodingFailed
    }
}

02) 데이터 바인딩

UI와 데이터를 바인딩하는 작업은 메인 스레드에서 이루어져야 하는데, 이 작업에 대해 @MainActor를 선언해주면 해당 메소드가 메인 스레드에서 실행된다. 또, async 함수를 실행할 경우 Task 클로저를 통해 호출해야 한다.

class TodoViewController: UIViewController {
	override func viewDidLoad() {
    	// ... //
        Task {
        	await bind()
        }
    }
    
    // ... //
    
    @MainActor
    private func bind() async {
    	do {
        	let todos = try await viewModel.fetchTodos()
            todoTableView.reloadData(todos: todos)
        } catch let error as CustomError {	// 직접 정의한 에러가 발생했을 경우 처리
        	print(error.debugMessage)
        } catch let error {					// 커스텀 에러 이외의 상황에서의 에러 처리
        	print(CustomError.etc(error).debugMessage)
        }
    }
}

03) 오류 발생 시키기 01 - 요청 실패

completionHandler에서 에러 상황을 구체적으로 처리한 것과 달리 async 함수는 코드가 굉장히 짧아졌는데, 같은 에러 상황에서 디버그 메시지가 어떻게 출력되는지 보고 싶어서 테스트를 진행하였다. 맥미니 와이파이를 끄고 실행해보았다.

bind() 함수에서 CustomError.etc로 처리한 디버그 메시지가 출력된 것을 확인했다.

04) 오류 발생 시키기 02 - 응답 에러

urlString의 맨 뒤 글자를 지운 뒤 실행해보았다.

fetchTodos()에서 throwbadResponse의 디버그 메시지가 출력되었다.

profile
iOS Junior Developer

0개의 댓글