옵저버 패턴은 개체의 상태 변화를 관찰하고, 그 변화가 발생했을 때 자동으로 통지(Notify)를 받아 처리할 수 있도록 하는 패턴이다. 주로 이벤트 기반 시스템에서 사용된다.
주요 개념부터 살펴보자
1. Subject (주제) : 상태를 가지고 있으며, 상태 변화를 옵서버들에게 알린다. 옵서버를 등록하고 제거하는 메서드를 제공한다.
2. Observer (옵저버) : 주제의 상태 변화를 관찰하고, 상태 변화가 발생했을 때 특정 행동을 수행한다.
3. ConcreteSubect (구체적인 주제 : 상태를 저장하고, 상태가 변경될 때 옵서버들에게 알린다.
4. ConcreteObserver (구체적인 옵서버) : 주제의 상태 변화를 관찰하고, 상태가 변경될 때 행동을 수행한다.
날씨 모니터링 시스템 소스코드를 통해서 옵서버 패턴에 대해서 조금 더 알아보자.
import java.util.ArrayList;
import java.util.List;
// Subject 인터페이스: 옵서버를 등록, 제거하고 알리는 메서드를 정의
interface Subject {
void registerObserver(Observer o);
void removeObserver(Observer o);
void notifyObservers();
}
// WeatherData 클래스: 구체적인 주제 역할을 하며, 옵서버를 등록, 제거하고 상태 변화를 알림
class WeatherData implements Subject {
private List<Observer> observers;
private float temperature;
private float humidity;
private float pressure;
public WeatherData() {
observers = new ArrayList<>();
}
@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;
measurementsChanged();
}
public void measurementsChanged() {
notifyObservers();
}
}
// Observer 인터페이스: 주제의 상태가 변경될 때 업데이트되는 메서드를 정의
interface Observer {
void update(float temperature, float humidity, float pressure);
}
// CurrentConditionsDisplay 클래스: 구체적인 옵서버 역할을 하며, 상태 변경 시 행동을 수행
class CurrentConditionsDisplay implements Observer {
private float temperature;
private float humidity;
private Subject weatherData;
public CurrentConditionsDisplay(Subject weatherData) {
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
@Override
public void update(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
display();
}
public void display() {
System.out.println("Current conditions: " + temperature + "F degrees and " + humidity + "% humidity");
}
}
// Client 클래스: WeatherData 객체를 생성하고, CurrentConditionsDisplay 옵서버를 등록하고 상태를 변경
public class ObserverPatternDemo {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData);
weatherData.setMeasurements(80, 65, 30.4f);
weatherData.setMeasurements(82, 70, 29.2f);
weatherData.setMeasurements(78, 90, 29.2f);
}
}
//출력
//Current conditions: 80.0F degrees and 65.0% humidity
//Current conditions: 82.0F degrees and 70.0% humidity
//Current conditions: 78.0F degrees and 90.0% humidity
온도 변화를 감지하고 여러 디스플레이장치에 온도 변화를 알리는 예시소스코드를 확인할 수 있다.
실무에서도 아주 많이 사용된다. 몇가지만 살펴 보자
1. 이벤트 핸들링 시스템
- 예를 들어 하나의 GUI 애플리캐이션이 있다고 하자. 키보드 입력 등 다양한 이벤트를 처리해야하는데 이때 자바로 프로그래밍 되어 있다면 ActionListener를 많이 사용한다. ActionListener가 옵서버 패턴을 사용하고 있다.
2. MVC 아키텍처
- 과거도 현재도 가장 많이 사용되는 MVC 아키텍처는 모델과 뷰 사이에 상호작용되는데 모델의 상태가 변경될때 뷰에 자동으로 통지하여 화면을 갱신하는 구조이다. 이역시 옵서버 패턴이다.
3. 실시간 데이터 피드
- 주식 시세, 뉴스 피드, 소셜 미디어 업데이트 등 실시간 데이터 변경을 구독자에게 통지할 때 사용된다.
4. 알림 시스템
- 이메일 SMS 푸시 알림 등 다양한 채널을 통해 알림을 전송할 때 사용한다.
이렇게 보면 현대에서는 AWS를 많이 사용하고 AWS의 SNS가 떠오를 수 있다.
맞다. AWS 의 SNS는 옵서버 패턴과 아주 유사하다.
AWS 의 Topic은 옵서버 패턴의 Subject와 같은 역할을 한다. 또한 Observer는 SNS에서 Subscribers이다. 그리고 Notification이 전송되는 구조이다.
그러면 AWS SQS는 어떨까?
SQS 는 생산자-소비자 패턴이기에 Producer - Consumer 구조에서는 큐에 저장하고 소비자가 읽을떄까지 보관하는것이다. 그렇기에 메시지 전달을 보장한다. 옵서버 패턴과는 다르지만 헛갈릴 수 있는 부분이다. 대부분 큐에 저장한것을 바로바로 읽어가는쪽으로 대부분의 기존 시스템들을 설계하고 구현했을테니 처음 접하거나 업력이 아직 얼마 안되었다면 헛갈릴 수 있다. 큐잉 메커니즘에 대해서는 별도로 학습하길 권장한다.
옵서버 패턴을 생각하지 않아도 본인 스스로 자주 쓰이는 경우가 많다.
비동기 프로그래밍을 할때이다. 자바스크립트 기준으로 Promise개체와 async/await 구문 역시 옵서버 패턴과 유사하다.
이벤트 버스도 비슷하다. 그만큼 옵서버 패턴은 자주 쓰이기도하고 본인도 모르게 유사하게 구조를 잡아가면서 구현하는 경우가 있다.
'Design Pattern > 행동 패턴(Behavioral Patterns)' 카테고리의 다른 글
전략(Strategy) - 행동 패턴(Behavioral Patterns) (0) | 2024.05.25 |
---|---|
상태(State) - 행동 패턴(Behavioral Patterns) (0) | 2024.05.25 |
메멘토(Memento) - 행동 패턴(Behavioral Patterns) (0) | 2024.05.25 |
중재자(Mediator) - 행동 패턴(Behavioral Patterns) (0) | 2024.05.25 |
반복자(Iterator) - 행동 패턴(Behavioral Patterns) (0) | 2024.05.25 |