디자인패턴

옵저버 패턴 (Observer Pattern)

fidget278 2022. 6. 14. 16:39

옵저버(관찰자) 패턴 정의

옵저버 패턴은 어떠한 주제가 있고, 해당 주제를 관찰하는 관찰자들로 이루어져 있다. 주제의 상태가 바뀌면 관찰자들에게 연락을 하게 되는 일대다(one-to-many, 1:N) 의존성의 디자인 패턴이다.  

ex) 유튜버와 구독자들의 관계.

유튜버가 영상을 등록하면, 구독자들은 알림을 받는다.

 

옵저버 패턴의 구현

하나의 주제(Subject)를 하나의 객체로 표현하고, 관찰자(Observer) 또한 객체로 구현한다. 따라서 Subject 객체의 상태가 변경되면 해당 Subject에 의존하는 모든 Observer 객체들에게 상태가 변경되었음을 알린다. 

 

출처 : https://ko.wikipedia.org/wiki/옵서버_패턴

Subject : 관찰 대상인 '주제' 객체로, 자신을 관찰하는 observer 객체들을 콜렉션으로 갖고 있다. observer 등록, 등록해지, 자신을 관찰하는 모든 observer에게 notify 하는 기능을 갖게 된다. 

Observer : 관찰하는 객체이다. 위 UML에서는 상속구조로 되어있지만, 인터페이스로 만들기도 한다. observer 객체들은 Subject가 notify()를 호출할 때마다 Subject 객체의 상태 변경을 수신하게 된다.

 

 

푸시(Push) 방식의 구현

Subject 객체에서 Observer 객체에게 notify를 할 때, 변경된 데이터를 함께 보내는 방식이다. 

notify 함수의 매개변수로 변경된 데이터가 들어간다. 

 

풀(Pull) 방식의 구현

Subject 객체로부터 notify를 받은 Observer 객체가 변경된 데이터를 직접 가져가는 방식이다. 

Observer 객체마다 관찰하는 데이터가 다를 경우 사용되는 방식이다. notify의 매개변수로 Subject 객체, 혹은 Subject 인터페이스를 받은 후 형변환을 통해 데이터를 빼간다. pull 방식의 구현에는 Subject에 getter 가 구현되어 있어야한다.

 

 

장단점

장점 :

1. 객체간의 관계를 인터페이스를 활용해 느슨한 결합 구조를 만들 수 있다. 

 - 느슨한 결합 구조로 인한 장점은 아래와 같다.

  •  Observer를 언제든 새로 추가, 제거할 수 있다.
  • 새로운 형식의 Observer라 해도 Subject는 변경될 필요가 없다.
  • Subject와 Observer는 서로 독립적으로 재사용할 수 있다.
  • Subject나 Object가 바뀌더라도 서로에게 영향을 미치지 않는다.

2. 한 객체(Subject)의 상태변화를 의존하는 객체(Observer)에서 자동으로 알 수 있다.

4. 런타임에 의존 관계를 생성하거나 삭제할 수 있다.

 

단점 :

1. 순서를 예측할 수 없다. 

Subject 내에서 Observer들을 순회하며 Notify 해주는데, 개별 Observer 입장에서는 자신이 호출되는 순서에 대해서 알 수 없다. 따라서 상태 변경에 따른 어떠한 행위를 할 때, 자신의 순서 앞에서 어떤 옵저버가 어떤 행위를 했는지 알 수가 없다.

 

2. Thread-safe 하지 않다. (스레드 안전 문제)

각각의 옵저버들이 호출하는 함수 체인 속에서 어떤 락을 잡고 있는지 알 수 없기에, 만약 A 옵저버가 a락을 잡고 b락을 잡으려고 하고, B 옵저버는 b락을 잡은 상태로 a락을 잡으려고 하고 있다면(a락을 잡아야 b락이 풀린다면) 터지게 된다.  

 

3. 너무 많이 사용하게 되면 상태 관리가 힘들어진다.

Subject가 너무 많은 상태를 갖고 있게 되면, Subject가 변경될 때마다 Observer들이 호출되는 수가 많아지고, 이에 따라 무언가 작업이 꼬였을 때 현재 상태가 올바른 상태인지에 대한 디버깅이 힘들어진다.

 

Reference

https://hamait.tistory.com/885

 

굿바이~ 옵저버 패턴 and FRP

문제 공유 우리는 오랫 동안 상호작용 되는 많은 부분에 있어서 옵저버패턴을 당연하듯 활용해 왔지만, 옵저버(관찰자, 소비자, 리스너) 패턴을 사용하다보면 경험 많은 개발자라면 누구나 "

hamait.tistory.com

https://im-yeobi.io/posts/design-pattern/observer-pattern/