옵저버 패턴

Bo Ram·2025년 3월 6일

옵저버 패턴 (Observer Pattern)

✅ 핵심 개념

옵저버 패턴은 객체 간 1:N 관계에서, 한 객체(Subject)의 상태 변화가 발생하면 여러 객체(Observers)에게 자동으로 알림을 보내는 패턴이다.

예시: 뉴스 구독 시스템

  • 사용자가 뉴스레터를 구독하면, 새로운 소식이 나올 때마다 자동으로 알림을 받음.

구성 요소

  1. Subject (주제, 발행자)
    • 옵저버를 등록·삭제할 수 있으며, 상태 변경 시 옵저버들에게 알림을 보냄.
  2. Observer (옵저버, 구독자)
    • Subject의 상태 변경을 감지하고 업데이트를 받음.
  3. ConcreteSubject (구체적인 주제)
    • 상태를 관리하며, 변경 시 모든 옵저버에게 알림을 보냄.
  4. ConcreteObserver (구체적인 옵저버)
    • Subject의 알림을 받아 변화를 반영하는 객체.

적용 예시: 날씨 모니터링 시스템

// 1. Subject 인터페이스 (발행자)
public interface Subject {
    void registerObserver(Observer o); // 옵저버 등록
    void removeObserver(Observer o); // 옵저버 삭제
    void notifyObservers(); // 변경 사항 알림
}

// 2. Observer 인터페이스 (구독자)
public interface Observer {
    void update(float temperature, float humidity, float pressure);
}

// 3. ConcreteSubject (구체적인 발행자)
import java.util.ArrayList;
import java.util.List;

public class WeatherData implements Subject {
    private List<Observer> observers = new ArrayList<>();
    private float temperature;
    private float humidity;
    private float pressure;

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

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

    @Override
    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(temperature, humidity, pressure);
        }
    }

    public void setMeasurements(float temperature, float humidity, float pressure) {
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        notifyObservers();
    }
}

// 4. ConcreteObserver (구체적인 구독자)
public class CurrentConditionsDisplay implements Observer {
    private float temperature;
    private float humidity;

    @Override
    public void update(float temperature, float humidity, float pressure) {
        this.temperature = temperature;
        this.humidity = humidity;
        display();
    }

    public void display() {
        System.out.println("현재 상태: 온도 " + temperature + "°C, 습도 " + humidity + "%");
    }
}

// 5. 실행 코드
public class WeatherStation {
    public static void main(String[] args) {
        WeatherData weatherData = new WeatherData();
        CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay();

        weatherData.registerObserver(currentDisplay); // 옵저버 등록
        weatherData.setMeasurements(25.3f, 65.0f, 1013.1f); // 새로운 날씨 데이터 설정
    }
}
// 실행 결과: 현재 상태: 온도 25.3°C, 습도 65.0%

옵저버 패턴의 특징

푸시(Push) vs 풀(Pull) 방식

  • 푸시 방식 (Push, 위 코드 적용)
    • Subject가 모든 데이터를 옵저버에게 전달
    • 장점: 빠름 / 단점: 필요 없는 데이터도 전달됨
  • 풀 방식 (Pull)
    • 옵저버가 필요한 데이터만 가져가는 방식
    • 장점: 유연성 증가 / 단점: 옵저버가 Subject 상태를 직접 조회해야 함

느슨한 결합 (Loose Coupling)

  • Subject는 옵저버가 누구인지 알 필요 없음, 단지 인터페이스를 통해 통신
  • 새로운 옵저버 추가·삭제 시 Subject를 수정할 필요 없음 → 확장성 높음

Java의 java.util.ObservableObserver

  • Java 9부터 ObservableObserverDeprecated
  • 대신 PropertyChangeListener 같은 대체 API 사용 가능

정리

  • 옵저버 패턴은 객체 간 1:N 관계에서 이벤트를 효율적으로 전달하는 데 유용
  • 느슨한 결합을 유지하며, 확장성이 뛰어남
  • 푸시(Push) vs 풀(Pull) 방식을 선택하여 효율적으로 구현 가능

실제 활용 예시:

  • 이벤트 리스너 (GUI 개발)
  • 알림 시스템 (뉴스 구독, 주식 가격 업데이트 등)
  • 파일 시스템 변경 감지 (파일 감시자 패턴)

실제 프로젝트에서 활용할 때는 성능과 데이터 전달 방식을 고려해서 적용해야 함!

profile
사부작ㅤ사부작

0개의 댓글