백프레셔 관리는 주로 백엔드에서 하지만 Combine 프레임워크를 활용해서 iOS 단에서도 관리를 해줄 수 있다. 여기서 백프레셔란 서버로부터 날라오는 데이터 속도를, 컴바인으로 한정지으면 업스트림에서 날라오는 데이터 속도를 다운스트림의 처리속도가 따라가지 못해 발생하는 문제로 예시 상황으로는 아래와 같다.
- 비동기 데이터 로딩
iOS 앱에서 외부 API나 데이터베이스로부터 비동기적으로 대량의 데이터를 로드할 때, 네트워크 상태나 데이터베이스의 응답 속도에 따라 데이터가 너무 빨리 도착하면, 앱의 메인 스레드가 블록되거나 UI가 느려질 수 있다. - 이벤트 스트리밍
실시간으로 많은 양의 이벤트를 처리해야 하는 앱(예: 금융 앱에서의 주식 가격 업데이트, 스포츠 앱에서의 실시간 점수 업데이트)에서 데이터 스트림의 백프레셔를 관리하지 못하면 앱이 느려지거나, 최악의 경우 응답하지 않을 수 있다. - 대용량 파일 다운로드
사용자가 대용량 파일을 다운로드하거나 동영상을 스트리밍할 때, 네트워크 상태와 장치의 저장 공간 관리가 백프레셔 문제와 직접적으로 관련될 수 있다. 다운로드 속도가 장치의 저장 처리 속도를 초과하면 문제가 발생할 수 있다.
이러한 문제 상황이 발생할 경우 컴바인의 Subscribers.Demand (구독자가 퍼블리셔에게 요청 항목 수 조절) 을 통해 백프레셔를 관리해줄 수 있다.
// 예제 실행을 위한 함수
func example(of description: String, action: () -> Void) {
print("\n--- Example of:", description, "---")
action()
}
// 첫 번째 예제: 일반적인 sink 사용
example(of: "Backpressure Issue") {
let publisher = (1...10).publisher
let startTime = Date()
publisher
.sink(receiveCompletion: { completion in
let processTime = Date().timeIntervalSince(startTime)
print("Completed with: \(completion) after \(processTime) seconds")
}, receiveValue: { value in
let processTime = Date().timeIntervalSince(startTime)
print("Received value \(value) at \(processTime) seconds")
sleep(1) // 데이터 처리 시간
})
}
// 두 번째 예제: Subscriber를 사용한 백프레셔 관리
example(of: "Handling Backpressure with IntSubscriber") {
final class IntSubscriber: Subscriber {
typealias Input = Int
typealias Failure = Never
var startTime = Date()
func receive(subscription: Subscription) {
subscription.request(.max(1)) // 초기 데이터 요청
startTime = Date() // 시작 시간 초기화
}
func receive(_ input: Int) -> Subscribers.Demand {
let processTime = Date().timeIntervalSince(startTime)
print("Received value \(input) at \(processTime) seconds")
if input % 2 == 0 {
sleep(2) // 짝수일 때는 처리 시간을 더 길게
return .max(2) // 더 많은 데이터 요청
} else {
sleep(1) // 홀수일 때는 기존과 동일
return .max(1) // 기본 데이터 요청
}
}
func receive(completion: Subscribers.Completion<Never>) {
let processTime = Date().timeIntervalSince(startTime)
print("Completed with: \(completion) after \(processTime) seconds")
}
}
let publisher = (1...10).publisher
let subscriber = IntSubscriber()
publisher.subscribe(subscriber)
}
예제 코드에서는 일부러 sleep 을 실행시켜 인위적으로 처리 시간을 지연시켰다. 2초간 지연됨에도 1초간 데이터가 계속 날라오고 있기 때문에 BackPressure 관리를 위해 max(2)개씩 데이터를 요청함으로써 프론트단에서 부족한 속도를 보완해주었다.
https://www.kodeco.com/21773708-intermediate-combine/lessons/3
'Flutter' 카테고리의 다른 글
| Combine | 12. Retrying and Catching Errors (0) | 2024.05.15 |
---|---|
| Combine | 11. Mapping Errors (0) | 2024.05.14 |
| Combine | 9. Networking with Combine (0) | 2024.05.14 |
| Combine | 8. Sequencing Operators (0) | 2024.05.13 |
| Combine | 7. Scheduling Operators (0) | 2024.05.13 |