반응형
유튜브 채널을 '구독'하면 새로운 영상이 올라올 때마다 스마트폰으로 알림이 옵니다. 우리가 일일이 채널에 들어가서 새 영상이 있는지 확인할 필요가 없죠. 소프트웨어 세계에서도 이와 똑같은 방식이 존재합니다. 바로 옵저버 패턴(Observer Pattern)입니다.
오늘은 객체의 상태 변화를 감지하고 자동으로 알림을 보내는 옵저버 패턴에 대해 심도 있게 알아보겠습니다.

1. 옵저버 패턴이란?
옵저버 패턴은 한 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체들에게 연락이 가고, 자동으로 내용이 갱신되는 일대다(One-to-Many) 의존 관계를 정의합니다.
핵심 역할
- 주체 (Subject / Observable): 상태를 보유하고 있는 '알림이'입니다. 옵저버들을 등록하고 관리하며, 상태가 변하면 알림을 보냅니다.
- 옵저버 (Observer): 알림을 받는 '구독자'들입니다. 주체의 상태 변화에 따라 자신의 정보를 업데이트합니다.
2. 옵저버 패턴의 구조
패턴의 구조를 이해하면 왜 '느슨한 결합(Loose Coupling)'이 가능한지 알 수 있습니다.
- Subject 인터페이스: 옵저버 등록(attach), 제거(detach), 통지(notify) 메서드를 정의합니다.
- Observer 인터페이스: 변화를 전달받을 update 메서드를 정의합니다.
- Concrete 클래스들: 각 인터페이스를 실제로 구현하여 구체적인 로직을 수행합니다.
3. Java 구현 예제: 뉴스 피드 시스템
구독자들에게 실시간으로 뉴스를 전송하는 시스템을 만들어 보겠습니다.
Step 1. 인터페이스 정의
Java
import java.util.ArrayList;
import java.util.List;
// Subject 인터페이스
interface Subject {
void registerObserver(Observer o);
void removeObserver(Observer o);
void notifyObservers();
}
// Observer 인터페이스
interface Observer {
void update(String news);
}
Step 2. 구체적인 클래스 구현
Java
// 뉴스 기사 발행인 (Concrete Subject)
class NewsPublisher implements Subject {
private List<Observer> observers = new ArrayList<>();
private String latestNews;
public void setNews(String news) {
this.latestNews = news;
notifyObservers();
}
@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(latestNews);
}
}
}
// 구독자 (Concrete Observer)
class User implements Observer {
private String name;
public User(String name) { this.name = name; }
@Override
public void update(String news) {
System.out.println(name + " 님! 새 뉴스 도착: " + news);
}
}
Step 3. 테스트 코드
Java
public class ObserverDemo {
public static void main(String[] args) {
NewsPublisher publisher = new NewsPublisher();
publisher.registerObserver(new User("알리스"));
publisher.registerObserver(new User("밥"));
publisher.setNews("옵저버 패턴 포스팅이 업로드되었습니다!");
}
}
4. ⚠️ Java Observer 클래스가 Deprecated 된 이유
자바 기본 라이브러리(java.util.Observer)를 사용해 보셨다면, Java 9 버전부터 선이 그어져 있는(Deprecated) 것을 보셨을 겁니다. 왜일까요?
- 확장성 부족: Observable이 인터페이스가 아닌 클래스라 이미 다른 클래스를 상속받은 경우 사용할 수 없습니다. (다중 상속 불가)
- 유연성 저하: 메서드 이름이 직관적이지 않고, 스레드 안전성(Thread-safe) 면에서도 한계가 있습니다.
💡 대안은 무엇인가요?
- PropertyChangeListener: 자바 빈즈 모델에서 권장하는 방식입니다.
- Flow API (Java 9+): 리액티브 스트림을 지원하는 최신 방식입니다.
- RxJava / Project Reactor: 더 복잡한 비동기 데이터 흐름이 필요할 때 사용합니다.
5. 옵저버 패턴의 장단점
👍 장점
- 유연성: 주체의 코드를 수정하지 않고도 새로운 옵저버 클래스를 언제든 추가할 수 있습니다.
- 실시간성: 데이터 변경 시 즉각적으로 반영되어야 하는 UI나 시스템에 적합합니다.
👎 단점
- 실행 순서 보장 불가: 옵저버들에게 알림이 가는 순서를 제어하기 어렵습니다.
- 메모리 누수 위험: 옵저버 등록 후 적절히 제거하지 않으면 계속 참조가 남아 메모리 누수가 발생할 수 있습니다.
결론
옵저버 패턴은 "상태 변화의 자동화"를 가능하게 하는 혁신적인 패턴입니다. 비록 자바 기본 클래스는 저물었지만, 패턴의 핵심 원리는 오늘날 리액티브 프로그래밍과 프론트엔드의 상태 관리 라이브러리 등에서 더 활발히 쓰이고 있습니다.
도움이 되셨다면 공감과 구독 부탁드립니다! 디자인 패턴 시리즈는 계속됩니다. 다음 포스팅도 기대해 주세요!
반응형
'Mobile & App Stack > Java Software Architecture & Patterns' 카테고리의 다른 글
| 템플릿 메서드 패턴: 중복 코드를 줄이는 상속의 기술 (Java 예제) (0) | 2025.01.03 |
|---|---|
| 커맨드 패턴 완벽 정리: Undo/Redo 기능을 만드는 가장 스마트한 방법 (0) | 2025.01.02 |
| 전략 패턴(Strategy Pattern) 완벽 정리: if-else 지옥에서 탈출하기 (0) | 2024.12.30 |
| 플라이웨이트 패턴 완벽 정리: 메모리 사용량을 90% 줄이는 마법 (0) | 2024.12.29 |
| 브리지 패턴(Bridge Pattern) 완벽 정리: 클래스 폭발을 막는 설계의 기술 (0) | 2024.12.28 |