Web/JS

[JS] JavaScript를 이용해서 DOM 변경 감지하기 (Mutation Observer)

메바동 2020. 9. 10. 21:54
728x90

  창이 열리면 input 태그에 focus를 주어야 하는데 자꾸 다른 곳에서 DOM이 변경되면서 focus가 나가버리는 상황이 있었다. 고민하다가 DOM이 변경될 때 input 태그에 focus를 주는 방법을 없을까? 하고 찾아보니 Mutation Observer가 있었다.

버튼을 클릭하면 아이템이 추가되는 화면

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>MutationObserver</title>

    <script>
        function addRow() {
            let list = document.querySelector('ul');
            let lastRow = document.querySelector('li:last-child');
            let newRowNum = parseInt(lastRow.textContent.replace(/[^0-9]/g, '')) + 1;
            
            let row = document.createElement('li');
            row.textContent = newRowNum + '번째 아이템';
            
            list.appendChild(row);
        }
    </script>
</head>
<body>
    <button onclick="addRow();">추가하기</button>

    <ul>
        <li>1번 아이템</li>
    </ul>
</body>
</html>

급하게 DOM이 변경되는 페이지를 만들었다.

 

 다음과 같이 페이지에서 ul에 li가 추가되거나 텍스트의 내용이 변경되거나 속성이 변경되거나 하는 것들을 감지하고 싶다면 Mutation Observer를 사용하면 된다.

Mutation Observer를 이용하면 특정 노드의 DOM 변경을 감지할 수 있다. html 태그나 body 태그에 사용하여 페이지의 전체적인 변경을 감지할 수도 있을 것 같다.

 

 위에 작성한 예제에 ul에 li가 추가될 경우 alert을 띄우고 싶다면 다음과 같이 Mutation Observer를 사용하면 된다.

 

// Mutation Observer
// 감시 대상 node 선택
let target = document.querySelector('ul');

// 감시자 인스턴스 만들기
let observer = new MutationObserver((mutations) => {
    // 노드가 변경 됐을 때의 작업
    alert('DOM 변경 감지');
})

// 감시자의 설정
let option = {
    attributes: true,
    childList: true,
    characterData: true
};

// 대상 노드에 감시자 전달
observer.observe(target, option);

추가하기를 누르면 alert 창이 잘 뜬다.

 

 Mutation Observer를 사용할 때 Option으로 줄 수 있는 항목은 다음과 같다.

 

속성 설명 기본값
childList 대상 노드의 자식 요소(텍스트 포함)의 변화 감지 false
attributes 대상 노드의 속성 변화 감지 false
characterData 대상 노드의 데이터 변화 감지 false
subtree 대상 노드의 자식 요소뿐만 아니라 후손 요소의 변화까지 감지 false
attributeOldValue 대상 노드의 속성 변경 전의 값도 기록에 남김 false
characterDataOldValue 대상 노드의 데이터 변경 전의 값도 기록에 남김 false
attributeFilter 모든 속성의 변화를 감지할 필요가 없는 경우 속성의 네임 스페이스 없이 속성 로컬 명의 배열로 설정  

 속성 중 최소한 childList, attributes, characterData는 true로 설정해야 한다.

 

생각해보니까 성능 저하는 크게 없는건가...

 아직 배울게 많은 것 같다. Mutation Observer 정리 끝.


· 참고

MDN - MutationObserver (https://developer.mozilla.org/ko/docs/Web/API/MutationObserver)

728x90