.store(in: ) 와 .eraseToAnyPubliser()

한담곰·2026년 1월 22일

쏘의 Swift_Study

목록 보기
14/15

(뭔가... 비슷하다는 느낌이 들어서 차이점이 궁금했습니다)

.store(in: &cancellables) 랑 .eraseToAnyPublisher() 의 차이점

.store(in:) = 구독 생명주기 관리 (메모리/취소 관리)
.eraseToAnyPublisher() = 타입 숨기기 (인터페이스 정리/설계용)

(1) .store(in: &cancellables) - 이 구독을 언제까지 살려둘 것인가?

역할: Combine 구독을 메모리에 유지하고, 나중에 자동으로 취소되게 관리하는 용도
Combine에서 pusliber.sink {...} 를 호출하면 구독 객체 (AnyCancellable)가 생성됨. 이것을 어디에도 저장하지 않으면 -> 바로 메모리에서 해제되고 -> 네트워크 요청 / 스트림 즉시 취소됩니다. 그래서 반드시 저장해야 합니다.

.store(in: &cancellables)는 이 구독을 cancellabes에 저장해 두고, ViewModel이 살아 있는 동안 유지하고, ViewModel이 해제되면 자동으로 cancel 해 줘라는 뜻입니다.

  • 생명주기 관리: ViewModel이 살아 있을 때만 구독 유지
  • 메모리 누수 방지: deinit 시 자동 취소
  • 네트워크 중단 방지: 요청이 중간에 끊기지 않게 함

만약 안 쓴다면?

hospitalNetwork.getHospitalList()
    .sink { ... }   // ❌ store 안 함

sink 실행되자마자 cancellable 바로 해제 -> 네트워크 요청 거의 즉시 취소 -> 값 안 옴 / completion 안 옴 / 이상한 버그 발생

(2) .eraseToAnyPublisher() - 구현 타입 숨기기 (인터페이스 정리)

이건 메모리랑 전혀 상관없고, 설계 / 타입 추상화용입니다.

URLSession.DataTaskPublisher
    .tryMap { ... }
    .decode(...)
    .map(...)

이 함수의 실제 반환 타입은:

Publishers.Map<
  Publishers.Decode<
    Publishers.TryMap<
      URLSession.DataTaskPublisher, Data
    >,
    HospitalAPIResponse
  >,
  [Hospital]
>

이걸 함수 시그니처에 쓰면: 읽기/수정불가능 + 외부 코드 전부 깨짐
그래서 타입 지우기를 하는 것입니다. .eraseToAnyPublisher()
이 Publisher의 내부 타입은 숨시고, 그냥 AnyPublisher<[Hospital], URLError>로만 보이게 하자" 하는 것입니다.

정리하자면, 둘은 목적과 역할이 완전히 다릅니다.

  • .eraseToAnyPublisher()는 반환 타입을 숨기기 위한 설계용 도구 (인터페이스 안정성)
  • .store(in:)은 구독을 유지하고 메모리 누수를 막기 위한 생명 주기 관리 도구 (메모리 안정성)
profile
iOS Developer

0개의 댓글