옵저버 패턴(Observer Pattern)

2025. 3. 19. 13:10·Computer Science/Design Pattern

1. 옵저버 패턴(Observer Pattern)

  • 주체가 어떤 객체의 상태 변화를 관찰하다가 변화가 있을 때마다 메서드 등을 통해 옵저버 목록에 있는 옵저버들에게 변화를 알려주는 디자인 패턴.
  • 객체 간의 1:N 관계를 설정해서, 한 객체의 상태 변화가 발생하면 이를 의존하는 객체들에게 자동으로 알림을 보내는 패턴.
  • 즉, 누가 변하면 자동으로 알려준다 ~

2. Java의 옵저버 패턴 예시

import java.util.ArrayList;
import java.util.List;

// 옵저버 인터페이스 (Observer)
interface Observer {
    void update(String videoTitle);
}

// 유튜브 채널 (Subject)
class YouTubeChannel {
    private List<Observer> subscribers = new ArrayList<>();
    private String channelName;

    public YouTubeChannel(String channelName) {
        this.channelName = channelName;
    }

    // 구독자 추가
    public void subscribe(Observer observer) {
        subscribers.add(observer);
    }

    // 구독자 제거
    public void unsubscribe(Observer observer) {
        subscribers.remove(observer);
    }

    // 새 영상 업로드 -> 모든 구독자에게 알림
    public void uploadVideo(String videoTitle) {
        System.out.println(channelName + " 채널에 새로운 영상 업로드: " + videoTitle);
        notifyObservers(videoTitle);
    }

    // 구독자들에게 알림 보내기
    private void notifyObservers(String videoTitle) {
        for (Observer subscriber : subscribers) {
            subscriber.update(videoTitle);
        }
    }
}

// 구독자 클래스 (Observer 구현)
class Subscriber implements Observer {
    private String name;

    public Subscriber(String name) {
        this.name = name;
    }

    @Override
    public void update(String videoTitle) {
        System.out.println(name + "님, 새로운 영상이 업로드되었습니다: " + videoTitle);
    }
}

// 실행 클래스
public class ObserverPatternDemo {
    public static void main(String[] args) {
        // 유튜브 채널 생성
        YouTubeChannel channel = new YouTubeChannel("자진모리의 개발채널");

        // 구독자 생성
        Subscriber user1 = new Subscriber("철수");
        Subscriber user2 = new Subscriber("영희");

        // 구독자 등록
        channel.subscribe(user1);
        channel.subscribe(user2);

        // 영상 업로드 (자동으로 알림 전송됨)
        channel.uploadVideo("옵저버 패턴 쉽게 이해하기!");

        // 영희가 구독 취소
        channel.unsubscribe(user2);

        // 새로운 영상 업로드
        channel.uploadVideo("스프링 부트로 웹 개발 시작하기!");
    }
}

코드 분석

1. Observer(옵저버 인터페이스)

  • 옵저버 패턴에서 Observer(구독자) 역할을 할 인터페이스
  • update(String videoTitle) 메서드: 유튜브 채널에서 새로운 영상이 올라오면 실행

2. YouTubeChannel(Subject 역할 클래스)

  • Subject(주제, 발행자) 역할
  • 구독자 목록을 ArrayList로 저장하고, 채널 이름을 저장
  • subscriber: 구독자가 채널을 구독하면 subscribers 리스트에 저장됨
  • unsubscribe: 구독자가 구독을 취소하면 리스트에서 삭제됨
  • uploadVideo: 새로운 영상을 업로드할 때 콘솔에 출력하고, notifyObservers(videoTitle)을 호출해서 모든 구독자에게 알림 보냄
  • notifyObservers: subscribers 리스트에 있는 모든 옵저버(구독자)에게 update(videoTitle)을 호출해서 알림을 전달

3. Subscriber(Observer 역할을 하는 구독자 클래스)

  • Observer 인터페이스를 구현한 클래스
  • 구독자의 이름을 저장, update() 메서드를 오버라이드해서 새로운 영상이 올라왔을 때 알림을 받음

4. ObserverPatternDemo(실행 클래스)

  • YouTubeChannel을 생성하고 구독자(철수,영희)를 등록함
  • 이후에, 영희가 구독을 취소함
  • 두번째 영상이 올라가면 철수만 알림 받음

3. 옵저버 패턴의 장단점

장점

1. 객체 간의 결합도가 낮아짐

  • Subject와 Observer가 직접적인 의존 관계가 없음
  • 새로운 Observer를 추가하거나 기존 Observer를 제거해도 Subject 코드 수정이 필요 없음 > 유지보수 쉬움 !
  • 예제의 유튜브 채널이 구독자의 구체적인 동작을 몰라도 자동으로 알림을 보낼 수 있었던 것처럼 ~

2. 자동 알림

  • Subject의 상태가 변경되면 자동으로 모든 Observer에게 알림을 보냄
  • 개발자가 직접 일일이 객체들을 호출해서 업데이트하는 수고를 덜어낸다 !
  • 예제의 유튜브 채널이 새 영상을 업로드하면 구독자들에게 자동으로 알림이 가는 것처럼~

3. 확장성이 뛰어남

  • 새로운 Observer를 추가할 때 기존 코드를 변경할 필요 없이 그냥 추가하면됨 !
  • 여러 개의 Observer를 등록할 수 있어서 하나의 Subject를 여러 곳에서 활용 가능하다

4. 변화에도 유연한 설계

  • Subject 내부 로직이 바뀌어도 Observer는 영향을 받지 않는다
  • 각 객체의 역할이 분리되어 있어서 코드 수정이 유연함 !

단점

1. Observer가 많아지면 성능 저하..

  • Observer가 많아질수록 업데이트를 한꺼번에 보내야 하기 때문에 성능 문제가 발생할 수 있음
  • ex) 유튜브 채널이 수백만 명의 구독자를 가지고 있다면 영상이 올라갈 때마다 엄 청 난 트래픽이 발생할 수 있음 > 특정 Observer에게만 알림을 보내거나, 비동기 방식으로 처리하기

2. 디버깅이 어려울 수도..

  • Observer 패턴을 사용하면 이벤트가 어디서 발생했는지 추적하기 어려울 수 있음
  • ex) Subject가 변경되었을 때 여러 Observer가 자동으로 반응하기 때문에 어떤 Observer가 어떤 순서로 호출되었는지 확인하기 어려울 수 있음

3. 메모리 누수 위험

  • Subject와 Observer가 서로를 참조하면서 객체가 해제되지 않는 메모리 누수 가능성.
  • Observer를 제거하지 않고 계속 남겨두면 불필요한 객체가 계속 메모리를 차지할 수도 있음 > ex)Observer가 필요 없을 때는 반드시 unsubscribe() 메서드를 호출해서 제거해 줘야 함

4. 모든 Observer가 필요하지 않은 업데이트도 받을 수 있음

  • 어떤 옵저버는 특정 조건에서만 업데이트가 필요할 수도 있는데 무조건 notify()를 호출하면 불필요한 업데이트가 발생할 수도 있음 > Observer에게 필터링 기능을 추가하거나, 특정 조건에서만 업데이트하도록 설계

4. 옵저버 패턴을 사용하는 경우

1. 상태 변경을 여러 객체가 감지해야 할 때

  • ex) 유튜브 채널, 뉴스 웹사이트

2. 이벤트 기반 시스템을 만들고 싶을 때

  • ex) 버튼 클릭 이벤트, 게임에서 캐릭터 체력이 0이 되면 여러 시스템이 반응

3. MVC(Model-View-Controller) 패턴

  • Model(데이터)이 변경될 때 View(화면)이 자동으로 업데이트되는 구조

4. Java의 상속(extends)과 구현(implements)

상속(extends)

- 기존(부모)클래스를 물려받아 새로운(자식)클래스를 만드는 것.

상속의 특징

  • 부모 클래스의 기능(메서드, 필드)를 자식 클래스가 그대로 물려받음
  • 자식 클래스는 부모 클래스의 기능을 재사용 + 새로운 기능을 추가할 수 있음
  • extends 키워드를 사용
  • 상속받은 메서드를 오버라이딩(재정의) 할 수도 있음 !
  • 즉, 부모님께 레시피를 물려받아 레시피 그대로 사용하거나 재료를 추가할 수 있음 ~!

구현(implements)

- 인터페이스(설계도)만 제공하고, 세부적인 기능은 클래스에서 직접 만드는 것.

구현의 특징

  • 인터페이스는 설계도 역할을 하며, 기능의 '이름'만 정의하고 '구현'은 없음
  • implements 키워드를 사용
  • 인터페이스를 구현하는 클래스는 반드시 인터페이스의 메서드를 오버라이딩(재정의)해야 함
  • 즉, 레시피 책은 있지만 안에 내용이 없어서 어떤 재료로, 어떤 방식으로 만들지 내가 직접 해야 함

5. 상속과 구현, 언제 사용할까?

- 상속을 사용할 때(extends)

*is-a 관계: 객체 지향 프로그래밍에서 "어떤 클래스가 다른 클래스의 상속인지를 나타내는 개념"

즉, "A는 B다 라는 문장이 성립하면, A는 B의 자식 클래스일 가능성이 높다

  • 기존 클래스를 그대로 사용하고 싶을 때
  • 부모 클래스의 기능을 재사용하면서 추가적인 기능을 더할 때
  • *is-a 관계가 성립할 때

- 구현을 사용할 때(implements)

*can-do 관계: 객체 지향 프로그래밍에서 "어떤 객체가 특정한 행동을 할 수 있는지를 나타내는 개념"

즉, "A는 B를 할 수 있다 라는 문장이 성립하는 경우"

  • 공통된 기능(인터페이스)은 같지만 각각 다르게 동작해야 할 때
  • 여러 개의 기능을 동시에 적용하고 싶을 때 > 다중 구현 가능
  • *can-do 관계가 성립할 때

 


6. 결론

 옵저버 패턴은 객체의 상태 변화가 있을 때 이를 다른 객체들에게 자동으로 알려주는 패턴이다.
한 객체(주체)가 상태 변화를 감지하고, 이를 의존하는 여러 객체(옵저버)들에게 알림을 보낸다.

 

상속은 자식 클래스가 부모 클래스의 기능을 재사용하고 확장할 때 사용된다.
구현은 인터페이스에서 정의된 기능을 클래스에서 실제로 구현할 때 사용된다

'Computer Science > Design Pattern' 카테고리의 다른 글

이터레이터 패턴(Iterator Pattern)  (0) 2025.03.21
프록시 패턴(Proxy Pattern)  (0) 2025.03.19
전략 패턴(Strategy Pattern)  (1) 2025.03.18
팩토리 패턴(Factory Pattern)  (0) 2025.03.17
싱글톤 패턴(Singleton Pattern)  (1) 2025.03.14
'Computer Science/Design Pattern' 카테고리의 다른 글
  • 이터레이터 패턴(Iterator Pattern)
  • 프록시 패턴(Proxy Pattern)
  • 전략 패턴(Strategy Pattern)
  • 팩토리 패턴(Factory Pattern)
zajinmori
zajinmori
hello world !
  • zajinmori
    zajinmori's DevLog
    zajinmori
  • 전체
    오늘
    어제
  • 글쓰기 관리
    • 전체 (14)
      • Computer Science (14)
        • Design Pattern (8)
        • Programming Paradigm (3)
        • Network (3)
        • Operating System (0)
        • Database (0)
        • Data Structure (0)
  • 블로그 메뉴

    • 링크

    • 공지사항

    • 인기 글

    • 태그

    • 최근 댓글

    • hELLO· Designed By정상우.v4.10.3
    zajinmori
    옵저버 패턴(Observer Pattern)
    상단으로

    티스토리툴바