본문 바로가기

FrontEnd

Iframe 완벽 가이드

반응형

꽤 자주 보지만 아직도 익숙하지 않은 Iframe에 대해 알아봅니다.

원문 링크입니다 : https://blog.logrocket.com/the-ultimate-guide-to-iframes/

 

The ultimate guide to iframes - LogRocket Blog

Not a fan of iframes? This post provides an overview of the tag's best features, shows you how to use them, and how to secure them against vulnerabilities.

blog.logrocket.com

iframe 요소(인라인 프레임의 줄임말)는 아마도 가장 오래된 HTML 태그 중 하나이며
1997년 Microsoft Internet Explorer에 HTML 4.01과 함께 도입되었습니다.
모든 최신 브라우저에서 지원하지만 많은 개발자가 사용하지 말라고 조언하는 기사를 끝없이 작성합니다.
나쁜 평판에도 불구하고 iframe은 쓸만한 사용 사례가 많이 있습니다.
게다가, 보안을 유지하는 것은 그리 어렵지 않으므로 사용자의 컴퓨터가 감염되는 것에 대해 걱정할 필요가 없습니다.
iframe에 대한 당신의 의견을 확립할 수 있도록, 그리고개발 기술을 연마하는 데 도움이 되도록
이 논란의 여지가 있는 태그에 대해 알아야 할 모든 필수 사항을 다룹니다.
 
iframe 요소가 제공하는 대부분의 기능을 살펴보고
이를 사용하는 방법과 iframe이 까다로운 상황을 극복하는 데 어떻게 유용할 수 있는지에 대해 설명합니다.
마지막으로 잠재적인 취약성을 피하기 위해 iframe을 보호하는 방법에 대해 이야기하겠습니다.

Iframe은 무엇인가요? 언제 사용하나요?

개발자는 주로 iframe 태그를 사용해 현재 문서 내에 다른 HTML 문서를 포함합니다.
타사 위젯(유명한 Facebook 좋아요 버튼 등), YouTube 동영상 또는 웹사이트의 광고 섹션을 포함해야 하는 경우
이 도구를 사용했을 수 있습니다.
예를 들어, 아래 코드는 500px 정사각형을 표시하며 그 안에 Google 홈페이지가 있습니다.

 

<iframe src="https://www.lgcns.com/" height="500px" width="500px"></iframe>
다음은 Twitter에서 웹 페이지를 트윗하는 버튼을 표시하는 또 다른 예입니다.
<iframe src="https://platform.twitter.com/widgets/tweet_button.html" style="border: 0; width:130px; height:20px;"></iframe>

염두에 두어야 할 점은
iframe 자신만의 탐색 컨텍스트와 함께 독립적인 HTML 문서를 포함할 수 있다는 것입니다.
즉, 부모의 JavaScript 및 CSS에서 격리됩니다.

 

이는 iframe을 사용하는 유효한 목적 중 하나입니다.
현재 페이지 웹 애플리케이션과 iframe 콘텐츠 간의 분리를 제공합니다.

그럼에도 불구하고 이 가이드에서 볼 수 있듯이 분리가 그렇게 완벽하지는 않습니다.
iframe은 여전히 ​​성가시거나 악의적인 방식으로 작동할 수 있습니다.
예를 들어 팝업 트리거 또는 비디오 자동 재생입니다.

 

JavaScript 및 CSS로부터의 이러한 격리가 얼마나 편리한지 설명하기 위해 다음 두 가지 상황을 살펴보겠습니다.
애플리케이션에서 사용자는 이메일을 생성하고 템플릿으로 저장할 수 있습니다.
특정 페이지에서 사용자가 미리 보고 하나를 선택할 수 있도록 그 템플릿들을 나열해서 보여주어야 했습니다.

 

현재 웹 사이트의 CSS가 이러한 템플릿의 스타일에 영향을 미치지 않도록
srcdoc 속성과 함께 iframe을 사용하는 것이 가장 깔끔한 솔루션이라는 것을 알았습니다.

<iframe srcdoc="<html><body>The content you see here will never be affected by the CSS of its parent container. It supposed to be rendered in black on a white background.</body></html>"></iframe>
iframe이 제 목숨을 구한 또 다른 상황은 고객을 위해 WYSIWYG 편집기를 만들어야 했을 때였습니다.
이러한 편집기의 문제는 포커스와 선택을 유지하는 방법을 찾아야 한다는 것입니다.
 
iframe은 격리된 환경을 제공하므로 외부 클릭 시 포커스 또는 선택 항목이 손실되지 않습니다.

iframe과 부모 간의 통신 이벤트를 사용하여(이 기사의 뒷부분에서 자세한 방법을 설명함)
강력한 편집기를 순식간에 설계할 수 있었습니다.

당신이 알아야 할 속성들

현재까지 iframe의 동작이나 스타일을 사용자 정의하는 데 사용할 수 있는 8가지 속성이 있습니다.
<iframe

  src="https://www.lgcns.com/"    <!-- 임베드할 문서 주소 --> 

  srcdoc="<p>Some html</p>"    <!-- 보여줄 html 문서 --> 

  height="100px"               <!-- 높이 픽셀 -->

  width="100px"                <!-- 너비 픽셀 -->

  name="my-iframe"             <!-- js 참조를 위해 자주 사용하는 name 속성 -->

  allow="fullscreen"           <!-- 기능 정책 -->

  referrerpolicy="no-referrer" <!-- iframe 콘텐츠를 가져올 때 보낼 리퍼러 설정 -->

  sandbox="allow-same-origin"  <!-- iframe의 제한 사항을 설정합니다(자세한 내용은 아래 참조). -->

></iframe>
위에 나열된 것보다 더 많이 있지만 HTML5에서는 더 이상 지원되지 않습니다:
ex ) align, frameborder, longdesc, marginheight, marginwidth 및 scrolling.
참고: 기본적으로 iframe 요소 주위에는 테두리가 있습니다.
이를 제거하려면 style 속성을 사용하여 border CSS 속성을 none으로 설정합니다

iframe 이벤트 및 통신

Loading and errors

iframe은 문서이기 때문에 대부분의 전역 이벤트 핸들러(global event handlers)를 사용할 수 있습니다.
iframe을 초기화할 때 스피너 또는 특정 메시지를 표시하는 것과 같이 사용자 경험을 개선할 수 있으며,
아래 두 가지가 유용합니다.
  • load 이벤트. iframe이 완전히 로드되면 트리거됩니다.
    • 즉, 모든 정적 asset이 다운로드되었으며 DOM 트리의 모든 요소에서 로드 이벤트가 발생했습니다.
  • error 이벤트. 오류 발생 시 트리거됩니다.
각각 onload 및 onerror 속성을 사용하여 이벤트를 리스닝 할 수 있습니다.
<iframe src="https://logrocket.com/" onload="onLoad()" onerror="onError()"></iframe>
또는 코딩해서 iframe에 리스너를 추가할 수 있습니다.
// For a new iframe
const iframe = document.createElement("iframe");

iframe.onload = function() {
  console.log("The iframe is loaded");
};
iframe.onerror = function() {
  console.log("Something wrong happened");
};

iframe.src = "https://logrocket.com/";
document.body.appendChild(iframe);

// For an existing iframe
const iframe = document.querySelector('.my-iframe');

iframe.onload = function() {
  console.log("The iframe is loaded");
}
iframe.onerror = function() {
  console.log("Something wrong happened");
}

아이프레임과 통신하기

부모와 iframe 간에 메시지를 보내는 것은 매우 쉽습니다. 여기에 설명된(documented here) postMessage 기능을 사용해야 합니다.

부모에서 아이프레임으로

부모에서 자식 아이프레임으로 보내고

const myiframe = document.getElementById('myIframe')

myIframe.contentWindow.postMessage('message', '*');

자식 아이프레임에서 리스닝합니다.

window.onmessage = function(event){
    if (event.data == 'message') {
        console('Message received!');
    }
};

아이프레임에서 부모로

iframe에서 메시지 보내기:
window.top.postMessage('reply', '*')

부모에서 메세지 리스닝하기

window.onmessage = function(event){
    if (event.data == 'reply') {
        console('Reply received!');
    }
};
참고: 메시지는 한번 실행되고 없어지기 때문에 만약 적절한 에러 핸들링 로직이 없다면, 디버깅할 때 까다로운 상황에 처할 수 있습니다.

보안

iframe을 사용하는 경우 대부분 제어할 수 없는 타사에서 오는 콘텐츠를 처리합니다.
따라서 애플리케이션의 잠재적인 취약성과 나쁜 사용자 경험(성가신 비디오 자동 재생과 같은)을 처리해야 합니다.
고맙게도 특정 기능을 블랙리스트 또는 화이트리스트에 추가할 수 있습니다.
sandbox 속성과 allow 속성을 사용해야 합니다.
리소스가 작업을 수행하는 데 필요한 최소 수준의 기능을 항상 부여합니다.
보안 전문가들은 이 개념을 "최소 권한의 원칙"이라고 부릅니다.(“the principle of least privilege.”)

sandbox 속성

Flag Details
allow-forms Allows form submission.
allow-modals Allows the resource to open new modal windows.
allow-orientation-lock Allows the resource to lock the screen orientation.
allow-pointer-lock Allows the resource to use the Pointer Lock API.
allow-popups Allows the resource to open new popups or tabs.
allow-popups-to-escape-sandbox Allows the resource to open new windows that will not inherit the sandboxing.
allow-presentation Allows the resource to start a presentation session.
allow-same-origin Allows the resource to maintain its origin.
allow-scripts Allows the resource to run scripts.
allow-top-navigation Allows the resource to navigate the top-level browsing context.
allow-top-navigation-by-user-activation Allows the resource to navigate the top-level browsing context, but only if initiated by a user gesture.
iframe에 부여할 권한을 결정하는 것은 사용자의 몫입니다.

예를 들어 iframe이 양식을 제출하고 새 모달 창을 열기만 하면 되는 경우
샌드박스 속성을 구성하는 방법은 다음과 같습니다.

<iframe sandbox="allow-forms allow-modals" src="https://www.something.com/"></iframe>
한 기능이 아이프레임 내에서 제대로 동작하지 않는 상황의 경우 플래그가 없기 때문일 수 있습니다.
신속하게 디버깅하려면 이에 대해 더 많이 알고 있어야 합니다.
또한 샌드박스 속성을 사용하지 않으면 iframe이 완전히 샌드박스화 됩니다.

즉, iframe 내부의 JavaScript가 실행되지 않으며 위에 나열된 모든 권한이 제한됩니다.
(예: 새 창 만들기 또는 플러그인 로드).

빈 샌드박스 속성은 주로 정적 콘텐츠에 사용되지만, 다른 리소스가 존재할 경우 기능이 상당히 제한될 수 있습니다.
<iframe sandbox="allow-forms allow-modals" src="https://www.something.com/"></iframe>
참고: 샌드박스 속성은 Internet Explorer 9 및 이전 버전에서 지원되지 않습니다.

allow 속성

allow 속성은 현재 실험적이며 Chromium 기반 브라우저에서만 지원됩니다.
iframe이 가속도계, 배터리 정보 또는 카메라에 액세스할 수 있도록 해당 기능을 화이트리스트에 추가할 수 있습니다.

 

25개 이상의 사용 가능한 플래그가 있으므로 여기에 모두 나열하지 않겠습니다. Mozilla 기능 정책 문서에서 찾아볼 수 있습니다.
아래 표에 가장 인기있는 것을 요약했습니다.
Flag Details
accelerometer Allows access the Accelerometer interface
ambient-light-sensor Allows access the AmbientLightSensor interface
autoplay Allows to autoplay video and audio files
battery Allows access to the Battery Status API
camera Allows access to the camera
fullscreen Allows access to fullscreen mode
geolocation Allows access to the Geolocation API
gyroscope Allows access to the Sensors API Gyroscope interface
magnetometer Allows access to the Sensors API Magnetometer interface
microphone Allows access to the device microphone
midi Allows access to the Web MIDI API
payment Allows access to the Payment Request API
usb Allows access to the WebUSB API
vibrate Allows access to the Vibration API

iframe에 대해 알아야 할 사항

iframe을 지원하지 않는 브라우저를 처리하는 방법

브라우저가 iframe을 지원하지 않으면 여는 <iframe> 태그와 닫는 </iframe> 태그 사이에 포함된 내용이 표시됩니다.
이러한 불쌍한 사용자를 위한 대체 수단으로 경고 메시지를 배치하는 것에 대해 항상 생각해야 합니다.
<iframe>
  <p>Your browser does not support iframes.</p>
</iframe>
iframe이 실제로 부모 문서의 일부인 것처럼(즉, 테두리와 스크롤바가 없음) 렌더링할 수 있나요?

정확히 이 목적을 위해 Seamless 속성이 도입되었습니다.
아직 실험적이며 제대로 지원되지 않습니다(Chromium 기반 브라우저만 사용 가능)

 

또한 이 글을 쓰는 시점엔 W3C HTML5 사양의 일부가 아닙니다.
(주 : Seamless 속성은 W3C 및 WHATWG hrml 사양 모두에서 제거되었으며 보안 및 기타 이유로 인해 브라우저에서 구현이 제거되었습니다. https://caniuse.com/#feat=iframe-seamless)
<iframe seamless src="https://logrocket.com/"></iframe>

iframe이 내 웹사이트의 SEO에 영향을 주나요?

오랫동안 크롤러는 이를 이해할 수 없었지만 더 이상 그렇지 않습니다.
내가 찾은 가장 관련성이 높은 답변은 이 기사(from this article)에서 나온 것이며 오늘의 결론은 다음과 같습니다.
검색 엔진은 iframe의 콘텐츠를 다른 웹사이트에 속하는 것으로 간주하기 때문에,
Iframe은 검색 엔진 순위에 도움이 되지도 해가 되지도 않는 경향이 있습니다.
따라서 iframe을 통해 표시되는 콘텐츠는 색인이 생성되지 않거나
Google 검색 결과에 표시되지 않을 수 있다고 가정하는 것이 가장 좋습니다.
해결 방법은 표시되는 콘텐츠에 대한 추가 텍스트 기반 링크를 제공하여
Googlebot이 이 콘텐츠를 크롤링하고 색인을 생성할 수 있도록 하는 것입니다.

참고: 오늘날의 웹 크롤러는 일반적으로 중복 콘텐츠 문제를 인식하므로
중복 콘텐츠 문제에 대해서도 걱정할 필요가 없습니다.

iframe이 내 웹사이트의 로딩 속도에 영향을 주나요?

페이지의 모든 iframe은 사용된 메모리와 대역폭과 같은 다른 컴퓨팅 리소스를 증가시킵니다.
따라서 모니터링 없이 iframe을 과도하게 사용해서는 안 됩니다.
그렇지 않으면 페이지 성능이 저하될 수 있습니다.
iframe이 페이지 속도를 늦추는 것을 방지하려면 페이지를 지연 로드하는 것이 좋습니다(즉, 사용자가 페이지 근처에서 스크롤할 때와 같이 필요할 때만 로드).
태그에 loading="lazy" 속성을 추가하기만 하면 됩니다.
이 글을 쓰는 시점에서 모든 최신 Chromium 기반 브라우저가 이를 지원합니다.
모든 곳에서 작동하는 lazyload library 라이브러리에 관심이 있을 것입니다.
<iframe src="https://logrocket.com/" loading="lazy"></iframe>
참고: loading="lazy" 속성은 img 태그에서도 동작합니다.

iframe을 반응형으로 만들려면 어떻게 해야 하죠?

iframe을 반응형으로 만드는 방법은 수도 없이 많습니다.
대신 두 가지 훌륭한 기사를 링크하겠습니다.
  • 이 첫 번째 문서(아마도 가장 간단한 솔루션)에서는 iframe을 다른 HTML 요소로 래핑하고 여기에 몇 가지 CSS 속성을 추가하여 이를 달성하는 방법을 보여줍니다.
  • 이 두 번째 문서에서는 가로 세로 비율을 처리하여 iframe을 반응형으로 만드는 방법을 보여줍니다.
  • Iframe Resizer Library도 있지만 실제로 필요하지 않은 추가 기능이 많이 제공된다는 점을 염두에 두십시오.
참고: 프로젝트에서 부트스트랩 라이브러리를 사용하는 경우 즉시 iframe을 반응형으로 만들 수 있는
embed-responsive 및 embed-responsive-16by9가 있습니다.
<div class="embed-responsive embed-responsive-16by9">
  <iframe src="https://logrocket.com/" loading="lazy"></iframe>
</div>

iframe이 로딩되는 동안 발생하는 흰색 플래시를 방지하는 방법

이 아티클(In this article)에서 Chris Coyier는 일부 CSS를 사용하여 페이지의 모든 iframe을 숨기고 창이 로드될 때까지 제거한 다음 표시되도록 하는 작은 스니펫을 공유합니다.

iframe 컨텐츠 다시 불러오기

contentWindow를 사용하여 iframe의 창 요소에 액세스할 수 있으므로 다음을 수행해야 합니다.

// Get the iframe
const iframe = document.getElementById('myIframe');
    
// Reload the iframe
iframe.contentWindow.location.reload();

보너스: iframe 접근성 정보

대부분의 경우 스크린 리더는 페이지에 iframe이 있음을 나타냅니다.
많은 사람들이 iframe 내부를 탐색할 수도 있습니다.

iframe이 다른 웹페이지를 포함하지 않고 대신 비디오 플레이어나 광고와 같은 외부 콘텐츠를 포함하는 경우
태그에 title을 추가하는 것이 필수적입니다.
태그에 title을 추가하면 사용자에게 iframe이 무엇인지에 대한 더 많은 컨텍스트를 제공합니다.

<iframe src="an_ad.html" title="I contain an advertisement"></iframe>

명심해야 할 또 다른 사항은 iframe에 읽을 수 없는 콘텐츠(예: JavaScript로 제작된 비디오 게임)가 포함된 경우
aria-hidden 속성을 사용하여 스크린 리더 사용자에게 콘텐츠를 숨겨야 한다는 것입니다.

<iframe src="a_video_game.com" title="I contain a video game" aria-hidden="true"></iframe>
지원하지 않는 모든 구형 브라우저의 경우 iframe 내부에 일부 콘텐츠를 포함해야 합니다.
모든 사람에게 해당 부분에 어떤 내용이 있는지에 관한 정보를 제공할 수 있습니다.
<iframe>
  <p>Your browser does not support iframes.</p>
</iframe>

결론

iframe은 신뢰할 수 없는 콘텐츠를 로드하는 경우 안전하지 않을 수 있지만 몇 가지 중요한 이점도 제공합니다.
따라서 개발자의 무기고에서 완전히 제거해서는 안 되며 필요한 상황에서만 사용하십시오.

참고

반응형