버튼을 눌렀을 때 성격 급한 사람은 버튼을 연타하는 경우가 적지 않다. API 통신 시에 이걸 적절하게 처리하지 않으면 통신이 여러 번 일어나는 상황이 발생하기 쉽다. 단순 조회면 그냥 하면 그만이지만 회원가입 버튼 같은 거면 까다로운 상황에 직면한다.
만약 내가 회원가입 시 UUID를 생성하고 이걸로 유저를 구분한다고 하자 이 상황에서 가입 시 연타해서 UUID가 4개 생길 수도 있다. 그럼 UUID가 의미가 있나?
이를 방지하는 기능이 보통 throttle과 debounce이다.
debounce
특정 시간까지 기다려서 더 이상 입력이 없다면 마지막으로 발생한 이벤트를 전달한다.
button.rx.tap
.debounce(.milliseconds(500), scheduler: MainScheduler.instance)
.subscribe(onNext: { [weak self] in
self?.sendSignUpRequest()
})
.disposed(by: disposeBag)
검색창에 텍스트를 입력하는 상황이 적절한 예시가 되겠는데 만약 "RxSwfit 한 번에 이해하기"라는 문장을 검색한다고 하자. 사실 이건 검색창에 "R", "Rx", "RxS" 순으로 한 글자씩 추가로 넣어주는 행위이다. 버튼을 눌러줄 때까지 아무것도 안 하다가 검색 버튼을 누르면 완료된 글자를 보내는 방법도 존재한다. 하지만 유저가 입력하다가 멈추는 상황(입력 완료)에서 debounce를 사용하면 일정 시간(debounce time)을 기다렸다가 자동으로 문자열을 가지고 검색을 수행할 수 있다.
이때 마지막 이벤트 (결과물)을 전송하므로 효율적인 처리가 가능하다. 물론 처음에 언급했던 버튼에는 조금 안 맞는 해결법일 수 있다. 연타가 멈추는 순간에 회원 가입이 실제로 수행될 것이기 때문이다.
throttle
그럼 쓰로틀은 뭘까?
button.rx.tap
.throttle(.seconds(1), scheduler: MainScheduler.instance)
.subscribe(onNext: { [weak self] in
self?.sendSignUpRequest()
})
.disposed(by: disposeBag)
throttle은 일정 시간에서 스트림으로 주어지는 하나의 이벤트만 전달하는 것이다.
검색을 다시 예로 들면 1초에 한번 카운트해서 "R", "RxSwift", "RxSwfit 한 번에 이", "RxSwfit 한 번에 이해하기"와 같이 특정 주기마다 한 번씩 이벤트를 전달한다.
버튼의 경우 예를 들어 20초에 한 번만 시행되게 하면 UUID는 하나만 생기게 될 것이다. 그렇기 때문에 UX를 고려한다면 버튼의 경우에는 throttle을 쓰는 게 더 적절할 수 있다.
distinctUntilChanged
distinctUntilChanged는 연속된 중복 값을 필터링하는 역할을 한다. 왜 이걸 굳이 썼을까?
debounce를 쓰던, throttle을 쓰던 불필요한 행동을 막는 좋은 도구이기 때문이다. 이걸 쓰면 기존에 검색 결과가 그대로인 상황에서 유용하다.
버튼에 쓰는건 toggle 같은 제한적인 상황에서 쓰일 수는 있겠다. 글을 적다 보니 처음부터 검색 예시를 들걸 하는 생각이 든다.. ㅎ
'Swift > etc' 카테고리의 다른 글
| [Firebase] Database lives in a different region 에러 (0) | 2023.03.21 |
|---|---|
| [Swift] Kingfisher와 SDWebImage (0) | 2023.03.19 |
| [Swift] 함수의 매개변수(Parameter) 레이블 (0) | 2023.03.18 |
| [Xcode] 디버거에서 data 타입을 사람이 볼 수 있는 방식으로 변환하는 법 (0) | 2023.03.18 |
| [UIKit] init(frame:)과 init(coder:)은 어떤 차이가 있는가? (0) | 2023.03.16 |