RxSwift - Subject

Seoyoung Lee·2023년 10월 27일
0

RxSwift

목록 보기
3/5
post-thumbnail

Subject란?

Subject는 Observable이자 Observer이다.

이벤트를 받으면 그 이벤트를 다시 구독자들에게 전달하는 역할을 한다.

→ 값을 방출할 수 있을 뿐 아니라 Observe도 가능하다!!

Subject에는 Publish Subject, Behavior Subject, Replay Subject, BehaviorRelay등 다양한 종류가 있다.

[RxSwift] Subject의 종류

Publish Subject 써보기

let subject = PublishSubject<String>()

subject.onNext("Issue 1")

subject.subscribe { event in
    print(event)
}

subject.onNext("Issue 2")
subject.onNext("Issue 3")

subject.dispose()

subject.onCompleted()

subject.onNext("Issue 4")
// 실행 결과
next(Issue 2)
next(Issue 3)

Publish Subject는 초깃값 없이 생성되고, 구독한 이후 방출되는 이벤트만 전달받는다.

  • onNext() 메소드를 사용해서 값을 방출한다.
  • Issue1은 subscribe를 하기 전 방출되었기 때문에 이벤트가 출력되지 않는다.
  • dispose() 메소드를 호출한 후에 호출된 메소드들의 결과는 적용되지 않는다.
  • dispose() 를 호출하지 않고 onCompleted() 만 호출하면 completed가 출력된다.

Behavior Subject

Behavior Subject는 Publish Subject와 비슷하다. 대신 초기화를 할 때 초깃값을 전달해주어야 한다. 구독을 하면 가장 최신 이벤트를 전달받는다.

let disposeBag = DisposeBag()

let subject = BehaviorSubject(value: "Initial Value")

subject.onNext("Last Issue")

subject.subscribe { event in
    print(event)
}

subject.onNext("Issue 1")
// 실행 결과
next(Last Issue)
next(Issue 1)

초깃값을 설정한 후 방출된 최신 값이 Last Issue 이므로 Last Issue를 방출하고, 그 다음 Issue 1 이 방출되었기 때문에 Issue 1도 출력된다.

Replay Subject

설정한 버퍼 크기만큼의 이벤트를 저장하고, Observer가 구독을 시작하면 버퍼에 있는 모든 이벤트를 전달한다.

let subject = ReplaySubject<String>.create(bufferSize: 2)

subject.onNext("Issue 1")
subject.onNext("Issue 2")
subject.onNext("Issue 3")

subject.subscribe {
    print($0)
}
// 실행 결과
next(Issue 2)
next(Issue 3)

버퍼 크기를 2로 설정했기 때문에 가장 마지막으로 방출된 두 개의 이벤트가 전달된 것을 볼 수 있다.

let subject = ReplaySubject<String>.create(bufferSize: 2)

subject.onNext("Issue 1")
subject.onNext("Issue 2")
subject.onNext("Issue 3")

subject.subscribe {
    print($0)
}

subject.onNext("Issue 4")
subject.onNext("Issue 5")
subject.onNext("Issue 6")

print("[Subscription 2]")
subject.subscribe {
    print($0)
}

첫 번째 subscribe 밑에 3개의 이벤트와 새로운 subscribe 메소드를 하나 추가하고 코드를 실행시키면 아래와 같은 실행결과가 나온다.

next(Issue 2)
next(Issue 3)
next(Issue 4)
next(Issue 5)
next(Issue 6)
[Subscription 2]
next(Issue 5)
next(Issue 6)

두 번째 subscription은 가장 마지막에 방출된 이벤트인 Issue5와 Issue6을 출력한다.

Variable (*deprecated)

Variable은 behavior subject를 감싸고 있으며, 현재 값의 상태를 저장한다. 이 값은 value 프로퍼티를 사용해서 접근할 수 있다.

let variable = Variable("Initial Value")

variable.value = "Hello world"

variable.asObservable()
	.subscribe {
		print($0)
}

// next(Hello World)

Variable은 RxSwift에서 공식적으로 deprecated되었다고 한다 😱 대신 BehaviorRelayBehaviorSubject 를 사용해야 한다. (참고: What’s New in RxSwift5)

Behavior Relay

BehaviorRelay는 RxCocoa 를 import해야 사용할 수 있다.

let relay = BehaviorRelay(value: "Initial Value")

relay.asObservable()
    .subscribe {
        print($0)
    }

relay.value = "Hello World" // Error!

relay.accept("Hello World")

BehaviorRelay의 value 는 읽기 전용이기 때문에 값을 직접 수정할 수 없다. 대신 accept() 라는 메소드를 사용해서 새 값을 넣어줄 수 있다.

// 실행 결과
next(Initial Value)
next(Hello World)

BehaviorRelay의 값이 배열이라면 나중에 값을 어떻게 변경해줄 수 있을까?

let relay = BehaviorRelay(value: ["Item 1"])

// 방법 1
var value = relay.value
value.append("Item 2")
value.append("Item 3")

relay.accept(value)

// 방법 2
relay.accept(relay.value + ["Item 2", "Item 3"])

relay.asObservable()
    .subscribe {
        print($0)
    }

value 의 값을 직접 변경해줄 수 없기 때문에 새 변수에 값을 담아서 append 하거나 value 에 저장된 배열과 새 값들을 저장한 배열을 합쳐서 accept 해주는 식으로 저장해주어야 한다.

next(["Item 1", "Item 2", "Item 3"])

BehaviorRelay는 UI에서 사용하기 좋도록 변형된 Subject라고 한다. 더 자세한 차이점 및 사용 방법은 나중에 공부해야 할 듯!

profile
나의 내일은 파래 🐳

0개의 댓글