“옵저버” = “관찰자”
옵저버 패턴은 객체의 상태변화를 관찰자들을 특정 객체에 등록하여 특정 객체의 상태변화가 있을 때마다 관찰자들에게 알려주는 디자인 패턴입니다.
Swift 5.1 부터 Combine 에서 Publisher를 추가하여 이 개념을 Language-level에서 지원하고 있습니다.
클래스 다이어그램을 먼저 보겠습니다.
옵저버 패턴은 변경사항을 수신하여 특정한 무언가 Task를 처리할 필요가 있을 때, 사용합니다.
좀 추상적이죠?
구체적으로 예시를 들면,
UITableview에서 셀을 생성하기 위해 특정 Array의 데이터의 count 값 만큼 cell을 생성한다고 가정합시다.
그러면 Array 데이터가 변경된다면, UITableview를 다시 그려야할 필요가 있겠죠.
이럴 때, 옵저버블 객체를 Array로 설정하여, 값이 변경될 때마다
tableview.reloadData()
를 실행하면 될겁니다.
옵저버 패턴은 MVC에서 주로 활용됩니다.
뷰컨트롤러는 구독자이고 모델은 발행자입니다.
이 관계로 인해서 모델과 뷰컨트롤러가 소통이 가능하죠.
아주 간단한 Combine을 활용해보겠습니다.
// 1 컴바인을 임포트한다.
import Combine
// 2 User 클래스를 정의한다.
public class User {
// 3 멤버변수를 정의한다.
@Published var name: String
// 4 초기화함수를 정의한다.
public init(name: String) {
self.name = name
}
}
3 번부분만 설명드리겠습니다.
직관적이죠. “@Published” 라는 프로퍼티래퍼가 있고 변수명은 “name” 입니다.
name의 값이 변경되면 update를 구독자에게 알릴 예정입니다.
당연히 업데이트 되기 위해서는 “let”으로 선언되어선 안되겠죠?
다음코드입니다.
// 1 "User" 인스턴스를 생성한다.
let user = User(name: "Ray")
// 2 발행자에 접근하여 값을 전달받는다.
let publisher = user.$name
// 3 구독자를 생성한다.
var subscriber: AnyCancellable? = publisher.sink() {
print("User's name is \($0)")
}
// 4 값을 업데이트한다.
user.name = "Vicki"
결과
User's name is Ray
User's name is Vicki
subscriber = nil
user.name = "Ray has left the building"
옵저버 패턴을 사용하기 전에 ‘어떤변화를 기대하는지’ 그리고 ‘어떤 조건에서 기대하는지’ 를 먼저 생각하고 사용해야합니다.
만약 그 이유에 대해서 명확하게 정의하지 못한다면, 사용하지 않는 것이 나을 수 있을겁니다.
(값이 변할때마다 로직이 동작할 텐데, 이것들이 쌓이기 시작하면 디버깅을어렵게 하곤합니다.)
Q. 옵저버 패턴은 무엇인가?
Q. 옵저버 패턴은 어떻게 구성되어 있는가
에 답할 수 있게 글을 작성했습니다.
읽어주셔서 감사합니다~!