[SwiftUI] Combine을 활용한 디바운싱(Debouncing) 처리

강치우·2024년 8월 20일
0

디바운싱(Debouncing)

오늘은 Combine에서 제공하는 디바운싱(Debouncing)에 대해 알아볼려고 합니다.

디바운싱이라는 걸 어떻게 알게됐냐하면, 유저 검색을 할 때 SwiftUI에서 기본으로 제공하는 .searchable을 사용하면서 생겼는데요.


SwiftUI에서 제공하는 메서드 중에서 searchable은 너무 좋은 기능 중 하나라고 생각합니다.

searchable 뷰 모디파이어만 사용해주면 서치 인터페이스를 만들어주는데, 여기에 간단한 필터링 로직 한스푼이면 바로 검색 기능이 만들어집니다.


근데 검색을 하면서 부터 문제점이 생깁니다.

위 사진은 영어로 검색했지만, searchable은 기본적으로 한글 검색을 시도할 때 자음 모음마다 리스트를 업데이트 해주면서 실시간으로 뷰를 재구성하는데, 여기서 빠르게 단어를 칠 때 마다 실시간 업데이트가 되면서 리스트가 과부화가 걸립니다.

이렇게 리스트가 과도하게 업데이트 되어서 빈 셀을 반환할 수도 있다는 에러 메세지가 출력됩니다.


그래서 검색 기능을 구현할 때, 사용자가 입력할 때마다 실시간으로 데이터를 검색하는 경우, 불필요한 API 호출을 최소화하는 것이 중요합니다.

예를 들어, 사용자가 검색어를 입력할 때마다 검색을 수행하면 너무 많은 API 호출이 발생하여 성능 저하나 서버 과부하가 발생할 수 있습니다.

이를 해결하기 위해 흔히 사용하는 방법이 “디바운싱(Debouncing)“입니다.


Debounce는 Combine 프레임워크에서 제공하는 연산자 중 하나로, 입력된 값 중에서 일정 시간 동안 변경이 없을 때에만 값을 방출합니다.

주로 사용자 입력과 같은 실시간 이벤트에서 유용하게 활용됩니다.

입력 값이 빈번하게 발생하는 경우, Debounce를 사용하여 값의 변동을 감지하고 일정 시간의 지연을 두어 최종 값을 처리할 수 있습니다.



Debounce 예시

import Combine

// 검색 입력을 처리하는 클래스
class SearchManager {
    let searchSubject = PassthroughSubject<String, Never>()
    
    func startSearching() {
        // 검색 입력 스트림에 Debounce 연산자 적용
        let debouncedPublisher = searchSubject
            .debounce(for: .seconds(0.5), scheduler: DispatchQueue.main)
        
        // 검색 결과를 처리하는 Subscriber 작성
        let subscriber = Subscribers.Sink<String, Never>(receiveValue: { query in
            // 실제 검색 요청 처리
            self.performSearch(with: query)
        })
        
        // Subscriber를 debouncedPublisher에 할당
        debouncedPublisher.subscribe(subscriber)
    }
    
    func performSearch(with query: String) {
        print("검색 요청: \(query)")
        // 실제 검색 요청 처리 로직 작성
    }
}

// 검색 입력을 테스트하는 코드
let searchManager = SearchManager()
searchManager.startSearching()

searchManager.searchSubject.send("a")
searchManager.searchSubject.send("ap")
searchManager.searchSubject.send("app")
searchManager.searchSubject.send("appl")
searchManager.searchSubject.send("apple")

위의 코드에서는 SearchManager 클래스를 사용하여 검색 입력을 처리하고, 입력 값을 Debounce 연산자를 적용한 후 검색 요청을 처리합니다.

입력 값이 연속적으로 발생하더라도 일정 시간의 지연을 두어 최종 검색어로 검색 요청을 처리합니다.

사용자가 TextField에 Text를 입력하고, 입력이 멈춘 후 0.5초 지난 후에 검색을 실행합니다.
사용자가 타이핑을 완료했을 때만 검색을 실행하려고 할 때 유용합니다.

Debounce는 지정된 시간 간격 동안 이벤트가 더 이상 발생하지 않을 때까지 기다립니다.
이 시간 동안 추가 이벤트가 발생하면 타이머를 리셋합니다.
즉, 연속된 이벤트 스트림에서 마지막 이벤트만을 전달합니다.


적용 결과

저 같은 경우에는 0.5초의 딜레이를 걸어줬더니 딱 업데이트 되는 정도가 적당했던거 같습니다.

ps. 딜레이는 0.3 ~ 0.5초 사이가 적당하다고 하네요.






레퍼런스
https://conandevdaily.tistory.com/19

profile
자허블을 좀 더 좋아하긴 합니다.

0개의 댓글