Combine으로 네트워크 통신

SteadySlower·2023년 4월 7일
0

iOS Development

목록 보기
14/38
post-custom-banner

dataTaskPublisher

URLSession.shared.dataTask(with: url, completionHandler: {  })

Combine을 사용하지 않고 URLSession을 사용하는 경우 보통 위 코드와 같은 메소드를 사용하는데요. 이는 비동기적으로 Request를 하고 받은 Response를 completionHandler에 전달합니다.

Combine을 사용하면 URLSession으로 Publisher를 만들 수 있습니다. 이 Publisher는 비동기적으로 Request를 하고 받은 response를 발행합니다.

// AnyPublisher<Data, URLError>
URLSession.shared.dataTaskPublisher(for: url).eraseToAnyPublisher()

decode

Combine에서는 네트워크 통신으로 받은 JSON을 struct로 디코딩 해주는 operator도 제공합니다. 이 경우 디코딩 에러가 발생할 수 있으므로 Publisher의 Error 타입을 정의할 때 URLError가 아니라 더 큰 타입인 Error를 정의해주어야 합니다.

struct SomeStruct: Codable {
		let someProperty: String
}

// AnyPublisher<[Post], Error>
URLSession.shared.dataTaskPublisher(for: url)
		.map { $0.data }
    .decode(type: SomeStruct.self, decoder: JSONDecoder())
    .eraseToAnyPublisher()

네트워크 통신을 받아 UI를 업데이트할 때

URLSession의 CompletionHandler 안에서 UI를 업데이트 하는 코드를 사용할 때 Main Thread에서 실행해야 하듯이 dataTaskPublisher 역시도 백그라운드에서 실행하기 때문에 UI를 업데이트하기 전에는 .receive(on: RunLoop.main)를 통해서 메인 쓰레드에서 실행해야 한다고 명시해주어야 합니다. 이렇게 하면 .sink를 사용해서 UI를 업데이트할 때 메인 쓰레드에서 실행하게 됩니다.

URLSession.shared.dataTaskPublisher(for: url)
		.map { $0.data }
    .decode(type: SomeStruct.self, decoder: JSONDecoder())
		.receive(on: RunLoop.main)
    .eraseToAnyPublisher()
profile
백과사전 보다 항해일지(혹은 표류일지)를 지향합니다.
post-custom-banner

0개의 댓글