-
Notifications
You must be signed in to change notification settings - Fork 0
신규 URLSession API #5
Copy link
Copy link
Open
Labels
Description
기존 방식
URLSession은 completion handler(콜백) 기반- 결과와 에러를 모두
@escaping클로저로 전달 → 가독성 낮음 dataTask메서드를 통해 작업을 만들고,resume()호출 -> 실행 순서 파악이 어려움
func fetchUser(completion: @escaping (User?, Error?) -> Void) {
let url = URL(string: "https://dummy.example.com/ ..")!
let task = URLSession.shared.dataTask(with: url) { data, response, error in
if let error = error {
completion(nil, error)
return
}
guard let data = data,
let user = try? JSONDecoder().decode(User.self, from: data) else {
completion(nil, URLError(.badServerResponse))
return
}
completion(user, nil)
}
task.resume()
}
// 호출
fetchUser { user, error in
if let user = user {
print(user)
}
}Concurrency 방식 (async/await 기반)
- 함수가 결과 값을
(Data, URLResponse)타입 형태의 튜플로 반환 try await로 에러와 중단 지점 표현 → 코드가 동기처럼 순차적으로 읽힘@escaping클로저가 불필요하여, 캡쳐를 신경쓰지 않아도 됨
func fetchData() async throws {
let url = URL(string: "https://dummy.example.com/ ..")!
// 1) 비동기 호출 → 값 직접 반환
let (data, response) = try await URLSession.shared.data(from: url)
// 2) 응답 확인
guard (response as? HTTPURLResponse)?.statusCode == 200 else {
throw URLError(.badServerResponse)
}
// 3) 결과 사용
let text = String(data: data, encoding: .utf8)
print(text ?? "")
}
// 호출
Task {
do {
try await fetchData()
} catch {
print(error.localizedDescription)
}
}data(from:) 기본 메서드
(Data, URLResponse)튜플을 반환try await로 호출 → 순차적 코드처럼 작성 가능
func fetchUser() async -> User? {
let url = URL(string: "https://dummy.example.com/ ..")!
do {
let (data, response) = try await URLSession.shared.data(from: url)
guard (response as? HTTPURLResponse)?.statusCode == 200 else { return nil }
return try JSONDecoder().decode(User.self, from: data)
} catch {
return nil
}
}에러 처리 (async throws)
- 함수 자체가 에러를 던질 수 있음
- 호출 시
try await필요
func fetchUser() async throws -> User {
let url = URL(string: "https://dummy.example.com/ ..")!
let (data, response) = try await URLSession.shared.data(from: url)
guard (response as? HTTPURLResponse)?.statusCode == 200 else {
throw URLError(.badServerResponse)
}
return try JSONDecoder().decode(User.self, from: data)
}실제 비동기 함수 호출 (Task 내부에서 호출)
- 비동기 함수는 반드시
Task같은 비동기 컨텍스트 안에서 호출 - UI 업데이트는
await MainActor.run사용
class ViewModel: ObservableObject {
@Published var user: User?
func fetchUser() {
Task {
let user = try await NetworkService().fetchUser()
// UI 업데이트: 메인 액터 hop
await MainActor.run {
self.user = user
}
}
}
}Reactions are currently unavailable