-
TCA - DebouncingTCA 2022. 10. 17. 14:42
안녕하세요. 그린입니다🍏
이번 포스팅에서는 TCA의 Debouncing에 대해 학습해보겠습니다🙌
Debounce?
Debouncing이라는건 우선 뭘 뜻하는 걸까요?
예전에 제가 Rx를 공부하면서 Debounce와 Throttle을 포스팅한 적이 있습니다.
https://green1229.tistory.com/m/178자세히 보실 분들은 이 포스팅을 선행으로 참고하셔도 좋을것 같아요!
간략하게 Debounce에 대한 요약을 해보자면 타이머를 설정하고 더 이상의 이벤트 방출이 없는 시간 간격이 해당 타이머의 시간일 경우 마지막 들어온 이벤트를 방출하도록 하는 메서드입니다.
사실상 무수히 많고 잦은 이벤트 방출을 막을 수 있는 목적이 가장 클 수 있기에 자동완성 혹은 연관검색어 기능에서 자주 활용됩니다.
이유는 마지막 들어온 이벤트만 방출하지 않고 계속 이벤트를 방출시킨다면 과부하가 걸릴 수 있기 딱 좋아서 일거에요🤪
그럼 Debounce에 대해 아 이런 개념이구나 알아봤으니 TCA에서는 어떻게 소개되고 사용되는지 알아보시죠!
TCA에서의 Debouncing 정의
TCA에서도 위의 동일 역할로 사용됩니다.
Effect 타입에서 사용하는 메서드죠.
즉, Effect를 Debounce할 수 있는 Effect 타입으로 변경해줍니다.
해당 메서드 사용을 위해서는 Hashable한 id 식별자를 이용해줍니다.
아래 TCA에서의 debounce 메서드 정의 구현을 볼까요?extension Effect { public func debounce<S: Scheduler>( id: AnyHashable, for dueTime: S.SchedulerTimeType.Stride, scheduler: S, options: S.SchedulerOptions? = nil ) -> Self { switch self.operation { case .none: return .none case .publisher, .run: return Self( operation: .publisher( Just(()) .setFailureType(to: Failure.self) .delay(for: dueTime, scheduler: scheduler, options: options) .flatMap { self.publisher.receive(on: scheduler) } .eraseToAnyPublisher() ) ) .cancellable(id: id, cancelInFlight: true) } } public func debounce<S: Scheduler>( id: Any.Type, for dueTime: S.SchedulerTimeType.Stride, scheduler: S, options: S.SchedulerOptions? = nil ) -> Self { self.debounce(id: ObjectIdentifier(id), for: dueTime, scheduler: scheduler, options: options) } }
기본적으로 위의 debounce 구현으로 이뤄져있습니다.
보시면 파라미터로 Hashable한 식별자 id와 얼마나 지연시킬지에 대한 dueTime을 받습니다.
그리고 어느 스케쥴러에서 돌아갈지와 어떤 스케쥴 옵션을 사용할지를 기본 파라미터로 받아요.
내부 구현을 보시면 Combine의 Just를 이용하고 delay 메서드를 이용합니다.
즉 단순 지연을 시켜주는 구현 그 자체입니다.
아래 메서드는 id 식별자를 Hashable한 값을 넘겨주지 않을때 위 메서드를 호출하여 만들어주게 됩니다.
결국 구현은 동일합니다.
이로써 우리는 TCA에서 debounce가 Effect 실행에 지연을 걸어줌을 확인할 수 있습니다.그럼 이 debounce 메서드를 우리는 TCA의 Effect에서 어떻게 사용하는지 구현해보겠습니다🕺🏻
TCA에서의 Debouncing 사용 구현
import ComposableArchitecture // 리듀서 구현부 ... struct SearchID: Hashable {} ... case let .textChanged(text): return environment.search(text) .debounce(id: SearchID(), for: 0.5, scheduler: environment.mainQueue) .map(Action.searchResponse) ...
위 리듀서 구현부를 보시죠.
우선 SearchID라는 Hashable한 구조체를 정의합니다.
그리고 textChanged라는 액션이 실행될때 사이드이펙트 단에서 search라는 동작을 수행해줍니다.
즉 텍스트를 받아 검색해주는것이죠.
그런데 계속 바뀌는 텍스트에 대해 검색하면 과부하가 올 수 있으니 0.5초라는 지정된 텀을 체크할 수 있는 타이머를 걸어주고 싶어요.
앞서 말했던 자동완성 기능 혹은 연관 검색어 탐색 기능의 역할을 하는 액션인것 같습니다.
debounce 메서드를 사용해 식별할 수 있는 Hashable한 SearchID 인스턴스를 넣어줍니다.
for은 dueTime의 레이블로 0.5초를 지정해줘요.
스케쥴링은 메인 큐에서 동작하도록 합니다.
그 다음 debounce된 Effect를 searchResponse 내부 액션에 맵핑해줍니다.
요러면 실제적인 동작은 타이핑을 계속 하더라도 0.5초 텀이 없으면 방출되지 않고 해당 텀을 만나면 걸려 있는 동안의 들어온 text는 무시될것이고 그 후 마지막 타이핑 된 텍스트를 가지고 search 해줍니다.
마무리
자 이렇게 TCA에서 디바운스를 거는 방법에 대해 알아봤습니다!
디바운스 개념을 처음 들어보면 난해할 수 도 있지만 알고 계셨던 개념이라면 TCA라고 다를것 없이 간단한 구현으로 구성된걸 확인할 수 있습니다🙌
[참고자료]
'TCA' 카테고리의 다른 글
TCA - concatenate & merge (여러 Effect를 단일 Effect로 만들기) (2) 2022.10.25 TCA - Throttling (2) 2022.10.20 TCA - Timer (2) 2022.10.13 TCA - IfLetStore (0) 2022.10.11 TCA - Debugging (2) 2022.10.06