Computer/WEB, PHP-JAVA-Script Updated: 2025. 9. 3. 13:41 hwaya.

iframe 불러오는 창 크기에 맞춰서 크기 조절하기

반응형

웹사이트 개발을 의뢰했더니, iframe 외부페이지를 가져오는데 높이를 픽스 시켜두고 답을 안줘서 스크립트로 문제를 해결하였다.
iframe로 불러와지는 페이지에서(편하게 자식) '내 페이지의 높이가 몇 이다' 라고 보내면 받아서 iframe의 높이를 맞춰준다.

 

index (iframe으로 다른 페이지를 불러오는 페이지, 부모)

아래 스크립트를 </body> 바로 위에, 그러니깐 body의 가장 아래쪽에 넣기.

<script>
    // 이 함수는 아이프레임을 찾으면 통신을 준비.
    function setupIframeListener(iframe) {
        console.log('iframe을 감지하여 리스너를 추가하고 준비 신호를 보냅니다.');

        // 자식에게 "준비됐다"는 신호를 보냄
        iframe.contentWindow.postMessage('ready-for-message', '*');

        // 메시지 리스너는 한번만 추가해야 하므로, 이미 추가되었는지 확인.
        if (!window.hasIframeListener) {
            window.addEventListener('message', function (event) {
                // 메시지가 올 때마다 최신 iframe 요소를 다시 찾음.
                const currentIframe = document.getElementById('ifm');
                if (currentIframe && event.source === currentIframe.contentWindow) {
                    if (event.data && event.data.frameHeight) {
                        currentIframe.style.height = event.data.frameHeight + 'px';
                    }
                }
            }, false);
            // 리스너가 중복으로 추가되는 것을 방지하기 위한 플래그
            window.hasIframeListener = true;
        }
    }

    // 모든 변화를 감시
    const observer = new MutationObserver(function(mutations) {
        // 페이지에 변화가 생길 때마다 실행.
        for (const mutation of mutations) {
            // 추가된 노드(요소)가 있는지 확인.
            if (mutation.addedNodes.length > 0) {
                const iframe = document.getElementById('ifm');
                // 만약 추가된 노드 중에 아이프레임이 있다면,
                if (iframe) {
                    // 통신 준비 함수를 실행하고, 파수꾼의 역할을 잠시 중단할 수 있습니다.
                    setupIframeListener(iframe);
                    // observer.disconnect(); // 필요에 따라 감시 중단
                    return; // 아이프레임을 찾았으므로 더 이상 확인할 필요 없음
                }
            }
        }
    });

    // 페이지 로딩이 끝나면 body 전체를 대상으로 감시를 시작.
    window.addEventListener('load', function() {
        // 혹시 페이지에 처음부터 아이프레임이 있을 경우를 대비해 한번 실행
        const initialIframe = document.getElementById('ifm');
        if (initialIframe) {
            setupIframeListener(initialIframe);
        }

        // body에 자식 요소가 추가되거나 제거되는 모든 변화를 감시
        observer.observe(document.body, {
            childList: true,
            subtree: true
        });
    });
</script>

 

target (iframe으로 불러올 페이지, 자식)

동일하게, </body> 태그 바로 위에 그러니까 body 마지막에 넣어준다.

<script>
        let lastHeight = 0;

        function resizeParentFrame() {
            const body = document.body;
            const html = document.documentElement;
            const height = Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight);

            if (Math.abs(height - lastHeight) > 1) {
                console.log('높이가 변경되어 부모에게 전송:', height);
                window.parent.postMessage({ frameHeight: height }, '*');
                lastHeight = height;
            }
        }

        window.addEventListener('message', function (event) {
            if (event.data === 'ready-for-message') {
                console.log('부모가 준비되었다는 신호를 받음. 높이를 전송합니다.');
                lastHeight = 0;
                resizeParentFrame(); // 첫 높이 전송
            }
        });

        window.addEventListener('resize', resizeParentFrame);

        const observer = new MutationObserver(function (mutations) {
            resizeParentFrame();
        });
        observer.observe(document.body, { childList: true, attributes: true, subtree: true, characterData: true });
    </script>

 

그럼 왜 이렇게 했을까?

기본 원칙: Same-Origin Policy (동일 출처 정책)

원래 웹 브라우저는 매우 엄격한 보안 규칙인 '동일 출처 정책(Same-Origin Policy)'을 따릅니다.

  • 정의: 서로 다른 '출처'(웹사이트 주소)를 가진 페이지끼리는 보안을 위해 서로의 내용에 직접 접근하거나 조작할 수 없다는 규칙입니다.
  • 비유: 아파트의 각 집(웹 페이지)은 서로의 사생활(데이터)을 보호하기 위해 문을 잠그고 있습니다. 옆집 사람이 우리 집에 마음대로 들어와 가구를 옮길 수 없는 것과 같습니다.
  • 우리의 경우: 부모 창(index.html)과 자식 창(data_annotation.html)은 서로 다른 문서이므로, 이 규칙에 따라 부모가 자식의 높이를 직접 알아내거나, 자식이 부모의 <iframe> 태그를 직접 조작하는 것이 원칙적으로 불가능합니다.

해결책: postMessage라는 안전한 시스템

이러한 불편함을 해결하기 위해, 웹 브라우저는 postMessage라는 특별한 통신 방법을 제공합니다. 이것은 마치 아파트 단지 내에서 사용하는 안전한 내부 우편 시스템과 같습니다.

  • 역할: 서로 다른 창(부모-자식, 탭-팝업 등)이 서로에게 안전하게 문자 메시지를 주고받을 수 있게 해주는 통로입니다.
  • 보안: 직접 집 안으로 들어가는 대신, 정해진 우편함으로 편지를 보내는 방식이라 안전합니다. 다른 집의 내용물을 훔쳐볼 수는 없고 오직 메시지만 전달 가능합니다.
반응형

Table of Contents


EIGHTBOX
EIGHTBOX
hwaya.

programmer

🍋일상의 소소한 순간들부터 큰 꿈까지, 호기심을 만족시킬 다양한 카테고리를 담은 블로그 입니다. 그리고, 소소한 행동에 감동하며 기뻐하고 하루하루에 감사하는 사람🌵

Today Yesterday Total
최신글