removeDuplicates는 연속으로 중복되는 값을 필터링하는 오퍼레이터
동작 원리
upstream에서 값이 방출될 때마다 바로 이전 값과 비교해서, 같으면 무시하고 다르면 downstream으로 전달
[1, 1, 2, 2, 2, 3, 1, 1]
↓ removeDuplicates
[1, 2, 3, 1 ]
- 전체 중복이 아니라 연속 중복만 제거
- 위처럼 1이 다시 나와도 앞의 3과 다르면 통과
기본 사용법
- Element가 Equatable을 준수하면 아무 인자 없이 사용 가능
let values = [1, 1, 2, 2, 3, 3, 1].publisher
values
.removeDuplicates()
.sink { print($0) }
// 출력: 1, 2, 3, 1
커스텀 비교 조건
Equatable을 준수하지 않거나, 비교 기준을 직접 정의하고 싶을 때 클로저를 사용
struct User {
let id: Int
let name: String
}
let users: [User] = [
User(id: 1, name: "Alice"),
User(id: 1, name: "Alice Updated"), // id는 같음
User(id: 2, name: "Bob"),
]
users.publisher
.removeDuplicates(by: { $0.id == $1.id }) // id 기준으로 비교
.sink { print($0.name) }
// 출력: Alice, Bob ← "Alice Updated"는 id가 같아서 제거됨
SwiftUI + Combine
가장 흔한 사용처는 검색창 입력 처리
@Published var searchText: String = ""
$searchText
.debounce(for: .milliseconds(300), scheduler: RunLoop.main)
.removeDuplicates() // 같은 텍스트로 API 중복 호출 방지
.sink { query in
fetchSearchResults(query)
}
.store(in: &cancellables)
debounce 이후에 removeDuplicates를 두면, 타이핑 후 잠시 멈췄다가 지웠다가 다시 같은 텍스트로 돌아왔을 때의 중복 호출도 방지
debounce vs removeDuplicates 역할 비교
둘은 보완 관계라서 보통 같이 씀
| debounce | removeDuplicates | |
| 목적 | 마지막 이벤트 이후 일정 시간 대기 | 연속 중복 값 제거 |
| 기준 | 시간 | 값의 동등성 |
| 주로 쓰는 곳 | 타이핑 완료 감지 | 불필요한 상태 변화 방지 |
정리
- 연속된 동일 값을 downstream에 전달하지 않는 필터 오퍼레이터
- Equatable 준수 시 인자 없이, 아닐 경우 by: 클로저로 비교 조건 지정
- debounce와 함께 사용하면 네트워크 요청 최적화에 매우 효과적
'iOS > Combine' 카테고리의 다른 글
| [Combine] Future, Deferred (0) | 2026.03.12 |
|---|---|
| [Combine] .handleEvents (0) | 2026.03.12 |