Embedded 콘텐츠란?

외부 리소스를 HTML 문서에 삽입하는 Embedded 콘텐츠의 특성과 대표 요소들을 이해하고, 올바른 삽입 방법과 대체 콘텐츠 제공 방법을 익힙니다

입문 15분 Embedded 콘텐츠 외부 리소스 img iframe

HTML 문서는 텍스트와 마크업만으로 구성되지 않습니다. 이미지, 동영상, 오디오, 외부 웹페이지, 인터랙티브 그래픽 등 다양한 외부 리소스를 문서 안에 삽입하여 풍부한 사용자 경험을 만들어낼 수 있는데, 이 역할을 담당하는 것이 바로 Embedded 콘텐츠입니다. Embedded 콘텐츠는 HTML 콘텐츠 모델에서 독특한 위치를 차지합니다. 다른 콘텐츠 카테고리의 요소들이 문서 자체의 구조와 텍스트를 다루는 반면, Embedded 콘텐츠 요소들은 외부에서 가져온 리소스를 문서의 일부로 통합하는 역할을 합니다. 이 카테고리에 속하는 요소들의 동작 원리와 특성을 이해하는 것은 웹 페이지의 성능, 접근성, 보안을 모두 고려한 개발을 위해 필수적입니다.

🔑 핵심 특징

  • 외부 리소스 참조 모델: Embedded 요소들은 자체적으로 콘텐츠를 갖지 않고, src, data 등의 속성을 통해 외부 리소스를 참조하여 렌더링합니다
  • 대체 콘텐츠(Fallback) 메커니즘: 외부 리소스 로드에 실패하거나 해당 미디어를 지원하지 않는 환경을 위해 대체 콘텐츠를 제공하는 구조를 갖고 있습니다
  • 고유한 렌더링 영역 확보: Embedded 요소들은 문서 흐름 안에서 자체적인 사각형 영역(replaced element)을 확보하며, 일반 텍스트 요소와는 다른 레이아웃 규칙을 따릅니다
  • 보안 경계(Security Boundary) 형성: 특히 iframe과 같은 요소는 별도의 브라우징 컨텍스트를 생성하여, 외부 콘텐츠와 호스트 문서 사이에 보안 경계를 형성합니다
  • 비동기 로딩 특성: 외부 리소스를 네트워크를 통해 가져오기 때문에 본질적으로 비동기적이며, 이로 인해 페이지 로딩 성능에 직접적인 영향을 미칩니다

🌐 실무에서의 영향

Embedded 콘텐츠에 대한 깊은 이해는 현대 웹 개발의 여러 핵심 영역에 직접적으로 연결됩니다. 이미지 최적화 하나만 보더라도, img 요소의 loading, decoding, srcset, sizes 속성을 올바르게 활용하면 페이지 로딩 속도를 극적으로 개선할 수 있습니다. iframe을 사용할 때 sandbox 속성과 allow 속성을 적절히 설정하지 않으면 XSS 공격이나 클릭재킹 같은 보안 취약점에 노출될 수 있으므로, 보안 관점에서의 이해도 매우 중요합니다. 또한 alt 텍스트 제공, title 속성 활용 등 접근성 측면에서도 Embedded 요소의 올바른 사용법을 아는 것이 필수적입니다. 결국 Embedded 콘텐츠를 제대로 다루는 것은 성능, 보안, 접근성이라는 웹 개발의 세 가지 핵심 축을 모두 관통하는 역량이며, 단순히 요소를 삽입하는 것을 넘어 그 동작 원리를 이해해야 실무에서 발생하는 다양한 문제에 대응할 수 있습니다.


핵심 개념

Replaced Element의 이해

입문

Embedded 콘텐츠 요소는 ‘대체 요소(Replaced Element)‘라는 특별한 성질을 가지고 있어요. 이 요소들은 직접 내용을 담지 않고, 외부에서 가져온 것을 대신 보여줘요.

🖼️ 액자와 비슷한 원리예요 벽에 걸린 액자를 생각해보세요. 액자 자체는 그림이 아니에요. 액자는 ‘틀’이고, 그 안에 사진이나 그림을 넣어서 보여주는 거예요. HTML의 img 태그도 마찬가지예요. 태그 자체는 이미지가 아니라 ‘이미지를 보여줄 틀’이에요.

📦 빈 상자에 물건을 채우는 것 택배 상자를 떠올려보세요. 상자는 비어 있지만, 주소(src 속성)를 보고 물건을 가져와서 채워 넣어요. Embedded 요소도 비슷해요. 태그 자체는 비어 있지만, 주소를 알려주면 거기서 이미지나 영상을 가져와서 보여줘요.

📐 자기만의 공간을 차지해요 일반 글자는 줄을 따라 흐르지만, 이미지나 영상은 자기만의 네모난 공간을 확보해요. 마치 교실에서 글씨는 줄노트를 따라 쓰지만, 사진은 정해진 크기의 공간에 붙이는 것과 같아요.

🔄 원래 크기가 정해져 있어요 사진은 찍을 때 크기가 정해져 있죠? Embedded 요소도 마찬가지로 원래 리소스의 크기(고유 치수)를 가지고 있어요. 물론 CSS로 크기를 바꿀 수 있지만, 아무 설정이 없으면 원래 크기대로 보여줘요.

💡 왜 이걸 알아야 하나요? 이미지나 영상이 화면에서 이상하게 찌그러지거나 레이아웃이 깨지는 문제의 대부분은 이 ‘대체 요소’의 특성을 모르기 때문에 생겨요. 원리를 이해하면 이런 문제를 쉽게 해결할 수 있어요.

중급

Embedded 콘텐츠 요소들은 대부분 Replaced Element(대체 요소)에 해당합니다. Replaced Element란 요소의 렌더링 결과가 CSS 포매팅 모델이 아닌 외부 리소스에 의해 결정되는 요소를 말합니다.

Replaced Element의 핵심 특성

일반적인 HTML 요소(<p>, <div> 등)는 자식 노드의 내용에 따라 렌더링됩니다. 반면 Replaced Element는 src, data 같은 속성이 가리키는 외부 리소스의 내용으로 대체되어 렌더링됩니다. 대표적인 Replaced Element로는 <img>, <video>, <iframe>, <canvas>, <embed>, <object> 등이 있습니다.

고유 치수(Intrinsic Dimensions)

Replaced Element는 고유 너비(intrinsic width), 고유 높이(intrinsic height), 고유 비율(intrinsic ratio)을 가질 수 있습니다. CSS로 크기를 명시하지 않으면 이 고유 치수를 기반으로 렌더링됩니다.

<!-- 고유 치수를 가진 img 요소 -->
<!-- 원본 이미지가 800x600이면 CSS 없이도 800x600으로 렌더링 -->
<img src="photo.jpg" alt="풍경 사진">

<!-- width/height 속성으로 고유 치수 힌트 제공 -->
<!-- 브라우저가 이미지 로드 전에 공간을 확보하여 레이아웃 시프트 방지 -->
<img src="photo.jpg" alt="풍경 사진" width="800" height="600">

<!-- CSS로 크기 변경 시 고유 비율 유지를 위해 object-fit 활용 -->
<img src="photo.jpg" alt="풍경 사진"
     style="width: 400px; height: 300px; object-fit: cover;">

레이아웃 시프트(CLS) 문제

Replaced Element의 고유 치수가 확정되기 전(리소스 로드 전)에는 브라우저가 요소의 크기를 알 수 없어 레이아웃 시프트가 발생합니다. 이를 방지하기 위해 widthheight 속성을 HTML에 명시하거나, CSS의 aspect-ratio 속성을 활용하는 것이 권장됩니다.

심화

Replaced Element는 CSS 명세와 HTML 명세가 교차하는 지점에서 정의되며, 일반 요소와는 근본적으로 다른 렌더링 파이프라인을 거칩니다.

CSS 명세에서의 Replaced Element 정의

CSS Display Module Level 3에서 Replaced Element는 “CSS 포매팅 모델의 범위를 벗어나는 고유 치수(intrinsic dimensions)를 가진 요소”로 정의됩니다. 구체적으로 CSS2.1 Section 10.3.2와 10.6.2에서 Replaced Element의 너비와 높이 계산 알고리즘이 명시되어 있으며, 일반 요소의 박스 모델 계산과는 별도의 규칙이 적용됩니다.

고유 치수 결정 우선순위(CSS Images Level 3, Section 5.2):

  1. 지정된 크기(Specified Size): CSS width/height 속성
  2. 고유 치수(Intrinsic Dimensions): 리소스 자체의 너비, 높이, 비율
  3. 기본 객체 크기(Default Object Size): 300px x 150px (CSS2.1 기본값)

이 알고리즘은 object-fitobject-position 속성에 의해 조율됩니다. object-fit: contain은 고유 비율을 유지하면서 지정된 영역에 맞추고, object-fit: cover는 영역을 완전히 채우되 넘치는 부분을 클리핑합니다.

브라우저 렌더링 엔진에서의 처리

Blink(Chrome) 엔진에서 Replaced Element는 LayoutReplaced 클래스로 구현되며, 일반 LayoutBlock과는 다른 레이아웃 경로를 따릅니다. 핵심 차이점은 내부 콘텐츠(intrinsic content)의 크기 결정이 외부 리소스 디코더(ImageDecoder, VideoDecoder 등)에 위임된다는 점입니다.

이미지 디코딩의 경우, Blink은 ImageResource 객체를 통해 점진적 디코딩(Progressive Decoding)을 수행합니다. JPEG의 경우 스캔 데이터가 도착할 때마다 부분 렌더링이 가능하며, 이는 decoding 속성의 async 값과 연계되어 메인 스레드 블로킹을 방지합니다.

Gecko(Firefox) 엔진은 nsImageFramensVideoFrame 등 미디어 타입별 전용 프레임을 사용하며, 리소스 로딩 상태(loading, complete, broken)에 따라 프레임의 렌더링 전략이 동적으로 전환됩니다.

대체 콘텐츠(Fallback Content) 메커니즘

입문

외부에서 가져오는 콘텐츠는 항상 성공적으로 불러와진다는 보장이 없어요. 그래서 HTML은 ‘대체 콘텐츠’라는 안전장치를 마련해 두었어요.

🚪 비상구가 있는 건물 건물에는 항상 비상구가 있어요. 평소에는 정문으로 다니지만, 문제가 생기면 비상구를 사용하죠. Embedded 콘텐츠도 마찬가지예요. 이미지나 영상을 못 불러오면, 미리 준비해둔 ‘비상 콘텐츠’를 대신 보여줘요.

📝 이미지 대신 글로 설명하기 친구에게 사진을 보내려는데 전송이 안 될 때, “바다가 보이는 카페에서 찍은 사진이야”라고 글로 설명하잖아요? 웹에서도 이미지를 못 보여줄 때 alt 속성에 적어둔 설명 글을 대신 보여줘요.

👀 눈으로 볼 수 없는 사람을 위해서도 시각 장애가 있는 분들은 화면 낭독기(스크린 리더)라는 프로그램으로 웹을 이용해요. 이 프로그램은 이미지를 볼 수 없으니까, alt에 적힌 설명을 소리로 읽어줘요. 대체 콘텐츠는 이미지가 깨졌을 때뿐만 아니라, 모든 사용자를 위한 배려예요.

🎬 영상도 대체 콘텐츠가 있어요 video 태그 안에 글을 넣어두면, 영상을 지원하지 않는 브라우저에서 그 글이 대신 나타나요. 마치 극장 문이 잠겨 있을 때 “오늘 공연 내용은…”이라고 적힌 안내문을 보는 것과 같아요.

💡 왜 대체 콘텐츠가 중요한가요? 인터넷이 느리거나, 이미지 서버가 고장 나거나, 또는 시각 장애가 있는 사용자가 방문할 때, 대체 콘텐츠가 없으면 그 부분이 완전히 사라져 버려요. 대체 콘텐츠는 어떤 상황에서도 정보를 전달할 수 있도록 하는 안전장치예요.

중급

Embedded 콘텐츠 요소들은 외부 리소스에 의존하기 때문에, 리소스 로드 실패나 미지원 환경에 대비한 Fallback Content(대체 콘텐츠) 메커니즘을 제공합니다. 요소마다 대체 콘텐츠를 제공하는 방식이 다릅니다.

요소별 Fallback 제공 방식

요소Fallback 방식설명
<img>alt 속성이미지 로드 실패 시 텍스트 표시
<video>자식 콘텐츠태그 사이의 HTML이 대체 콘텐츠
<audio>자식 콘텐츠태그 사이의 HTML이 대체 콘텐츠
<object>자식 콘텐츠중첩된 <object> 또는 HTML
<iframe>자식 콘텐츠태그 사이의 HTML이 대체 콘텐츠
<canvas>자식 콘텐츠JavaScript 미지원 시 표시
<!-- img: alt 속성으로 대체 텍스트 제공 -->
<img src="chart.png" alt="2024년 월별 매출 추이 그래프">

<!-- video: 태그 사이에 대체 콘텐츠 -->
<video src="demo.mp4" controls>
  <p>브라우저가 동영상을 지원하지 않습니다.
     <a href="demo.mp4">동영상 다운로드</a></p>
</video>

<!-- object: 중첩 fallback 체인 -->
<object data="interactive.swf" type="application/x-shockwave-flash">
  <object data="fallback.png" type="image/png">
    <p>콘텐츠를 표시할 수 없습니다.</p>
  </object>
</object>

alt 속성의 올바른 사용

alt 속성은 단순히 “이미지 설명”이 아니라, 이미지가 전달하는 정보를 텍스트로 동등하게 대체하는 역할입니다. 장식용 이미지는 빈 alt=""를 사용하고, 정보를 전달하는 이미지는 그 정보를 구체적으로 기술해야 합니다. alt 속성을 아예 생략하면 스크린 리더가 파일명을 읽어버리는 문제가 발생합니다.

<!-- 정보 전달 이미지: 구체적인 대체 텍스트 -->
<img src="error-icon.png" alt="오류 발생">

<!-- 장식용 이미지: 빈 alt (스크린 리더가 무시) -->
<img src="decorative-line.png" alt="">

<!-- 차트/그래프: 데이터를 텍스트로 기술 -->
<img src="sales-chart.png"
     alt="2024년 매출: 1월 100만, 2월 150만, 3월 200만으로 증가 추세">

심화

Fallback Content 메커니즘은 HTML Living Standard에서 요소별로 다른 처리 모델을 따르며, 브라우저의 리소스 로딩 파이프라인과 밀접하게 연결되어 있습니다.

HTML Living Standard의 img 요소 처리 모델

HTML Living Standard Section 4.8.3에 따르면, img 요소는 내부적으로 4가지 상태를 가집니다:

  1. Unavailable: 초기 상태, 리소스 요청 전
  2. Partially available: 고유 치수는 확정되었으나 디코딩 미완료
  3. Completely available: 리소스 로드 및 디코딩 완료
  4. Broken: 리소스 로드 실패 또는 디코딩 오류

Broken 상태에서 alt 속성이 존재하면 대체 텍스트를 인라인 요소처럼 렌더링하고, alt 속성이 없으면 깨진 이미지 아이콘(broken image indicator)을 표시합니다. 이때 요소가 Replaced Element에서 Non-replaced Element로 전환되어 일반 인라인 박스의 레이아웃 규칙을 따르게 됩니다.

object 요소의 Fallback 체인 알고리즘

<object> 요소는 HTML 명세에서 가장 복잡한 Fallback 메커니즘을 가집니다. Section 4.8.7의 리소스 표현 결정 알고리즘(Determine the Object’s Representation)은 다음 순서로 실행됩니다:

  1. data 속성의 URL로 리소스 페치(Fetch) 시도
  2. Content-Type 또는 type 속성으로 MIME 타입 결정
  3. 해당 MIME 타입의 핸들러(플러그인, 내장 렌더러) 탐색
  4. 핸들러가 없거나 로드 실패 시 → 자식 콘텐츠로 Fallback
  5. 자식에 <object>가 있으면 재귀적으로 같은 알고리즘 적용

이 재귀적 Fallback 체인은 점진적 기능 저하(Graceful Degradation)의 대표적 구현입니다. 단, 각 단계에서 네트워크 요청이 발생할 수 있어 성능에 영향을 줄 수 있습니다.

접근성 명세와의 연계

WAI-ARIA(Web Accessibility Initiative - Accessible Rich Internet Applications)와 WCAG 2.1(Web Content Accessibility Guidelines) 기준에서 Embedded 콘텐츠의 Fallback은 단순한 기능이 아니라 법적 요구사항에 해당합니다. WCAG 2.1 성공 기준 1.1.1(Non-text Content, Level A)은 모든 비텍스트 콘텐츠에 동등한 텍스트 대안을 요구합니다.

접근성 트리(Accessibility Tree)에서 img 요소는 alt 속성의 유무에 따라 다르게 처리됩니다. alt가 있으면 role="img"와 함께 접근 가능한 이름(Accessible Name)으로 노출되고, alt=""이면 role="presentation"으로 처리되어 접근성 트리에서 제거됩니다. alt 속성 자체가 없으면 브라우저가 파일명이나 URL을 접근 가능한 이름으로 사용하는데, 이는 “IMG_20240315_123456.jpg” 같은 무의미한 정보가 읽히는 문제를 발생시킵니다.

브라우징 컨텍스트와 보안 경계

입문

웹페이지 안에 다른 웹페이지를 넣을 수 있다는 거 알고 있나요? 이때 안전하게 넣는 방법이 중요해요.

🏠 집 안의 방처럼 분리되어 있어요 큰 집 안에 여러 방이 있잖아요. 각 방에는 문이 있어서, 문을 잠그면 다른 방에서 들어올 수 없어요. 웹에서 iframe이라는 태그로 다른 웹페이지를 넣으면, 그 페이지는 별도의 ‘방’에서 실행돼요.

🔒 왜 분리해야 하나요? 만약 다른 사람이 만든 웹페이지를 내 페이지에 넣었는데, 그 페이지가 내 페이지의 정보를 마음대로 볼 수 있다면 위험하겠죠? 그래서 브라우저는 자동으로 ‘벽’을 세워서, 넣어둔 페이지가 바깥 페이지의 정보에 접근하지 못하게 막아요.

🎛️ 허용 범위를 직접 정할 수 있어요 sandbox라는 속성을 사용하면, 넣어둔 페이지가 할 수 있는 일을 세밀하게 조절할 수 있어요. 마치 놀이터에 울타리를 치고, “여기서만 놀아”라고 범위를 정하는 것과 같아요. 스크립트 실행, 폼 제출, 팝업 생성 등을 하나씩 허용하거나 차단할 수 있어요.

🌐 유튜브 영상을 넣을 때도 이 원리가 작동해요 웹페이지에 유튜브 영상을 넣을 때 사용하는 것이 바로 iframe이에요. 유튜브 페이지가 별도의 ‘방’에서 실행되니까, 유튜브가 여러분의 페이지 내용을 볼 수 없고, 반대로 여러분의 페이지도 유튜브 내부를 함부로 조작할 수 없어요.

💡 안전하게 외부 콘텐츠를 활용하는 핵심이에요 이 ‘분리’와 ‘보안 경계’ 개념을 이해하면, 외부에서 가져온 콘텐츠를 안전하게 활용하면서도 사용자의 정보를 보호할 수 있어요.

중급

iframe 요소는 독립적인 브라우징 컨텍스트(Browsing Context)를 생성합니다. 이는 부모 문서와 완전히 분리된 실행 환경으로, 각각 독립된 window 객체, document 객체, JavaScript 실행 컨텍스트를 갖습니다.

동일 출처 정책(Same-Origin Policy)

브라우저의 핵심 보안 메커니즘인 동일 출처 정책에 의해, 출처(프로토콜 + 호스트 + 포트)가 다른 iframe은 부모 문서의 DOM에 접근할 수 없습니다. 동일 출처인 경우에만 window.parent, window.frames 등을 통한 상호 접근이 허용됩니다.

<!-- 기본 iframe: 동일 출처 정책만 적용 -->
<iframe src="https://example.com/widget"></iframe>

<!-- sandbox: 모든 권한 차단 후 필요한 것만 허용 -->
<iframe src="https://example.com/widget"
        sandbox="allow-scripts allow-same-origin">
</iframe>

<!-- sandbox 주요 값 -->
<!-- allow-scripts: JavaScript 실행 허용 -->
<!-- allow-same-origin: 동일 출처 취급 허용 -->
<!-- allow-forms: 폼 제출 허용 -->
<!-- allow-popups: 팝업 창 허용 -->

<!-- allow: Feature Policy로 기능 제어 -->
<iframe src="https://example.com/camera-app"
        allow="camera; microphone"
        sandbox="allow-scripts">
</iframe>

sandbox 속성의 동작 원리

sandbox 속성을 지정하면 iframe에 대한 모든 권한이 차단된 상태에서 시작합니다. 이후 allow-* 토큰을 추가하여 필요한 권한만 개별적으로 부여하는 화이트리스트 방식입니다.

주의할 점은 allow-scriptsallow-same-origin을 동시에 지정하면, iframe 내 스크립트가 sandbox 속성 자체를 제거할 수 있어 보안이 무력화될 수 있다는 것입니다. 신뢰할 수 없는 콘텐츠에는 이 조합을 사용하지 않아야 합니다.

심화

iframe의 브라우징 컨텍스트와 보안 모델은 HTML Living Standard의 가장 복잡한 영역 중 하나이며, 다중 명세가 교차하는 지점에 위치합니다.

HTML Living Standard의 브라우징 컨텍스트 모델

HTML Living Standard Section 7.1에 따르면, 브라우징 컨텍스트(Browsing Context)는 Document 객체를 표시하는 환경으로, 각 브라우징 컨텍스트는 고유한 WindowProxy 객체와 세션 히스토리(Session History)를 갖습니다.

iframe이 생성하는 것은 중첩 브라우징 컨텍스트(Nested Browsing Context)로, 부모 브라우징 컨텍스트와 트리 구조를 형성합니다. 이 트리는 window.parent, window.top, window.frames 등의 API로 탐색 가능하지만, 동일 출처 정책에 의해 실제 접근이 제한됩니다.

최근 명세에서는 브라우징 컨텍스트가 브라우징 컨텍스트 그룹(Browsing Context Group)으로 그룹화되며, Cross-Origin-Opener-Policy(COOP)와 Cross-Origin-Embedder-Policy(COEP) 헤더에 의해 그룹 간 분리가 이루어집니다. 이 분리가 완료된 상태에서만 SharedArrayBuffer나 고정밀 타이머(performance.now() 마이크로초 정밀도) 같은 위험할 수 있는 API가 활성화됩니다.

프로세스 격리(Site Isolation) 아키텍처

Chromium의 Site Isolation은 각 출처(origin)를 별도의 렌더러 프로세스에서 실행하는 보안 아키텍처입니다. iframe이 교차 출처(cross-origin) 문서를 로드하면, 해당 iframe은 부모 문서와 다른 프로세스에서 렌더링됩니다.

이 구현의 핵심은 OOPIF(Out-of-Process iFrame)라는 메커니즘입니다. OOPIF에서는 iframe의 렌더링 결과가 컴포지터 레이어(Compositor Layer)로 전달되어, 부모 프로세스의 컴포지터가 최종 합성을 수행합니다. 이로 인해 Spectre 같은 사이드 채널 공격(Side-Channel Attack, 프로세스 메모리를 관측하여 정보를 탈취하는 공격)에 대한 프로세스 레벨 격리가 달성됩니다.

Firefox의 Fission 프로젝트도 유사한 목표를 가지며, 프로세스 단위 격리를 통해 각 교차 출처 iframe의 메모리 공간을 물리적으로 분리합니다.

Permissions Policy(구 Feature Policy) 명세

W3C Permissions Policy 명세는 iframe의 기능 접근을 세밀하게 제어합니다. allow 속성으로 지정된 정책은 HTTP 헤더의 Permissions-Policy와 결합되어 최종 권한이 결정됩니다.

권한 결정 알고리즘은 두 단계로 동작합니다:

  1. HTTP 헤더의 Permissions-Policy가 해당 기능의 허용 출처를 정의
  2. iframe의 allow 속성이 자식 브라우징 컨텍스트에 대한 추가 제한을 적용

두 정책의 교집합(intersection)이 최종 허용 범위가 됩니다. 예를 들어, 서버가 Permissions-Policy: camera=self로 설정하면, iframe에 allow="camera"를 지정해도 교차 출처 iframe은 카메라에 접근할 수 없습니다.