옵저버!! 너... 관음증 있니?

Plato·2022년 7월 24일
0
post-thumbnail

TL;DR: 옵저버 패턴은, 여러 객체가, 특정 상태의 변화에 관심을 가져야 할 때, 유용한 패턴이다.

서론

옵저버 패턴과 프록시 패턴을 사용하여, 전역 상태를 관리하는 프로젝트를 최근에 수행햇다. 이를 구현하기 위해, 맨땅에 헤딩하며 해당 패턴들을 학습했다. 나의 맨땅 헤딩 경험이, 독자분들에게도 도움이 되길 바라며, 옵저버 패턴을 살펴보자.

본론

옵저버 패턴

옵저버 패턴은, 특정 데이터가 변할 때 마다, 반응해야 하는 객체들이 여럿 있을 때, 유용한 패턴이다. 예시로, 전역 상태를 관리할 때 사용할 수 있다. 전역 상태는, 모든 컴포넌트가 접근할 수 있고, 의존할 수 있기 때문에, 전역 상태가 변경될 때마다, 여러 컴포넌트가 변경되기도 한다. 도대체 옵저버 패턴이 무엇이길래, 이런 상황에 유용한 걸까?

옵저버 패턴은, 전역 상태를 담는 주체 객체, 그리고 상태 변화를 관찰하는 관찰 객체로 구성된다. 주체 객체는, 보통 등록(register)과 제거(unregister) 메소드를 갖는다. 이는 구독과 구독 해제와 비슷하다. 주체 객체의 상태에 관심 있는 객체를 등록할 수 있고, 더 이상 해당 객체가 해당 상태에 관심이 없다면, 해제할 수도 있다.

주체 객체의 상태에 변화가 생기면, 주체 객체가, 관찰 객체에 알린다. 이때 일반적으로, 관찰 객체의 특정 메소드를 실행시키는 방식으로, 알린다. 예시를 통해 살펴보자.

class Store {
  // 전역 상태를 관리하는 클래스
  constructor (states = new Map()) {
    this._observers = new Map()
    this._states = states
  }
  
  setState(state) {
    this._states.set(state.key, state.value)
    this.notify(state)
  }

  subscribe (state, observer) {
    if (this._observers.get(state) === undefined) {
      this._observers.set(state, [observer])
    } else this._observers.get(state).push(observer))
  }

  notify (state) {
    if (this._observers.size === 0) return
    const observersArr = this._observers.get(state)
    observersArr.forEach((observer) => observer())
  }
}

Store.subscribe(observerObject)

여기서 this._observers는 옵저버 객체의 메소드를 저장하는 맵이다. 당연히, 옵저버 객체의 모든 메소드를 저장하지는 않는다. 위에서 설명했듯이, 상태 변화가 생겼을 때, 실행시켜야 하는 메소드를 저장한다. this._states는 주체 객체가 관리하는 상태를, 저장하는 맵이다. subscribe는 위에서 설명한 등록 함수이다.

이때, 주체 객체의 상태는, 무조건 주체 객체의 setState 메소드를 통해 변경된다. setState 메소드를 살펴보면, 상태를 변경한 후, notify 메소드를 실행하는 것을 확인할 수 있다. notify 메소드는, 주체 객체의 _observers에 접근하여, 해당 상태에 구독 중인 옵저버 객체의 메소드를 실행시킨다.

이처럼 옵저버 패턴을 사용하면, 상태가 변경될 때마다, 해당 상태에 관심 있는 객체의 메소드를 실행시킴으로써, 상태 변화에 대응할 수 있도록 돕는다. 이렇게 하면, 상태를 변경시켰을 때, 어떤 코드를 실행시켜서 상태 변화에 대응할지, 상태를 변경시키는 코드가 신경 쓰지 않아도 된다. 또한 상태에 관심 있는 객체들도, 상태의 변화를 어떻게 알아낼지 고민하지 않아도 된다. 상태 값이 변하는 순간, 주체 객체가 알아서, 옵저버 객체의 메소드를 실행 시켜주기 때문이다.

마무리

이번 글에서는, gof(4인방)의 24가지 디자인 패턴 중, 옵저버 패턴을 살펴봤다. 소프트웨어 개발을 공부하면서, 상태가 변할 때, 상태의 변화에 자동으로 대응하는 패턴이 항상 궁금했었다. 이전에는, 주기적으로 상태 값을 체크하는 방법밖에 떠오르지 않았는데, 이 방법은 너무 낭비가 심할 것이 분명하기 때문이다. 이번 프로젝트를 진행하면서, 옵저버 패턴을 학습하며 무척 즐거웠다. 이 글을 읽을 사람이 한 명이라도 있을지 모르겠지만, 독자분들에게도 도움이 됐길 바라며, 이만 물러가 본다.

0개의 댓글