옵저버 패턴은 일단 이번 포스트에서 카테고리를 Unity로 분류하긴 했는데 소프트웨어 분야에서 널리 쓰이는 디자인 패턴이므로 알아두는 것이 좋을 것 같아 Unity에서 옵저버 패턴을 구현하기 위해 카테고리를 Unity로 정했다
옵저버 패턴에 대해 알아보자. 관찰자 패턴, 발행-구독 모델이라고도 한다
옵저버란? 관찰자라는 뜻으로 무언가를 지켜보는 오브젝트를 의미한다. 소프트웨어에서 무언가는 어떤 이벤트를 의미하는데 뭐 사용자의 입력이 될 수 있고, 어떤 객체의 상태가 변할 수 있고 하니까 이런 이벤트들을 지켜본다
말 그대로, 관찰자의 관찰 대상이 되는 객체이다. 객체의 상태가 바뀌면 관찰자에게 이를 알려야한다
예를 들어 유튜브를 생각해보자
우리는 유튜브에서 어떤 채널에 있는 재미있는 동영상을 보는데 계속 보고 싶은 경우 구독을 해서 영상이 올라올 때마다 새 동영상 알림이 와서 볼 수 있는데 만약 재미없게 되어 구독을 해지하면 이제 알림이 오지 않는다
이와 비슷하게 유튜브 채널은 새로운 영상을 올리는 Subject, 발행자가 되고 우리는 구독을 해서 그 알림을 받는 Observer가 된다
그래서 옵저버 패턴은 1:1 또는 1:N의 관계를 가질 수 있어 주로 분산 이벤트 핸들링 시스템 구현에 사용된다
근데 예시만 보면 관찰자가 능동적으로 관찰 대상자를 선택하는 것 같아 보이지만 실제로 쓰임을 보면 관찰 대상자가 관찰자를 등록하는 수동적인 관계라 예시는 예시로만 기억하자
옵저버 패턴은 관찰 대상자와 관찰자로 나누어져 있어야 한다
관찰 대상자(Subject)에는 자신을 관찰할 관찰자(Observer)를 등록하고 해제하는 함수가 있어야 하고 또 등록한 관찰자들을 자료구조에 저장해야 한다. 어떤 이벤트가 발생하면 그 관찰자들에게 알려야 하니까
관찰자에는 어떤 이벤트를 받으면 호출할 함수를 정의해야 한다
이를 위해 관찰자, 관찰 대상자의 기본 메서드들을 인터페이스로 정의하고 특정 클래스에서 이를 상속받도록 한다
유튜버가 영상을 업로드하면 구독자가 그 알림을 받는 과정을 유니티로 구현해보자
먼저 Observer와 Subject의 인터페이스를 구현해보자
namespace ObserverPattern
{
public interface IObserver
{
void OnUpload(string channel);
}
public interface ISubject
{
void RegisterObserver(IObserver observer);
void RemoveObserver(IObserver observer);
void NotifyObservers();
}
}
위 인터페이스는 먼저 유튜버에 해당하는 Subject 인터페이스에는 구독자를 등록, 해제하는 함수와 영상을 업로드하면 NotifyObservers 메서드가 실행돼 구독자들에게 알림이 간다
구독자에 해당하는 Observer 인터페이스는 업로드가 됐을 때 실행할 함수인 OnUpload를 선언해준다
그래서 Youtuber와 Subscriber 클래스를 만들자
먼저 Youtuber이다
public class Youtuber : MonoBehaviour, ISubject
{
[SerializeField] Button uploadBtn;
public string channel;
private List<IObserver> observers = new List<IObserver>();
void Start()
{
uploadBtn.onClick.AddListener(NotifyObservers);
}
public void RegisterObserver(IObserver observer)
{
observers.Add(observer);
}
public void RemoveObserver(IObserver observer)
{
observers.Remove(observer);
}
public void NotifyObservers()
{
foreach (IObserver observer in observers)
{
observer.OnUpload(channel);
}
}
}
ISubject 인터페이스를 상속받아 구독자(Observer)들을 저장하는 변수를 두고 인터페이스 함수들을 정의해준다
다음 Subscriber이다
public class Subscriber : MonoBehaviour, IObserver
{
public Youtuber youtuber;
public string userName;
void OnEnable()
{
youtuber.RegisterObserver(this);
}
void OnDisable()
{
youtuber.RemoveObserver(this);
}
public void OnUpload(string channel)
{
Debug.Log("[" + userName + "]님 " + channel + "에서 새 영상을 업로드했습니다");
}
}
오브젝트가 활성화/비활성화될 때 구독할 youtuber에 구독, 구독해제 해준다
그리고 유튜버가 영상을 업로드하면 OnUpload 함수가 실행이 될 것이다

다음의 오브젝트들을 선언하고 오브젝트에 해당하는 스크립트를 컴포넌트로 등록해준다


게임을 시작하고 비활성화되어 있는 Subscriber를 활성화하고 게임 화면에 있는 버튼을 누르게 되면? 다음과 같이 로그가 뜬다

다음과 같이 순서는 무작위인것으로 보인다
그리고 다시 비활성화하고 버튼을 누르면 아무것도 안 뜬다
위와 같이 간단한 예제를 통해 옵저버 패턴을 알아보았다.
이 패턴과 비슷한 일을 하는 델리게이트와 액션도 있는데 둘 다 쓰임새가 다른 것 같은데 이것도 나중에 정리해보면 좋을 것 같다
참고를 많이 한 블로그는 적어두겠습니다 감사합니다
Inpa Dev