문제상황:
반응형 웹 개발 중, 다음과 같은 코드를 작성하여 브라우저 창 크기가 변경될 때마다 요소의 크기를 감지하고 변경하려고 했습니다.
const observedElement = document.getElementById('observedElement');
const resizeObserver = new ResizeObserver(entries => {
for (const entry of entries) {
const { width, height } = entry.contentRect;
console.log('Element:', entry.target);
console.log(`Width: ${width}, Height: ${height}`);
}
});
resizeObserver.observe(observedElement);
그러나 다음과 같은 에러로그가 발생했습니다.
ResizeObserver loop limit exceeded
해결방법:
다음과 같이 코드를 수정하여 에러를 해결했습니다.
const observedElement = document.getElementById('observedElement');
const resizeObserver = new ResizeObserver(entries => {
for (const entry of entries) {
const { width, height } = entry.contentRect;
console.log('Element:', entry.target);
console.log(`Width: ${width}, Height: ${height}`);
}
// 수정된 부분: 다음 프레임까지 기다렸다가 계속 감지
requestAnimationFrame(() => {
resizeObserver.observe(observedElement);
});
});
resizeObserver.observe(observedElement);
원인분석:
상세한 원인 분석:
이 문제는 ResizeObserver가 작동하는 방식과 관련이 있습니다. 기본적으로, 웹 페이지의 요소가 크기 변경될 때마다 ResizeObserver는 해당 요소에 대한 콜백 함수를 실행합니다. 그러나 레이아웃 변경이 연속적으로 발생하면, ResizeObserver는 레이아웃 변경을 처리하는 데 필요한 시간 이내에 감지할 수 없는 경우가 있습니다. 이러한 경우에 발생하는 에러가 "ResizeObserver loop limit exceeded"입니다.
코드에서 에러가 발생한 원인을 더 상세하게 살펴보면, ResizeObserver 콜백 함수 내에서 다른 레이아웃 변경이 발생하여 무한 반복이 생겼기 때문입니다. 이것은 콜백 함수가 실행될 때마다 ResizeObserver가 요소를 계속 관찰하면서 발생한 문제입니다.
이 문제를 해결하기 위해 requestAnimationFrame 함수를 사용하여 콜백 함수의 실행을 다음 브라우저 애니메이션 프레임까지 연기할 수 있습니다. 이렇게 하면 브라우저가 레이아웃 변경을 처리할 수 있는 충분한 시간이 주어집니다.
코드 수정에 대한 설명:
위에서 제안한 코드 수정 부분을 살펴보면, 콜백 함수의 마지막 부분에 requestAnimationFrame 함수를 사용하여 resizeObserver.observe(observedElement)를 다음 프레임까지 연기하고 있습니다.
requestAnimationFrame(() => { resizeObserver.observe(observedElement); });
이렇게 수정함으로써, 브라우저는 레이아웃 변경을 처리한 다음에만 ResizeObserver가 다시 관찰하도록 할 수 있으며, 무한 반복으로 인한 에러를 방지할 수 있습니다.
참고링크:
MDN Web Docs: ResizeObserver MDN Web Docs: Using ResizeObserver