시각적 콘텐츠 조각 - 게시 URL을 사용하여 게재 visual-content-fragments-deliver-with-the-publish-url

첨부된 HTML 템플릿이 있는 모델을 기반으로 하는 콘텐츠 조각이 게시되면 해당 조각의 렌더링된 HTML을 다음 구조의 URL에서 Adobe Experience Manager(AEM) as a Cloud Service 게시 계층을 통해 사용할 수 있습니다.

https://publish-p<programId>-e<envId>.adobeaemcloud.com/adobe/stable/previewtemplates/contentFragments/<templateId>/<fragmentId>/<variation>.html

이 URL은 모든 웹 컨텍스트에 포함될 수 있는 자체 포함된 HTML 문서(인라인 CSS 및 구조 포함)를 반환합니다.

임베드 기법 — 개요 embedding-techniques-overview

호스트 페이지에는 시각적 컨텐츠 조각의 HTML을 소비하는 세 가지 접근 방식이 있습니다. 각 구성 요소는 스타일 격리, 레이아웃 비헤이비어, 접근성 및 복잡성에 대한 고유한 특성을 제공합니다.

인라인 요소
iframe
사용자 지정 요소 + Shadow DOM
메커니즘
fetch() URL을 innerHTML을(를) 통해 <div>에 응답 HTML을 삽입하십시오.
<iframe src="publishURL">
사용자 지정 요소, HTML fetch()을(를) 정의하고 첨부된 섀도 DOM 루트에 삽입합니다.
스타일 격리
없음 — 조각 CSS가 호스트 페이지로 누출되고 호스트 CSS가 조각에 영향을 줍니다.
전체 — 별도의 검색 컨텍스트, 전체 CSS 격리
강력함 — 그림자 DOM 경계 블록이 호스트 CSS 캐스케이드, 조각 스타일이 캡슐화된 상태로 유지
레이아웃 기여도
전체 — 컨텐트는 일반 문서 플로우의 일부이며, flexbox/grid/container 크기 조정에 응답합니다.
없음 — iframe에 고정 차원이 있습니다. 명시적인 width/height 또는 JS 기반 자동 크기 조정이 필요합니다.
전체 — 사용자 지정 요소는 다른 DOM 요소와 마찬가지로 호스트 문서의 일반 흐름에 참여합니다
접근성(a11y)
우수 — 컨텐츠는 기본 DOM 트리에 있으며, 화면 판독기와 보조 기술이 완전히 트래버스할 수 있습니다
중재 — 별도의 탐색 컨텍스트로 인해 화면 판독기 탐색이 혼동될 수 있습니다. title 특성이 필요합니다.
양호 — 컨텐츠는 동일한 문서 내에 있으며, 섀도우 DOM은 최신 보조 기술에 의해 트래버스 가능합니다
SEO
불량 — JS fetch()을(를) 통해 로드된 컨텐츠가 대부분의 웹 크롤러에서 인덱싱되지 않습니다.
불량 — iframe 컨텐츠는 일반적으로 상위 페이지 컨텍스트에서 인덱싱되지 않습니다
불량 — 인라인과 동일하며, JS를 가져온 콘텐츠는 크롤링할 수 없습니다.
JavaScript 런타임
공유 — 동일한 창/문서 컨텍스트, 조각에 <script>개의 태그가 포함된 경우 스크립트 충돌 위험
격리됨 — 별도의 창 컨텍스트, 충돌 위험 없음
공유 — 동일한 창 컨텍스트이지만 DOM 범위가 지정됨. 섀도우 루트 내의 스크립트는 호스트 컨텍스트에서 실행됩니다
교차 원본 지원
게시 URL에 CORS 헤더가 필요합니다(서비스에서 구성).
기본적으로 작동 - iframe은 CORS 없이 원본 간 콘텐츠를 로드합니다.
게시 URL에 CORS 헤더 필요(인라인과 동일)
구현의 복잡성
최소 — JS 라인 몇 개
Trivial — 0JS 필요, 순수 HTML
낮음 — 사용자 지정 요소 정의에 대한 JS 줄이 20개까지 페이지 전체에서 재사용할 수 있습니다
최적의 대상
프로토타이핑, 신뢰할 수 있는 동일 출처 콘텐츠, 레이아웃 통합이 중요한 컨텍스트 및 CSS 충돌을 관리할 수 있음
빠른 포함, 샌드박스를 작동하는 콘텐츠, CORS를 사용할 수 없는 교차 원본 시나리오, 완전히 격리되어야 하는 콘텐츠
프로덕션 사용 - 격리, 레이아웃 기여도 및 접근성의 균형을 맞춥니다(AEM 핵심 구성 요소 및 외부 사이트에 권장).

인라인 요소(fetch + innerHTML) inline-element-fetch-and-innerhtml

가장 간단한 방법:

  1. 게시 URL 가져오기
  2. 컨테이너 요소에 HTML 삽입

인라인 요소 포함의 예:

<div id="cf-container"></div>
<script>
  fetch("<publish-url>")
    .then(r => r.ok ? r.text() : Promise.reject(r.status))
    .then(html => {
      document.getElementById("cf-container").innerHTML = html;
    })
    .catch(err => console.error("Failed to load fragment", err));
</script>

사용 시기:

  • 신속한 프로토타이핑 또는 개념 증명 페이지
  • 호스트 페이지와 조각 스타일을 모두 제어하는 동일한 원본 컨텍스트
  • 최대 레이아웃 유연성이 스타일 캡슐화보다 중요한 경우
CAUTION
CSS 충돌 위험
조각의 인라인 스타일(<style> 블록, 글꼴-면 선언 및 요소 선택기 포함)이 호스트 페이지의 캐스케이드에 병합됩니다.
이로 인해 두 방향에서 의도하지 않은 스타일 무시가 발생할 수 있습니다.
이러한 충돌을 용인하거나 적극적으로 관리할 수 있는 경우에만 이 기술을 사용하십시오.

iframe iframe

게시 URL을 <iframe>src(으)로 직접 로드합니다. JavaScript은 필요하지 않습니다.

iframe 임베드의 예:

<iframe
  src="<publish-url>"
  title="Content Fragment Preview"
  width="100%"
  height="600"
  frameborder="0"
  style="border: none;"
></iframe>

iframe 크기를 자동으로 조정할 수도 있습니다(선택 사항).

iframe의 크기를 콘텐츠 높이로 동적으로 조정하려면(스크롤 막대 제외) postMessage 패턴 또는 적절한 라이브러리를 사용하십시오.

간단한 접근 방식의 예는 다음과 같습니다.

<iframe id="cf-iframe" src="<publish-url>" title="Content Fragment Preview"
  width="100%" frameborder="0" style="border:none; overflow:hidden;"
  onload="this.style.height = this.contentDocument.documentElement.scrollHeight + 'px';"
></iframe>
WARNING
위의 onload 자동 크기 조정 접근 방식은 동일 원본 iframe에만 작동합니다.
원본 간 게시 URL의 경우 postMessage 기반 솔루션이 필요하거나 고정 높이를 설정해야 합니다.

사용 시기:

  • Edge Delivery Services 포함 블록(기본 통합 — 아래 섹션 참조)
  • 전체 CSS/JS 격리가 중요한 컨텍스트
  • CORS가 구성되지 않은 교차 원본 포함
  • 제로 코드 빠른 통합(URL만 붙여넣기)

게시 URL을 가져오고 HTML을 캡슐화된 섀도 DOM 루트에 주입하는 재사용 가능한 <cf-visualization> 사용자 지정 요소를 정의합니다.

이 요소는 다음을 제공합니다.

  • 그림자 DOM 격리
    • 조각의 마크업과 스타일은 그림자 루트로 캡슐화되어 호스트 페이지의 CSS 캐스케이드와 충돌을 방지할 수 있습니다.
  • 인라인 레이아웃 기여도
    • 렌더링된 콘텐츠는 호스트 문서의 일반 흐름에 참여하며, 수동 차원 관리 없이 컨테이너 크기 조정 및 flexbox/grid 컨텍스트에 응답합니다.
  • 단일 탐색 컨텍스트
    • 보조 문서 컨텍스트가 만들어지지 않습니다. 조각 컨텐츠는 페이지의 JavaScript 런타임을 공유하며 보조 기술에 의해 완전히 트래버스됩니다.
  • 최소 오버헤드
    • 단일 fetch 호출은 게시 계층에서 미리 렌더링된 HTML을 검색합니다. 클라이언트측 렌더링 프레임워크는 필요하지 않습니다.
IMPORTANT
이는 프로덕션 사용에 권장되는 접근 방법이며 AEM 핵심 구성 요소에서 사용하는 기술입니다.

사용자 지정 요소를 정의하려면 페이지당 다음 스크립트를 한 번씩 포함합니다. 페이지의 모든 <cf-visualization> 인스턴스는 이 정의를 사용합니다.

<script>
  class CfVisualization extends HTMLElement {
    connectedCallback() {
      const src = this.getAttribute("src");
      if (!src) return;

      const shadow = this.attachShadow({ mode: "open" });

      fetch(src)
        .then((r) => (r.ok ? r.text() : Promise.reject(r.status)))
        .then((html) => {
          shadow.innerHTML = html;
        })
        .catch((err) => {
          console.error("cf-visualization: failed to load", src, err);
        });
    }
  }

  if (!customElements.get("cf-visualization")) {
    customElements.define("cf-visualization", CfVisualization);
  }
</script>

사용자 지정 요소를 사용하려면 다음을 수행하십시오.

<cf-visualization src="<publish-url>"></cf-visualization>

사용 시기:

  • 핵심 구성 요소를 사용하는 AEM Sites 페이지(기본 제공 비헤이비어)
  • 깔끔하고 재사용 가능한 통합이 필요한 외부/타사 웹 사이트
  • 스타일 격리와 레이아웃 흐름 기여도가 모두 필요한 모든 컨텍스트

Edge Delivery Services과 통합(포함 블록) integration-with-edge-services-embed-block

Edge Delivery Services에서 게시 URL은 <iframe>(으)로 렌더링되는 포함 블록​을(를) 통해 사용됩니다.

  1. 포함 블록이 프로젝트에 있는지 확인합니다.

    EDS 프로젝트에 포함 블록이 아직 포함되어 있지 않은 경우 aem-block-collection 저장소에서 해당 블록을 복사합니다.

    code language-cmdline
    # From the aem-block-collection repo, copy blocks/embed/ into your project's blocks/ directory
    cp -r aem-block-collection/blocks/embed/ your-eds-project/blocks/embed/
    
  2. 문서 작성 편집기(Edge Delivery Services)에서 포함 작성

    문서 작성에서 블록은 표로 표시됩니다. 시각적 콘텐츠 조각 임베드를 추가하려면 다음을 수행하십시오.

    table 0-row-1 1-row-1
    임베드
    (게시 URL을 하이퍼링크로 붙여넣기)

    또는 프로젝트나 Sidekick이 블록 라이브러리에 포함 블록으로 구성된 경우 슬래시 메뉴를 통해 삽입하고 게시 URL을 블록 콘텐츠에 붙여넣을 수 있습니다.

  3. 결과

    포함 블록은 <iframe> 내에서 게시 URL을 렌더링합니다. 조각 콘텐츠는 EDS 페이지 레이아웃 내에서 전체 CSS 격리 상태로 로드됩니다.

통합 - AEM Sites 및 핵심 구성 요소 integration-aem-sites-with-core-components

콘텐츠 조각 핵심 구성 요소(core/wcm/components/contentfragment/v1/contentfragment)에는 고객 요소 + 그림자 DOM 기술을 사용하는 시각적 콘텐츠 조각 렌더링에 대한 기본 지원이 있습니다.

작동 방식:

  • 작성자 모드:

    구성 요소의 displayMode이(가) vcf(으)로 설정되면 제작 clientlib(vcfRenderer.js)은 미리보기 API에서 조각 HTML을 가져와서 제작 캔버스에서 인라인으로 렌더링합니다.

    작성자 미리보기 엔드포인트의 예는 다음과 같습니다.

    code language-html
    GET /adobe/sites/cf/fragments/{fragmentId}/preview?templateId={templateId}&variation={variation}
    
  • 게시 모드:

    게시된 페이지(wcmmode.disabled)에서 HTL 템플릿은 게시 URL에서 가져온 인라인 스크립트를 렌더링하고 HTML을 섀도 DOM 루트에 삽입합니다.

    예제 핵심 구성 요소 시각적 컨텐츠 조각(templates.html):

    code language-html
    <div class="cmp-contentfragment cmp-contentfragment--vcf"
       data-cmp-contentfragment-id="{fragmentId}"
       data-cmp-contentfragment-vcf-template="{templateId}"
       data-cmp-contentfragment-variation="{variation}">
      <!-- Only rendered when wcmmode.disabled (publish) -->
      <div data-vcf-url="{vcfPublishUrl}" class="cmp-contentfragment__vcf-loader" style="display:none"></div>
      <script>
          (function() {
              var script = document.currentScript;
              var loader = script.previousElementSibling;
              var el = script.parentElement;
              if (!el || !loader) return;
              var url = loader.dataset.vcfUrl;
              if (!url) return;
              loader.remove();
              var shadow = el.attachShadow({ mode: "open" });
              var body = document.createElement("body");
              body.style.display = "none";
              shadow.appendChild(body);
              fetch(url)
                  .then(function(r) { return r.ok ? r.text() : Promise.reject(r.status); })
                  .then(function(html) {
                      body.innerHTML = html;
                      body.style.display = "";
                  });
          })();
      </script>
    </div>
    

    게시 URL 형식:

    Sling 모델(ContentFragmentImpl)은 다음 패턴을 사용하여 게시 URL을 빌드합니다.

    code language-html
    /adobe/experimental/previewtemplates-expires-20260301/contentFragments/{templateId}/{fragmentId}/{variation}.html
    

    이 상대 URL은 런타임 시 게시 호스트에 대해 확인됩니다.

외부 사이트와 통합 integration-with-external-sites

AEM이 아닌 웹 사이트의 경우 Customer Element + Shadow DOM 기술을 사용하십시오. 따라서 프레임워크 종속성 없이 선언적인 깔끔한 통합이 가능합니다.

예:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Product Page</title>
</head>
<body>
  <h1>Product Details</h1>
  <p>Some host-page content here...</p>

  <!-- Embed the Content Fragment visualization -->
  <cf-visualization
    src="https://publish-p12345-e67890.adobeaemcloud.com/adobe/experimental/previewtemplates-expires-20260301/contentFragments/product_template/abc-123/master.html"
  ></cf-visualization>

  <p>More host-page content below the fragment...</p>

  <!-- Custom Element definition (include once) -->
  <script>
    class CfVisualization extends HTMLElement {
      connectedCallback() {
        const src = this.getAttribute("src");
        if (!src) return;
        const shadow = this.attachShadow({ mode: "open" });
        fetch(src)
          .then(r => r.ok ? r.text() : Promise.reject(r.status))
          .then(html => { shadow.innerHTML = html; })
          .catch(err => console.error("cf-visualization: failed to load", src, err));
      }
    }
    if (!customElements.get("cf-visualization")) {
      customElements.define("cf-visualization", CfVisualization);
    }
  </script>
</body>
</html>
NOTE
서로 다른 src URL을 사용하여 동일한 페이지에 여러 <cf-visualization> 요소를 배치할 수 있습니다. 사용자 지정 요소 정의는 한 번만 포함하면 됩니다.

CORS 및 보안 고려 사항 cors-and-security-considerations

관심사
세부 정보
CORS
콘텐츠 조각 시각화 서비스는 구성 가능한 허용된 원본을 사용하여 /adobe/** 경로에서 CORS를 구성합니다.
인라인 요소(fetch + innerHTML) 1 및 고객 요소 + 섀도 DOM 기법(fetch() 사용)을 사용하려면 허용 목록의 원본 호스트가 있어야 합니다.
iFrame 기법은 CORS가 필요하지 않습니다.
CSP/X-Frame-Options
게시된 HTML에서 서비스가 Content-Security-Policy 또는 X-Frame-Options 헤더를 설정하지 않습니다. CDN 또는 Dispatcher이 이러한 헤더를 추가하는 경우 호스트 원본에서 프레이밍(iFrame용) 또는 fetch() 액세스(인라인/섀도 DOM용)를 허용하는지 확인하십시오.
콘텐츠 트러스트
게시된 HTML은 서비스에서 관리하는 Handlebars 템플릿을(를) 사용하여 작성된 콘텐츠 조각 데이터에서 미리 렌더링됩니다. 사용자 생성 스크립트는 포함되지 않습니다. 그러나 모든 innerHTML 삽입과 마찬가지로 소스 원본을 신뢰할 수 있도록 하십시오.

적절한 기법 선택 choose-the-appropriate-technique

다음 사항을 적합한 기술을 선택하는 데 도움이 되는 의사 결정 안내서로 사용하십시오.

시나리오
솔루션
JavaScript을 전혀 사용하지 않고 완전히 격리해야 합니까?
Iframe
스타일 격리를 통한 레이아웃 흐름 참여가 필요하십니까?
사용자 지정 요소 + Shadow DOM (권장)
가장 빠른 프로토타입, 동일 출처 및 CSS 충돌이 허용됩니까?
인라인 요소
Edge Delivery Services에 임베드?
블록 포함(후드 아래의 iframe)
AEM Sites 페이지에 포함하시겠습니까?
핵심 구성 요소 (Shadow DOM, 내장)

추가 리소스 additional-resources

추가 리소스를 사용할 수 있습니다.

recommendation-more-help
experience-manager-cloud-service-help-main-toc