메뉴 닫기

Java Observer 패턴, Subject와 Observer 인터페이스의 핵심 역할 정리

Java Observer 패턴, Subject와 Observer 인터페이스의 핵심 역할 정리

🔍 객체 간 상태 변화 통지를 가능하게 하는 두 인터페이스의 설계 원리를 알아봅니다

Java의 Observer 패턴은 한 객체의 상태 변화가 다른 객체에 자동으로 전달되도록 설계하는 대표적인 행위 패턴입니다.
이 패턴의 핵심은 SubjectObserver라는 두 인터페이스인데요,
각각의 역할과 책임을 명확히 구분함으로써 결합도를 낮추고, 유지보수성과 확장성을 높일 수 있습니다.
Subject는 상태를 보유하고 변화를 관찰자에게 알리는 역할을, Observer는 이 변화를 받아 처리하는 역할을 수행합니다.

이번 글에서는 이 두 인터페이스가 어떤 책임을 가지고 있으며, 실무에서 어떻게 설계하고 구현하는지 구체적으로 알아보겠습니다.
또한 Java에서의 예시 코드와 함께, 올바른 설계 시 주의할 점과 실무 활용 팁까지 정리해 드립니다.
Observer 패턴을 처음 접하는 분뿐만 아니라 이미 사용해본 경험이 있는 개발자에게도 도움이 될 만한 내용이 될 것입니다.



🔗 Subject 인터페이스란?

Observer 패턴에서 Subject 인터페이스는 상태를 보유하고 관리하는 주체의 역할을 정의합니다.
이 인터페이스는 관찰자(Observer)를 등록하거나 제거하고, 상태 변화 시 등록된 모든 관찰자에게 알림을 보내는 메서드를 포함합니다.
즉, 발행자(Publisher)로서의 책임을 가지는 핵심 컴포넌트입니다.

📌 기본 메서드 구성

  • registerObserver(Observer o) : 관찰자를 등록
  • removeObserver(Observer o) : 관찰자를 제거
  • 📢notifyObservers() : 등록된 모든 관찰자에게 상태 변경을 통지

💬 Subject 인터페이스는 관찰자 리스트를 직접 관리하지 않고, 인터페이스로만 행동을 정의하여 다양한 구현체에서 유연하게 사용할 수 있도록 합니다.

이러한 설계 덕분에 새로운 관찰자를 쉽게 추가하거나 기존 관찰자를 제거할 수 있으며,
상태 변화 로직과 알림 로직이 명확히 분리되어 코드의 가독성과 유지보수성이 향상됩니다.

🛠️ Observer 인터페이스란?

Observer 패턴에서 Observer 인터페이스는 상태 변화 알림을 받는 구독자(Subscriber) 역할을 정의합니다.
이 인터페이스는 주제(Subject)로부터 전달된 변화를 처리하는 핵심 메서드를 포함하며,
실제로 어떤 동작을 할지는 구현 클래스에서 자유롭게 결정할 수 있습니다.

📌 기본 메서드 구성

  • 🔔update(Object state) : 주제로부터 전달된 상태 변화를 받아 처리

Observer 인터페이스는 단 하나의 update() 메서드를 정의하는 경우가 많습니다.
이 메서드의 매개변수는 변경된 데이터나 상태를 전달받기 위해 사용되며,
UI 갱신, 로그 기록, 다른 시스템 호출 등 다양한 동작을 수행할 수 있습니다.

💎 핵심 포인트:
Observer 인터페이스를 사용하면 상태 변화를 처리하는 로직을 다양한 구현체에서 독립적으로 작성할 수 있어, 재사용성과 확장성이 뛰어납니다.



⚙️ 두 인터페이스의 상호 작용 구조

Subject와 Observer 인터페이스는 발행-구독(Publish-Subscribe) 구조를 기반으로 동작합니다.
Subject는 상태를 관리하고, 변화가 발생하면 등록된 모든 Observer의 update() 메서드를 호출해 변경 사항을 통보합니다.
Observer는 이 알림을 받고, 자신의 역할에 맞게 후속 동작을 수행합니다.

📌 동작 흐름

  • 📝Observer가 Subject에 등록(register)됩니다.
  • 📢Subject의 상태가 변경되면 notifyObservers() 메서드가 실행됩니다.
  • 🔔모든 Observer의 update() 메서드가 호출되어 상태 변화를 처리합니다.

💬 이 구조의 장점은 Subject와 Observer가 서로의 내부 구현을 몰라도 상호작용이 가능하다는 점입니다. 덕분에 유지보수성과 확장성이 크게 향상됩니다.

이러한 상호 작용 덕분에 다양한 상황에서 Observer 패턴이 활용됩니다.
예를 들어, 주식 시세 변동 알림 시스템, 실시간 채팅 알림, UI 상태 갱신 등은 모두 Subject와 Observer의 구조를 기반으로 동작합니다.

🔌 코드 예시로 보는 구현 방식

아래 예시는 Java에서 SubjectObserver 인터페이스를 정의하고, 이를 활용해 뉴스 발행 시스템을 구현한 간단한 사례입니다.

CODE BLOCK
// Observer 인터페이스
interface Observer {
    void update(String message);
}

// Subject 인터페이스
interface Subject {
    void registerObserver(Observer o);
    void removeObserver(Observer o);
    void notifyObservers();
}

// ConcreteSubject
class NewsPublisher implements Subject {
    private List<Observer> observers = new ArrayList<>();
    private String latestNews;

    public void registerObserver(Observer o) {
        observers.add(o);
    }

    public void removeObserver(Observer o) {
        observers.remove(o);
    }

    public void setNews(String news) {
        this.latestNews = news;
        notifyObservers();
    }

    public void notifyObservers() {
        for (Observer o : observers) {
            o.update(latestNews);
        }
    }
}

// ConcreteObserver
class NewsSubscriber implements Observer {
    private String name;
    public NewsSubscriber(String name) {
        this.name = name;
    }
    public void update(String message) {
        System.out.println(name + "님, 새로운 뉴스가 도착했습니다: " + message);
    }
}

// 실행 예시
public class ObserverPatternExample {
    public static void main(String[] args) {
        NewsPublisher publisher = new NewsPublisher();
        Observer sub1 = new NewsSubscriber("철수");
        Observer sub2 = new NewsSubscriber("영희");

        publisher.registerObserver(sub1);
        publisher.registerObserver(sub2);

        publisher.setNews("Java Observer 패턴 글이 발행되었습니다!");
    }
}

이 예시에서 Subject는 뉴스 발행자 역할을 하고, Observer는 뉴스 구독자의 역할을 수행합니다.
뉴스가 업데이트되면 등록된 모든 구독자에게 자동으로 알림이 전달됩니다.

💎 핵심 포인트:
인터페이스 기반 구현을 사용하면 다양한 유형의 Subject와 Observer를 손쉽게 교체하거나 확장할 수 있습니다.



💡 설계 시 장점과 주의점

📌 장점

  • 결합도 감소로 유지보수와 확장이 용이합니다.
  • 새로운 Observer 추가나 제거가 간단합니다.
  • 다양한 상황에서 재사용이 가능합니다.

📌 주의점

⚠️ 주의: Observer가 많아질수록 알림 성능이 저하될 수 있으며, 불필요한 업데이트가 빈번히 발생할 수 있습니다.

또한, 여러 Observer가 동일한 데이터를 수정하는 경우 경합 조건(Race Condition)이 발생할 수 있으므로 동기화 처리가 필요합니다.
불필요한 메모리 점유를 방지하기 위해 더 이상 필요 없는 Observer는 반드시 제거해야 합니다.

📌 설계 팁

  • 💡알림 주기를 조절하여 불필요한 호출을 줄입니다.
  • 💡필요한 Observer에만 선택적으로 알림을 보냅니다.
  • 💡약한 참조(WeakReference)를 활용해 메모리 누수를 방지합니다.

자주 묻는 질문 (FAQ)

Subject와 Observer 인터페이스를 꼭 나눠야 하나요?
네. 역할을 분리하면 코드의 결합도가 낮아지고, 새로운 구현체를 쉽게 추가하거나 교체할 수 있어 유지보수가 용이해집니다.
Observer 패턴과 이벤트 리스너 패턴은 같은 건가요?
구조적으로 유사하지만, 이벤트 리스너 패턴은 특정 이벤트 타입에 반응하는 구조이고, Observer 패턴은 일반적인 상태 변화 알림에 사용됩니다.
Java 기본 API의 Observer와 Observable을 사용해도 되나요?
Java 9 이후로 Deprecated 되었기 때문에, 직접 인터페이스를 구현하거나 이벤트 리스너 방식으로 구현하는 것이 권장됩니다.
Observer가 너무 많으면 어떻게 되나요?
알림 전달 시간이 길어지고 성능이 저하됩니다. 필요한 Observer만 등록하거나, 알림을 비동기적으로 처리하는 방법을 고려해야 합니다.
update 메서드에서 예외가 발생하면 다른 Observer에도 영향이 있나요?
한 Observer의 예외가 전체 알림 흐름을 중단시킬 수 있습니다. 예외 처리를 개별 Observer에서 처리하도록 설계하는 것이 좋습니다.
Subject와 Observer 간에 데이터를 양방향으로 주고받을 수 있나요?
가능하지만, 양방향 의존성이 생기면 결합도가 높아집니다. 가급적 단방향 흐름을 유지하는 것이 바람직합니다.
Observer 패턴을 테스트하는 좋은 방법이 있나요?
Mock 객체를 활용해 notifyObservers 호출 시 각 Observer의 update 메서드가 올바르게 호출되는지 검증할 수 있습니다.
Observer 패턴 대신 Publisher-Subscriber 패턴을 쓰는 게 나을 때는?
시스템 규모가 크고, 구성 요소 간의 결합을 최소화해야 하는 경우 Pub-Sub 패턴이 더 적합할 수 있습니다. 특히 메시지 브로커를 통해 비동기 통신이 필요한 경우 유용합니다.

📌 Subject와 Observer 인터페이스로 완성하는 유연한 상태 통지 구조

Java의 Observer 패턴에서 Subject와 Observer 인터페이스는 객체 간 결합도를 낮추면서 상태 변화를 효율적으로 전달하는 핵심 요소입니다.
Subject는 상태를 관리하고 변화를 알리는 주체이며, Observer는 이를 수신해 필요한 처리를 수행하는 구독자입니다.
이 구조를 활용하면 코드 확장과 유지보수가 쉬워지고, 다양한 상황에 맞게 기능을 추가할 수 있습니다.
다만, 성능 저하와 불필요한 알림을 방지하기 위해 관찰자 수와 알림 주기를 적절히 관리하는 것이 중요합니다.
두 인터페이스의 역할을 명확히 구분하고 올바르게 구현한다면, 안정적이면서도 확장성 높은 소프트웨어 아키텍처를 구축할 수 있습니다.


🏷️ 관련 태그 : Observer패턴, Subject인터페이스, Observer인터페이스, Java디자인패턴, 상태변화통지, 객체지향설계, 발행구독모델, 결합도낮추기, 실시간알림, 이벤트처리