logo hsb.horse
← 스니펫 목록으로 돌아가기

Snippets

dataset를 이용한 멱등 DOM 옵저버 설정

data 속성을 사용해 MutationObserver 중복 등록을 방지하는 간단한 패턴. 전역 레지스트리 불필요, 이식성이 높다.

게시일: 수정일:

MutationObserver를 여러 번 설정하면 같은 요소에 중복 옵저버가 등록될 수 있다. 전역 Set이나 Map으로 관리하는 방법도 있지만, dataset에 관찰 완료 플래그를 기록하는 방법은 가볍고 이식성이 높다.

코드

const OBSERVE_ID_KEY = 'observeId'
const isElementObserved = <T extends HTMLElement = HTMLElement>(
ele: T
) => Object.hasOwn(ele.dataset, OBSERVE_ID_KEY)
const setObserverId =
(id: string) =>
<T extends HTMLElement = HTMLElement>(ele: T): T => {
ele.dataset[OBSERVE_ID_KEY] = id
return ele
}
export const observeElement = (
observeId: string,
element: HTMLElement | string,
observerCallback: MutationCallback,
options: MutationObserverInit = { childList: true }
) => {
const observedElement =
element instanceof HTMLElement
? element
: document.querySelector<HTMLElement>(element)
if (observedElement && !isElementObserved(observedElement)) {
const observer = new MutationObserver(observerCallback)
observer.observe(observedElement, options)
setObserverId(observeId)(observedElement)
return observer
}
}

사용 예시

// 셀렉터 문자열 또는 HTMLElement 모두 전달 가능
observeElement(
'my-list-observer',
'#item-list',
(mutations) => {
for (const mutation of mutations) {
console.log('변경 감지:', mutation.type)
}
}
)
// 같은 요소에 다시 호출해도 중복 등록되지 않음
observeElement('my-list-observer', '#item-list', callback)

동작 원리

  1. Object.hasOwn(ele.dataset, OBSERVE_ID_KEY)data-observe-id 속성 존재 여부 확인
  2. 미등록 상태인 경우에만 MutationObserver를 생성하고 observe()를 호출
  3. 관찰 시작 후 ele.dataset[OBSERVE_ID_KEY] = id로 플래그 기록
  4. 이후 호출에서는 isElementObservedtrue를 반환하여 아무 작업도 하지 않음

dataset 값은 HTML의 data-* 속성에 직접 기록되므로 DevTools에서 확인할 수 있다.

장점

  • 전역 레지스트리 불필요: 상태를 요소 자체에 저장하므로 별도의 Map이나 Set 관리가 필요 없음
  • 높은 이식성: 프레임워크 의존성 없음, 모든 환경에서 동작
  • 디버깅 편의성: DevTools에서 속성 값을 직접 확인 가능

주의사항

요소가 DOM에서 제거되면 dataset 정보도 함께 사라진다. 같은 요소가 재삽입되면 다시 옵저버가 등록된다. 또한 옵저버를 중지하려면 observer.disconnect()를 별도로 호출해야 한다.