먹고 기도하고 코딩하라

RxSwift의 observe(on:)과 DispatchQueue.main.async 언제 써야 할까 본문

앱/Swift

RxSwift의 observe(on:)과 DispatchQueue.main.async 언제 써야 할까

사과먹는사람 2023. 10. 14. 13:58
728x90
728x90

 

Observable 구독하는 클로저에서 이벤트가 발생하면 UI를 업데이트해주는 코드가 있었다.

그런데 observe를 메인 스레드가 아니라 다른 스레드에서 하고 있어서 이벤트를 받아 onNext 하면 메인 스레드가 아닌 데서 UI 조작한다고 앱이 강제종료되는 이슈가 생겼다.

.observe(on: MainScheduler.Instance)를 체이닝에 추가해서 메인 스레드에서 관찰하도록 변경해줌으로써 이슈는 해결했다.

그런데 문득 궁금해졌다. 그러니까, onNext에서 할 행동을 DispatchQueue.main.async { } 블록으로 감싸줘도 되는 게 아닌가? 이 둘은 퍼포먼스상으로 유의미한 차이가 있을까?

 

먼저 .observe(on: MainScheduler.Instance) 메소드부터 살펴보자.

.observe(on:)의 쓰임새는 특정 작업을 어떤 스레드에서 수행하게 함이다. Observable 시퀀스의 특정 부분이 특정 스레드에서 수행되게 하는 것이 그 목적인 것이다.

someObservable
	.observe(on: MainScheduler.Instance) // 이 밑으로 메인 스레드에서 작업을 수행한다.
	.subscribe { event in 
		switch event {
		case .next(let value):
			subtitleLabel.text = value
		case .error(let error):
			print(error.localizedDescription)
		default: break
		}
	}

이렇게 .observe(on:)을 걸었다면, subscribe 코드 전체가 메인 스레드에서 수행된다. 실상 메인 스레드에서 실행될 필요가 없는 코드들까지 메인 스레드에서 수행된다는 특징이 있다.

 

DispatchQueue.main.async는 메인 스레드에서 코드를 수행하는 좀 더 일반적인 방법이다. Rx 프로그래밍뿐 아니라 어느 코드에서도 사용할 수 있고, 블록 단위로 제어가 가능하다. 때문에 특정 코드만 메인 스레드에서 실행하도록 보장하고 싶다, 하면 그 부분만 블록으로 감싸면 된다.

someObservable
	.subscribe { event in 
		switch event {
		case .next(let value):
			DispatchQueue.main.async {
				subtitleLabel.text = value
			}
		case .error(let error):
			print(error.localizedDescription)
		default: break
		}
	}

정상적인 값 이벤트를 제외하고도 에러 등을 처리하는 것까지 메인 스레드에서 해야 하는가를 고려해서 선택하면 적합한 방법을 찾을 수 있을 것이다. 

728x90
반응형
Comments