유니티 / / 2026. 4. 2. 11:34

디자인 패턴 - 옵저버 패턴(Observer Pattern)

예전에 프로젝트를 진행하다가 이벤트 기반으로 여러 객체가 서로 상태를 감지해야 하는 상황이 생겼는데요. 이때 사용했던 옵저버 패턴(Observer Pattern) 을 포스팅해보려고 합니다! 게임 개발을 하다 보면 "적이 죽었을 때 UI 업데이트, 사운드 재생, 점수 추가가 동시에 일어나야 해!" 같은 상황이 자주 생기잖아요. 이걸 깔끔하게 해결해주는 게 바로 옵저버 패턴입니다.


1. 옵저버 패턴(Observer Pattern)이란?

객체들 사이에서 하나의 객체 상태가 바뀌면, 그걸 지켜보고 있던 다른 객체들이 자동으로 알림을 받아 반응하는 디자인 패턴입니다.

이 구조에서 등장하는 두 가지 역할이 있어요.

  • Subject(발행자) : 상태가 변하는 객체. 옵저버 목록을 갖고 있고, 변경이 생기면 알림을 보냅니다.
  • Observer(구독자) : Subject를 구독하고 있는 객체. 알림이 오면 자신의 동작을 실행합니다.

비유하자면, 유튜브 구독 알림과 똑같아요. 크리에이터(Subject)가 영상을 올리면(상태 변경), 구독자들(Observer)이 알림을 받는 구조입니다!


2. 왜 옵저버 패턴을 쓸까?

제가 이 패턴을 쓰게 된 이유는 크게 네 가지입니다.

  • 결합도 감소 → Subject는 Observer가 누구인지 구체적으로 알 필요가 없어요. 그냥 "알림을 보낼 뿐"이고, 누가 받는지는 신경 안 씁니다.
  • 유지보수 편의성 → 새로운 Observer를 추가해도 Subject 코드를 전혀 수정하지 않아도 됩니다.
  • 이벤트 처리 간결화 → 여러 객체가 동시에 반응해야 하는 상황을 깔끔하게 처리할 수 있습니다.
  • 확장성 → 구독자를 언제든 자유롭게 추가하거나 제거할 수 있어서 유연한 구조를 만들 수 있습니다.

즉, 객체 간 의존성을 최소화하면서도 긴밀하게 연동할 수 있어서, 규모가 커질수록 진가가 드러나는 패턴입니다!


3. 사용 방법

Unity C# 기준으로 간단하게 구현하는 방법을 소개할게요.

① Observer 인터페이스 정의

public interface IObserver
{
    void OnNotify(string eventType);
}

② Subject 클래스 작성

public class Subject
{
    private List<IObserver> _observers = new List<IObserver>();

    public void Subscribe(IObserver observer)
    {
        _observers.Add(observer);
    }

    public void Unsubscribe(IObserver observer)
    {
        _observers.Remove(observer);
    }

    public void Notify(string eventType)
    {
        foreach (var observer in _observers)
        {
            observer.OnNotify(eventType);
        }
    }
}

③ Observer 구현

public class UIManager : MonoBehaviour, IObserver
{
    public void OnNotify(string eventType)
    {
        if (eventType == "EnemyDead")
        {
            Debug.Log("UI 업데이트: 적 처치 표시!");
        }
    }
}

④ 실제 연결 및 사용

Subject enemySubject = new Subject();
enemySubject.Subscribe(uiManager);  // 구독 등록

// 적이 죽었을 때
enemySubject.Notify("EnemyDead");   // 구독자 전체에게 알림 발송

Unity에서는 C# event나 Action, 또는 UnityEvent를 활용하면 이 구조를 더 간결하게 쓸 수도 있어요!


4. 실제 적용 예시

적(Enemy)이 사망했을 때 UI 업데이트 / 사운드 재생 / 점수 추가가 동시에 일어나야 하는 상황을 가정해볼게요.

  • 적용 전 : Enemy 클래스 안에서 UIManager, SoundManager, ScoreManager를 직접 참조 → 의존성 폭발, 코드 수정 시 연쇄 오류 위험
  • 적용 후 : Enemy가 Notify("EnemyDead")만 호출 → 각 Manager가 알아서 반응 → Enemy 코드는 단 한 줄도 건드릴 필요 없음

코드가 훨씬 깔끔해지고, 나중에 "적 처치 시 파티클 효과 추가"가 필요해도 EffectManager만 구독시키면 끝입니다!


5. 마무리

옵저버 패턴은 단순히 "알림 보내는 패턴" 같아 보이지만, 실제 프로젝트에서는 객체 간 결합도 감소 + 유지보수 효율 두 가지를 동시에 챙길 수 있는 중요한 디자인 패턴입니다.

특히 Unity처럼 다양한 시스템이 서로 맞물려 돌아가는 환경에서는, 이 패턴을 익혀두면 훨씬 체계적인 코드를 짤 수 있으니 꼭 한 번 써보시길 추천드립니다!

  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유