[JS][JAVA]MutationObserver와 Observer pattern

JUNYOUNG·2024년 3월 15일
post-thumbnail

자바스크립트 작업 중 값이 추가될 때, 호출없이 미리 정의한 함수를 사용해서 렌더링할 수 있지않을까 싶어서 찾아보다가 MutationObserver 객체를 사용해서 구현했습니다.
예전 안드로이드에서 이미지피커 작업 중, RecyclerView-SelectionSelectionTracker 를 사용하면서 옵저버패턴을 접하게되었는데 다시한번 나온 개념이라 짚고 넘어가겠습니다.

MutationObserver

MutationObserver는 웹 애플리케이션에서 DOM의 변화를 감지하는 효율적인 방법을 제공합니다.
개발자는 이를 사용하여 DOM 요소의 추가, 삭제, 속성 변경 등을 비동기적으로 감시할 수 있습니다.
이는 동적 콘텐츠와 사용자 상호작용에 대응하는 웹 애플리케이션 개발의 효율성을 가져다 줍니다.

기본 사용법

  1. MutationObserver 객체 생성
  2. 콜백 함수 정의: 변화가 감지될 때 실행될 함수
  3. observe 메소드를 사용하여 감시할 DOM 요소와 감시할 변화의 종류를 지정
  4. 필요에 따라 disconnect 메소드로 감시 중단

예시 코드

// 콜백 함수 정의 
const callback = function(mutationsList, observer) {
	for(let mutation of mutationsList) {
		if (mutation.type === 'childList') {
			console.log('A child node has been added or removed.');         
		}
	}
}; 
// MutationObserver 인스턴스 생성 
const observer = new MutationObserver(callback);  

// 감시할 대상 노드 설정 (예: body 태그)
const targetNode = document.body;

// 감시 설정: 대상 노드와 감시할 변화의 종류
observer.observe(targetNode, { childList: true });

// 테스트를 위해 대상 노드에 새로운 자식 노드를 추가하는 예시 코드
setTimeout(() => {
    const newNode = document.createElement('div');
    newNode.textContent = 'New child node added!';
    targetNode.appendChild(newNode);
}, 3000);

// 필요한 경우, 감시 중단
// setTimeout(() => {
//     observer.disconnect();
//     console.log('Observer disconnected');
// }, 6000);

이 코드는 targetNode로 설정된 요소 내부에 자식 요소가 추가되거나 삭제될 때 콘솔에 메시지를 출력합니다.
여기에서 setTimeout 함수를 사용하여 3초 후에 targetNode에 새로운 div 요소를 추가하고,
이 변화를 MutationObserver가 감지하여 콜백 함수를 실행하게 됩니다.
필요한 경우, 추가된 setTimeout을 사용하여 6초 후에 observer의 감시를 중단할 수도 있습니다.


옵저버 패턴

옵저버 패턴은 객체의 상태 변화를 관찰하는 객체들(옵저버)이 하나 이상 있을 때,
상태가 변하면 해당 객체들(서브젝트)에게 자동으로 알림(notify)을 보내는 디자인 패턴입니다.
즉, Subject는 자신이 누구에게 알리는지 몰라도 되며, Observer는 어떤 Subject로부터 변화를 감지할지만 알면 됩니다.
이를 통해 시스템의 결합도를 낮출 수 있으며, 각 컴포넌트를 독립적으로 변경하거나 확장할 수 있게 합니다.

동작 원리

  1. 서브젝트(Subject): 상태 변화를 갖는 객체
  2. 옵저버(Observer): 서브젝트의 상태 변화를 감시하고, 변화가 있을 때 통지를 받는 객체들
  3. 서브젝트는 옵저버 목록을 관리하고, 상태에 변화가 있을 때 모든 옵저버에게 변화를 알림

예시 코드(JAVA)

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

Observer 인터페이스는 모든 옵저버 객체가 구현해야 하는 메소드 update를 정의합니다.
이 메소드는 서브젝트의 상태 변화를 옵저버에게 알리기 위해 호출됩니다.
여기서 String message는 서브젝트로부터 전달받은 특정 정보나 데이터를 의미합니다.

// 서브젝트 클래스 
class Subject {
	private List<Observer> observers = new ArrayList<>();
    public void addObserver(Observer observer) {
    	observers.add(observer);     
	}
    public void notifyObservers(String message) {         
    	for (Observer observer : observers) {         
        	observer.update(message);         
            }     
		}
	}

Subject 클래스는 Observer 객체들을 관리하는 역할을 합니다.
내부적으로 Observer 객체의 리스트를 유지하며, addObserver 메소드를 통해 새로운 Observer를 리스트에 추가할 수 있습니다.
notifyObservers 메소드는 서브젝트의 상태 변화가 있을 때 호출됩니다.
이 메소드는 등록된 모든 옵저버들의 update 메소드를 호출하여 상태 변화를 알립니다.
String message 파라미터는 변화에 대한 정보나 데이터를 옵저버에게 전달하는 데 사용됩니다.

동작 과정
1. 여러 Observer 객체들이 Subject 객체에 등록(addObserver)됩니다.
2. Subject 객체에서 어떤 상태 변화가 발생하면, notifyObservers 메소드를 호출합니다. 이 메소드는 등록된 모든 Observer들의 update 메소드를 호출하여 상태 변화를 알립니다.
3. 각 Observer 객체는 update 메소드를 통해 상태 변화에 대응하는 로직을 수행합니다.
이 패턴은 객체 간의 결합도를 낮추고, 확장성과 유연성을 높이는 데 유용하게 사용됩니다.
예를 들어, GUI 애플리케이션에서 모델의 상태가 변경될 때마다 여러 뷰(view)를 업데이트해야 하는 경우나, 분산 시스템에서 상태의 변경을 다수의 클라이언트에게 효과적으로 알려야 하는 경우 등에 사용될 수 있습니다.

결론

MutationObserver와 옵저버 패턴은 각각 웹 개발과 객체 지향 설계에서 변화 감지를 구현하는 효과적인 방법입니다. 이들은 동적인 환경에서의 유연성과 반응성 향상에 기여하며, 개발자가 더 직관적이고 유지보수하기 쉬운 코드를 작성할 수 있도록 돕습니다.

Ref

profile
Onward, Always Upward - 기록은 성장의 증거

0개의 댓글