본문 바로가기
iOS/Combine

[Combine] .removeDuplicates()

by Bokoo14 2026. 3. 11.

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