상세 컨텐츠

본문 제목

자바스크립트의 MutationOberver 에 대하여..

멘토링

by amanda.hyon 2022. 3. 31. 01:03

본문

옵저버 패턴이란?

옵저버 패턴은 데이터 종속적인 인터페이스가 데이터의 변화를 감시하는 구조를 말합니다. 엑셀 표를 생각해봅시다. 사용자가 스프레드시트의 값을 바꿀 때마다 표는 물론 그래프와 차트에도 변화가 전달되어야 합니다. 이때 중요한 건 모든 요소들이 동시에, 즉각적으로 변해야 한다는 것입니다. 모든 객체들의 신속한 동기화를 위해서는 데이터를 보유한 주체(Subject)를 여러 객체들이 감시(Observe)하는 방식이 가장 효과적입니다.

 

이 프로그래밍 패턴을 발전시킨 것이 리액티브 프로그래밍 패러다임이죠. 2009년 마이크로소프트에서 발표한 ReactiveX 프레임워크는 RxJS, Rx.NET 등 여러 언어를 지원하는 버전으로 발표되었습니다. RxJS는 자바스크립트의 비동기 액션을 하나의 데이터 흐름으로 제어하기 위해 주로 사용됩니다. 저 또한 사내 서비스에 RxJS 도입을 고려하고 있는 중입니다만, RxJS는 커다란 규모의 프레임워크인 만큼 설계가 안정된 뒤에 도입할 예정입니다.

보다 간단하게 옵저버 패턴을 사용할 수 있는 방법은 없을까요? 강력한 기능이 탑재된 것은 아니지만 이미 자바스크립트가 자체적으로 보유하고 있는 쏠쏠한 옵저버들이 여럿 있습니다.

JS Observers

MDN 페이지에서 소개하고 있는 자바스크립트 전체 API 중 옵저버는 총 다섯가지입니다. 간략하게 소개하자면 다음과 같습니다.

  • IntersectionObserver: 루트 영역(뷰포트)와 대상 객체의 겹침을 감시
  • MutationObserver: 객체의 속성 변경을 감시
  • PerformanceObserver: 프로세스 성능 모니터링
  • ReportingObserver: 웹 사이트의 표준 및 정책 준수 현황을 감시
  • ResizeObserver: 객체의 너비, 높이의 변화를 감시

 

MutationObserver 란?

총 5가지의 옵저버 패턴 중 HTML 요소의 변경을 감지할 수 있는 MutationObserver웹 개발에서 HTML 요소를 감지하여 처리해줘야 할 때가 있습니다. 그럴때 굉장히 유용하게 사용할 수 있는 기능입니다.

또한 Google Optimize를 사용할 때도 굉장히 유용하게 사용할 수 있는 기능이니 마케터 분들께서도 알고 계시면 좋은 기능입니다.

 

먼저 MutationObserver 를 사용하는 기본 코드부터 보여드리도록 하겠습니다.

가장 기본적인 사용법은 아래와 같습니다. 상세한 설정은 config를 통해 할 수 있습니다.

// 감지할 타겟
var target = document.getElementById('target');

// 변경을 감지했을 때 실행할 부분
var observer = new MutationObserver(mutations => {
  mutations.forEach(mutation => {
    console.log(mutation);
  });
});

// 감지 설정
var config = {
  childList: true,	// 타겟의 하위 요소 추가 및 제거 감지
  attributes: true,	// 타켓의 속성 변경를 감지
  characterData: false,	// 타겟의 데이터 변경 감지
  subtree: false,	// 타겟의 자식 노드 아래로도 모두 감지
  attributeOldValue: false,	// 타겟의 속성 변경 전 속성 기록
  characterDataOldValue: false	// 타겟의 데이터 변경 전 데이터 기록
};

// 감지 시작
observer.observe(target, config);

// 감지 종료
observer.disconnect();
  1. 감지할 타겟을 정합니다.
  2. 변경을 감지했을 때 실행할 코드를 작성합니다.
  3. 어떤 부분을 감지할지, 어디까지 감지할지 설정합니다.
  4. 감지를 시작합니다.
  5. 감지할 필요가 없게 되었을 때는 종료합니다. 계속해서 감지하게 하시려면 종료하지 않으시면 됩니다.

 

https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver

// 변화를 감지할 노드를 선택합니다.
const targetNode = document.getElementById('some-id');
 
// 변화 감지 설정입니다.
const config = { attributes: true, childList: true, subtree: true };
// 옵션 설명
//  - childList : 대상 노드의 하위 요소가 추가되거나 제거되는 것을 감지합니다.
//  - attributes : 대상 노드의 속성 변화를 감지합니다.
//  - characterData : 대상 노드의 데이터 변화를 감지합니다.
//  - subtree : 대상의 하위의 하위의 요소들까지의 변화를 감지합니다.
//  - attributeOldValue : 변화 이전의 속성 값을 기록합니다.
//  - characterDataOldValue : 변화 이전의 데이터 값을 기록합니다.
//  - attributeFilter : 모든 속성의 변화를 감지할 필요가 없는 경우 속성을 배열로 설정합니다.
 
// 변화가 감지될 때 실행할 콜백 함수
const callback = function(mutationsList, observer) {
  // 참고로 'for ...of' 문은 IE 11에서 동작하지 않습니다.
  for(let mutation of mutationsList) {
    if (mutation.type === 'childList') {
      // 자식 노드가 추가되거나 제거되었습니다.
      console.log('A child node has been added or removed.');
    }
    else if (mutation.type === 'attributes') {
      // mutation.attributeName 속성이 수정되었습니다.
      console.log('The ' + mutation.attributeName + ' attribute was modified.');
    }
  }
};
 
// 콜백 함수가 연결된 옵저버 인스턴스를 생성합니다.
const observer = new MutationObserver(callback);
 
// 선택한 노드의 변화 감지를 시작합니다.
observer.observe(targetNode, config);
 
// 아래와 같이, 나중에 관찰을 멈출 수 있습니다.
observer.disconnect();

 

이해를 돕기위해 타겟 하위 요소 추가 및 제거 감지와 타겟 속성 변경 감지 예시를 다음과 같이 준비 했습니다.

위와 같은 화면이 있다고 가정해보겠습니다.

검정색 네모 박스 div 태그를 MutationObserver를 사용하여 감지하고 있습니다.

변경이 감지되면 변경사항을 Console에 출력하도록 하였습니다.

요소 추가 버튼은 타겟인 div 태그에 p 태그의 요소를 추가하고,

요소 삭제 버튼은 타켓인 div 태그에 p 태그 요소를 삭제하고,

테두리 색상 변경 버튼은 div 태그의 style에 테두리 색상을 변경합니다.

 

요소 추가 버튼을 클릭해 타겟인 div 태그 안에 p 태그가 들어갔습니다.

변경사항을 출력해보면,

type이 childList로 타겟의 하위 요소 변경 감지했습니다.

addedNodes에 추가된 노드인 p 태그를 확인하실 수 있습니다.

 

요소 삭제 버튼을 클릭해 타겟인 div 태그 안에 있던 p 태그가 삭제됬습니다.

변경사항을 출력해보면,

type이 childList로 타겟의 하위 요소 변경을 감지했습니다.

removeNodes에 삭제된 노드인 p 태그를 확인하실 수 있습니다.

 

테두리 색상 변경 버튼을 클릭해 타겟인 div 태그의 테두리 색상이 변경되었습니다.

변경사항을 출력해보면,

type이 attributes로 타겟의 속성 변경을 감지했습니다.

attributeName에 변경된 속성인 style을 확인하실 수 있습니다.

 

참고자료: 

https://jsikim1.tistory.com/154

https://code-examples.net/ko/q/1e3162f

https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver

https://www.huskyhoochu.com/js-observers/

 

관련글 더보기

댓글 영역