iframe은 생각보다 자주 보이지만,
막상 직접 다루려고 하면 높이 문제나 도메인 제약 때문에 꽤 까다로운 태그다.
특히 그냥 붙여 넣기만 하면 되는 줄 알았다가
높이가 안 맞거나, 내부 페이지에 접근이 안 되거나, 반응형 대응이 꼬이는 경우가 많다.
이번 글은 실무에서 iframe을 쓸 때 헷갈리기 쉬운 포인트들을 기준으로 정리해봤다.
HTML 페이지 안에 또 다른 HTML 페이지를 삽입하는 태그.
말 그대로 "내부 프레임(inline frame)".
<iframe src="/other_page.php" width="400" height="300"></iframe>
iframe은 일반 <div>와 다르게 height: auto가 안 먹힌다.
height를 지정하지 않으면 브라우저 기본값 150px이 적용된다.
그래서 아무 생각 없이 붙이면
내용은 많은데 iframe은 150px짜리 박스만 보이는 상황이 생긴다.
콘텐츠에 맞추려면 JS로 내부 scrollHeight를 읽어서 직접 세팅해야 한다.
// iframe 내부 페이지에서 부모 iframe 높이를 세팅
parent.document.getElementById("my_iframe").height = document.body.scrollHeight;
상한/하한이 필요하면 Math.min, Math.max를 사용한다.
// 최소 205px, 최대 495px
const nextHeight = Math.max(Math.min(document.body.scrollHeight, 495), 205);
parent.document.getElementById("my_iframe").height = nextHeight;
iframe의 높이를 세팅하는 방법이 두 가지 있다.
// 방법 1: HTML 속성
iframe.height = "300";
// 방법 2: 인라인 스타일
iframe.style.height = "300px";
이 두 가지를 섞어 쓰면 충돌이 발생한다.
인라인 style이 HTML 속성보다 우선하므로, 이전에 style.height를 세팅한 적이 있으면 이후 iframe.height 변경이 무시될 수 있다.
한 가지 방식으로 통일하거나, 전환 시 이전 값을 초기화해야 한다.
// 인라인 스타일 초기화
iframe.style.height = "";
실무에서는 이런 식으로 섞어 쓰다가
“분명 높이를 바꿨는데 왜 안 바뀌지?” 하고 한참 헤매는 경우가 많다.
#my_iframe { height: 495px !important; }
#my_iframe { max-height: 495px !important; }
height: !important는 JS의 인라인 스타일 세팅도 덮어쓸 수 있어서,
동적 높이 제어가 필요하면 max-height/min-height를 사용하는 것이 좋다.
별도 문서를 로드하므로 CSS, JS 등 리소스가 이중으로 로딩된다.
페이지에 iframe이 많을수록 성능 부담이 커진다.
iframe 안의 콘텐츠는 검색엔진에서 별도의 페이지로 인식된다.
즉,
👉 iframe은 SEO에 불리하다기보다
SEO 관점에서 “기여하지 않는 구조”에 가깝다.
내부 콘텐츠 크기가 변해도 부모가 자동으로 감지하지 못한다.
MutationObserver 등으로 변화를 감시하고 수동으로 높이를 업데이트해야 한다.
new MutationObserver(function() {
parent.document.getElementById("my_iframe").height = document.body.scrollHeight;
}).observe(document.body, { childList: true, subtree: true });
다른 도메인의 iframe이면 JS로 내부 콘텐츠에 접근할 수 없다 (동일 출처 정책).
이 경우 postMessage를 사용해야 한다.
postMessage는 부모 페이지와 iframe 사이에서
👉 메시지 형태로 데이터를 주고받는 방식이다.
// iframe 내부에서 부모에게 높이 전달
parent.postMessage({ type: 'resize', height: document.body.scrollHeight }, '*');
// 부모 페이지에서 수신
window.addEventListener('message', function(e) {
if (e.data.type === 'resize') {
document.getElementById("my_iframe").style.height = e.data.height + 'px';
}
});
parent.postMessage(data, '*');
*는 모든 도메인을 허용하는 방식이라 위험하다.
parent.postMessage(data, 'https://example.com');
window.addEventListener('message', function(e) {
if (e.origin !== 'https://example.com') return;
});
| 방식 | 설명 | 적합한 경우 |
|---|---|---|
| AJAX + div | fetch()로 HTML 삽입 | 같은 도메인 |
| Web Component | Shadow DOM으로 격리 | iframe 대체 |
| 모달/팝업 | JS로 토글 | 단순 UI |
iframe은 격리와 외부 삽입에는 강하지만,
높이 제어와 SEO, 반응형 대응에서 까다롭다.