ETC

[디자인 패턴] 옵저버 패턴(Observer Pattern)이란?

코냥이 2024. 10. 27. 22:51

 

 

 

1. 옵저버 패턴 (Observer Pattern)


옵저버(Observer)를 직역하면 관찰자, 감시자를 뜻한다.

옵저버 패턴(Observer Pattern)옵저버(감시자)가 관찰하는 대상자의 상태 변화(이벤트)가 발생되는 것을 감시하는 패턴이다.

옵저버 패턴은 다른 디자인 패턴과 다르게 일대다(1:N) 의존성을 가진다.

 

 

옵저버 패턴을 유튜브 채널과 구독에 비유하면 이해하기가 좀 더 쉽다.

유튜브 채널을 구독하는 구독자는 자신이 구독한 채널의 새 영상이 업로드되면 알림을 받게 된다. 여기서 유튜브 채널은 관찰 대상자가 되고, 구독자는 옵저버(관찰자)가 된다.

유튜브 채널에 새 영상이 업로드되는 이벤트를 감지하고, 미리 정의해 둔 알림을 보내는 동작이 수행된다.

 

이처럼 옵저버 패턴은 이벤트가 발생될 때마다 미리 정의해 둔 동작을 수행하도록 해주는 디자인 패턴이다.

 

 

 

 

2. 옵저버 패턴의 장단점


[ 장점 ]

  • 실시간으로 객체의 상태 변화를 알 수 있다.
  • 옵저버와 관찰 대상자(Subject)의 관계를 느슨하게 유지할 수 있다. (느슨한 결합)
    • 느슨한 결합은 두 객체가 상호작용을 하지만 서로에 대해 잘 모른다는 의미이다.
    • 관찰 대상자(Subject)는 옵저버가 무엇을 하는지, 구상 클래스가 무엇인지 알 필요가 없다.
    • 옵저버는 언제든지 추가, 삭제가 가능하며, 옵저버와 관찰 대상자(Subject)는 서로 영향을 주고 받지 않게 된다.

 

[ 단점 ]

  • 옵저버 패턴을 많이 사용하게 되면 상태 관리가 어려워진다.
  • 사용되지 않는 옵저버를 삭제하지 않으면 메모리 누수가 발생할 수 있다.

 

 

 

 

3. Spring의 옵저버 패턴 활용 방법


Spring에서는 옵저버 패턴을 어떻게 사용할까?

 

가장 대표적으로, Spring의 이벤트 발행을 담당하는 ApplicationEventPublisher 인터페이스가 있다.

@EventListener 어노테이션을 사용해서 이벤트를 정의하고, ApplicationEventPublisher 인터페이스를 사용해서 이벤트를 발행한다.

이 때, @EventListener 가 옵저버(관찰자)가 되고, ApplicationEventPublisher 인터페이스가 관찰 대상자(Subject)가 된다.

 

 

더보기

Spring 이벤트 발행과 구독에 관련해서 정말 잘 정리해주신 망나니개발자님의 포스팅을 참고하면 좋을 것 같다...!

 

 

 

 

4. Java로 옵저버 패턴 구현하기


Java에서는 JDK에서 지원하는 내장 옵저버 패턴이 존재한다.

본 포스팅에서는 내장 옵저버 패턴을 사용하지 않고 직접 간단하게 구현해 볼 예정이다.

위에서 예시로 들었던 유튜브 채널과 구독자를 구현해보려고 한다.

 

Observer(관찰자) : 구독자
Subject(관찰 대상자) : 유튜브 채널
이벤트 : 채널 커뮤니티에 새로운 글이 업로드되면 구독자들은 알림을 받는다.

 

 

Channel

관찰 대상자인 Subject 인터페이스이다.

  • addObserver : 관찰 대상자를 구독할 옵저버를 추가하는 기능
  • deleteObserver : 관찰 대상자 구독 취소하는 기능
  • notifyObserver : 옵저버에게 알림을 전송하는 기능
public interface Channel {

	void addObserver(Subscriber subscriber); // 옵저버 추가

	void deleteObserver(Subscriber subscriber); // 옵저버 삭제

	void notifyObserver(String message); // 옵저버에게 알림 전송

}

 

Subscriber

관찰자인 Observer 인터페이스이다.

  • update : 구독 중인 관찰 대상자의 알림을 받았는지 확인하는 기능
public interface Subscriber {

	void update(String message);

}

 

CatChannel

Channel 인터페이스를 정의하는 CatChannel 클래스이다.

  • subscriberList : 해당 채널을 구독하는 Observer 리스트
  • uploadPost : 해당 채널의 이벤트 행위
public class CatChannel implements Channel {

	private List<Subscriber> subscriberList = new ArrayList<>();

	public void uploadPost() {
		System.out.println("이벤트 발생 : 채널 커뮤니티 글 업로드");
		notifyObserver("고양이 채널 커뮤니티에 새 글이 업로드 되었습니다.");
	}

	@Override
	public void addObserver(Subscriber subscriber) {
		subscriberList.add(subscriber);
	}

	@Override
	public void deleteObserver(Subscriber subscriber) {
		subscriberList.remove(subscriber);
	}

	@Override
	public void notifyObserver(String message) {
		subscriberList.forEach(subscriber -> subscriber.update(message));
	}
}

 

ASubscriber

Subscriber 인터페이스를 정의하는 ASubscriber 클래스이다.

public class ASubscriber implements Subscriber {

	@Override
	public void update(String message) {
		System.out.println("A 구독자 수신 완료 : " + message);
	}
    
}

 

BSubscriber

Subscriber 인터페이스를 정의하는 BSubscriber 클래스이다.

public class BSubscriber implements Subscriber {

	@Override
	public void update(String message) {
		System.out.println("B 구독자 수신 완료 : " + message);
	}
    
}

 

CSubscriber

Subscriber 인터페이스를 정의하는 CSubscriber 클래스이다.

public class CSubscriber implements Subscriber {

	@Override
	public void update(String message) {
		System.out.println("C 구독자 수신 완료 : " + message);
	}
	
}

 

ObserverMain

옵저버 패턴을 테스트할 Main 클래스이다.

CatChannel에 a, b, c 옵저버를 모두 등록한 후의 결과와 b 옵저버를 삭제한 후의 결과를 확인해 보자.

public class ObserverMain {

	public static void main(String[] args) {
		CatChannel catChannel = new CatChannel();

		Subscriber aSubscriber = new ASubscriber();
		Subscriber bSubscriber = new BSubscriber();
		Subscriber cSubscriber = new CSubscriber();

		catChannel.addObserver(aSubscriber);
		catChannel.addObserver(bSubscriber);
		catChannel.addObserver(cSubscriber);

		catChannel.uploadPost();

		System.out.println("============");

		catChannel.deleteObserver(bSubscriber);

		catChannel.uploadPost();
	}

}

 

 

 

실행 결과

실행 결과

Subject의 이벤트가 발생했을 때, 구독 중인 Observer 에게만 알림이 가는 것을 확인할 수 있다.

 

 

 

 

 

 

 

 

출처

 

 

 

긴 글 읽어주셔서 감사합니다 🍀

잘못 작성된 내용은 피드백 주시면 반영하겠습니다 😎