{"componentChunkName":"component---src-templates-blog-post-js","path":"/translation/2026/declarative-partial-updates/","result":{"data":{"site":{"siteMetadata":{"title":"Ykss","author":"[Ykss]","siteUrl":"https://ykss.netlify.app","comment":{"disqusShortName":"","utterances":"ykss/ykss.netlify.com"},"sponsor":{"buyMeACoffeeId":""}}},"markdownRemark":{"id":"cc8d7df0-0d44-5d88-80d0-81e3ce1e6cf4","excerpt":"원문: declarative partial updates 웹은 시작 당시의 정적, 문서 중심 매체에서 오래전에 벗어났습니다. 현대적이고 풍부한 웹 앱은 소통, 구매, 다양한 콘텐츠 소비, 복잡한 일상 관리 등 수많은 이유로 모든 사람이 사용합니다. HTML은 모든 발전에도 불구하고 콘텐츠가 준비된 시점이나 사용자가 소비하는 시점과 관계없이 여전히 위에서 아래로 순서대로 전달됩니다. CSS…","html":"<blockquote>\n<p>원문: <a href=\"https://developer.chrome.com/blog/declarative-partial-updates\">declarative partial updates</a></p>\n</blockquote>\n<p>웹은 시작 당시의 정적, 문서 중심 매체에서 오래전에 벗어났습니다. 현대적이고 풍부한 웹 앱은 소통, 구매, 다양한 콘텐츠 소비, 복잡한 일상 관리 등 수많은 이유로 모든 사람이 사용합니다.</p>\n<p>HTML은 모든 발전에도 불구하고 콘텐츠가 준비된 시점이나 사용자가 소비하는 시점과 관계없이 여전히 위에서 아래로 순서대로 전달됩니다. CSS로 콘텐츠 순서를 바꿀 수 있지만 접근성 측면에서 상당한 부작용이 발생할 수 있습니다. 자바스크립트는 다양한 API로 DOM을 조작하여 이 제약에서 어느 정도 벗어나지만, HTML에 연결하려면 장황한 구문이나 DOM 트리 구성이 필요한 경우가 많습니다.</p>\n<p>웹은 클라이언트-서버 특성상 성능이 매우 중요하지만, HTML의 순서대로 전달되는 특성을 우회하기 위해 최적이 아닌 선택을 하는 경우가 많아 성능이 저하됩니다. 전체 페이지가 준비될 때까지 기다리거나 컴포넌트를 비동기 방식으로 전달하기 위해 무거운 프레임워크를 사용하는 것이 그 예입니다. 자바스크립트 프레임워크의 인기는 웹 개발자들이 웹의 기원인 엄격한 문서 중심 멘탈 모델보다 컴포넌트 기반 모델을 선호한다는 것을 보여줍니다.</p>\n<p>Chrome 팀은 이 문제를 고민해 왔으며, 웹 플랫폼에 <a href=\"https://github.com/WICG/declarative-partial-updates\">선언적 부분 업데이트(Declarative Partial Updates)</a>라는 이름의 새로운 기능을 개발해 왔습니다.</p>\n<p>두 가지 새로운 API 세트로 HTML을 보다 비선형적인 방식으로 더 쉽게 전달할 수 있습니다. HTML 문서 내에서 순서에 구애받지 않거나, 새로운 자바스크립트 API를 활용하여 기존 문서에 HTML을 동적으로 삽입하는 방식 모두 지원합니다. Chrome 148부터 <code class=\"language-text\">chrome://flags/#enable-experimental-web-platform-features</code> 플래그를 사용하여 개발자 테스트를 진행할 수 있습니다. 폴리필도 제공되어 아직 지원하지 않는 브라우저에서도 이 새로운 API를 바로 사용할 수 있습니다.</p>\n<p>웹 플랫폼에 추가된 이 기능들은 다른 브라우저 공급업체와 표준화 기관의 긍정적인 피드백을 바탕으로 표준화가 진행 중입니다. 관련 표준은 이 새로운 API를 포함하도록 업데이트되고 있습니다.</p>\n<h2 id=\"비순서-스트리밍\" style=\"position:relative;\"><a href=\"#%EB%B9%84%EC%88%9C%EC%84%9C-%EC%8A%A4%ED%8A%B8%EB%A6%AC%EB%B0%8D\" aria-label=\"비순서 스트리밍 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>비순서 스트리밍</h2>\n<p>첫 번째 변경 사항은 <code class=\"language-text\">&lt;template></code> HTML 요소와 처리 명령어(processing instruction) 자리표시자를 사용하는 새로운 <a href=\"https://github.com/WICG/declarative-partial-updates/blob/main/patching-explainer.md\">비순서 스트리밍 API(out-of-order streaming APIs)</a>입니다.</p>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre class=\"language-html\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>?marker</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>placeholder<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span>\n\n...\n\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>template</span> <span class=\"token attr-name\">for</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>placeholder<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span> Here is some <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>em</span><span class=\"token punctuation\">></span></span>HTML content<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>em</span><span class=\"token punctuation\">></span></span>! <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>template</span><span class=\"token punctuation\">></span></span></code></pre></div>\n<p><a href=\"https://developer.mozilla.org/docs/Web/API/ProcessingInstruction\">처리 명령어</a>는 XML에서 오랫동안 존재해 왔지만, HTML에서는 주석으로 처리되어 무시되었습니다. 이 새로운 API는 그 동작을 바꿔 HTML에 처리 명령어를 도입합니다. 브라우저가 <code class=\"language-text\">&lt;?marker name=\"placeholder\"></code> 처리 명령어를 만나면 이전처럼 즉시 아무 동작도 하지 않지만, 나중에 참조할 수 있도록 기록해 둡니다.</p>\n<p><a href=\"https://developer.mozilla.org/docs/Web/HTML/Reference/Elements/template\"><code class=\"language-text\">&lt;template></code> 요소</a>는 <code class=\"language-text\">name</code> 속성으로 해당 처리 명령어를 찾아 콘텐츠를 교체합니다. 파싱이 완료된 후 DOM은 다음과 같습니다.</p>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre class=\"language-html\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span><span class=\"token punctuation\">></span></span>Here is some <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>em</span><span class=\"token punctuation\">></span></span>HTML content<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>em</span><span class=\"token punctuation\">></span></span>!<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span></code></pre></div>\n<p>교체를 위한 <code class=\"language-text\">&lt;?marker></code> 외에도, 템플릿이 처리되기 전에 임시 자리표시자 콘텐츠를 표시할 수 있는 <code class=\"language-text\">&lt;?start></code>와 <code class=\"language-text\">&lt;?end></code> 범위 마커도 있습니다.</p>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre class=\"language-html\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span><span class=\"token punctuation\">></span></span>\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>?start</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>another-placeholder<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n  Loading…\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>?end</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span>\n\n...\n\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>template</span> <span class=\"token attr-name\">for</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>another-placeholder<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n  Here is some <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>em</span><span class=\"token punctuation\">></span></span>HTML content<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>em</span><span class=\"token punctuation\">></span></span>!\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>template</span><span class=\"token punctuation\">></span></span></code></pre></div>\n<p><code class=\"language-text\">&lt;template></code>이 파싱될 때까지 <code class=\"language-text\">Loading…</code>이 표시되다가 새 콘텐츠로 교체됩니다.</p>\n<p>템플릿 안에 처리 명령어를 포함하여 여러 번의 업데이트를 허용할 수도 있습니다.</p>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre class=\"language-html\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>ul</span> <span class=\"token attr-name\">id</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>results<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>?start</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>results<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n  Loading…\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>?end</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>ul</span><span class=\"token punctuation\">></span></span>\n\n...\n\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>template</span> <span class=\"token attr-name\">for</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>results<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>li</span><span class=\"token punctuation\">></span></span>Result One<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>li</span><span class=\"token punctuation\">></span></span>\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>?marker</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>results<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>template</span><span class=\"token punctuation\">></span></span>\n...\n\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>template</span> <span class=\"token attr-name\">for</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>results<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>li</span><span class=\"token punctuation\">></span></span>Result Two<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>li</span><span class=\"token punctuation\">></span></span>\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>?marker</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>results<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>template</span><span class=\"token punctuation\">></span></span>\n...</code></pre></div>\n<p>파싱 후 생성되는 HTML은 다음과 같습니다.</p>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre class=\"language-html\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>ul</span> <span class=\"token attr-name\">id</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>results<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>li</span><span class=\"token punctuation\">></span></span>Result One<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>li</span><span class=\"token punctuation\">></span></span>\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>li</span><span class=\"token punctuation\">></span></span>Result Two<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>li</span><span class=\"token punctuation\">></span></span>\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>?marker</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>results<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>ul</span><span class=\"token punctuation\">></span></span></code></pre></div>\n<p>나중에 문서에 <code class=\"language-text\">&lt;template for=\"results\"></code>가 추가될 경우에 대비해 마지막에 처리 명령어가 남아 있습니다.</p>\n<h3 id=\"데모\" style=\"position:relative;\"><a href=\"#%EB%8D%B0%EB%AA%A8\" aria-label=\"데모 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>데모</h3>\n<p>다음 영상은 스트리밍 HTML로 구현한 기본 사진 앨범 애플리케이션입니다.</p>\n<p><video muted=\"\" loop=\"\" controls=\"\" autoplay=\"\" width=\"100%\"> <source src=\"https://developer.chrome.com/static/blog/declarative-partial-updates/video/patching-photo-album.mp4?hl=ko\" type=\"video/mp4\"> </video></p>\n<p>비순서 스트리밍으로 구현된 사진 앨범 데모 (<a href=\"https://github.com/GoogleChromeLabs/web-perf-demos/blob/main/patching-demos/photo-album-server.js\">소스</a>)</p>\n<p>초기 레이아웃 이후 상태와 사진이 모두 HTML로 스트리밍됩니다.</p>\n<h3 id=\"사용-사례\" style=\"position:relative;\"><a href=\"#%EC%82%AC%EC%9A%A9-%EC%82%AC%EB%A1%80\" aria-label=\"사용 사례 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>사용 사례</h3>\n<p>스트리밍 HTML과 결합된 이 비순서 패치 HTML에는 다양한 사용 사례가 있습니다.</p>\n<ul>\n<li><strong>아일랜드 아키텍처(island architecture).</strong> Astro와 같은 프레임워크가 대중화한 일반적인 패턴인 <a href=\"https://jasonformat.com/islands-architecture/\">아일랜드 아키텍처</a>로, 컴포넌트가 정적 HTML 위에서 독립적으로 하이드레이션됩니다. <code class=\"language-text\">&lt;template for></code> API를 사용하면 정적 콘텐츠를 HTML에서 직접 유사한 방식으로 처리할 수 있습니다. 자바스크립트 프레임워크도 이를 활용하여 더 인터랙티브한 아일랜드를 만들거나 컴포넌트를 처리할 수 있습니다.</li>\n<li><strong>준비된 콘텐츠 전달.</strong> 아일랜드 아키텍처 덕분에 데이터베이스 조회처럼 추가 처리가 필요한 콘텐츠를 기다리지 않고, 준비되는 즉시 콘텐츠를 스트리밍할 수 있습니다. 많은 플랫폼이 스트리밍 HTML을 지원하지만 HTML의 순서 특성 때문에 콘텐츠가 지연되거나 복잡한 자바스크립트 DOM 조작에 의존하는 경우가 많습니다. 이제 기다리는 동안 정적 콘텐츠를 먼저 전달하고, 비용이 많이 드는 콘텐츠는 HTML 스트림 끝에 연결할 수 있습니다.</li>\n<li><strong>페이지 로드 성능에 최적인 순서로 HTML 전달.</strong> 한 단계 더 나아가, 콘텐츠가 준비된 경우에도 순서를 변경할 수 있습니다. 예를 들어 메가 메뉴는 페이지가 인터랙티브해질 때까지 사용자가 볼 수 없는 많은 HTML을 포함하는 일반적인 탐색 기능입니다. 이 큰 HTML 덩어리는 HTML 문서 뒤쪽에 배치하여 초기 페이지 로드에 필요한 더 중요한 HTML을 우선시할 수 있습니다. HTML에서 순서는 더 이상 제약이 아닙니다.</li>\n</ul>\n<p>몇 가지 예시에 불과하며, 개발자들이 이 새로운 API를 어떻게 활용할지 기대됩니다.</p>\n<h3 id=\"제한-사항-및-주의점\" style=\"position:relative;\"><a href=\"#%EC%A0%9C%ED%95%9C-%EC%82%AC%ED%95%AD-%EB%B0%8F-%EC%A3%BC%EC%9D%98%EC%A0%90\" aria-label=\"제한 사항 및 주의점 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>제한 사항 및 주의점</h3>\n<p>API에는 몇 가지 제한 사항과 주의할 점이 있습니다.</p>\n<ul>\n<li><code class=\"language-text\">&lt;template for></code>는 보안상의 이유로 동일한 부모 요소 내의 처리 명령어만 업데이트할 수 있습니다. <code class=\"language-text\">&lt;body></code> 요소에 직접 <code class=\"language-text\">&lt;template for></code>를 추가하면 <code class=\"language-text\">&lt;head></code>를 포함한 전체 문서에 접근할 수 있습니다.</li>\n<li><code class=\"language-text\">&lt;?end></code> 처리 명령어는 선택 사항이며, 생략하면 <code class=\"language-text\">&lt;?start></code> 요소와 포함 요소의 끝 사이에 있는 콘텐츠가 교체됩니다.</li>\n<li><code class=\"language-text\">&lt;template for></code>가 스트리밍을 시작한 후 처리 명령어를 이동하면 새 콘텐츠가 기존 위치로 계속 스트리밍되는 등 예기치 않은 결과가 발생할 수 있습니다.</li>\n<li><code class=\"language-text\">setHTML</code>이나 <code class=\"language-text\">innerHTML</code> 같은 메서드로 <code class=\"language-text\">&lt;template for></code>를 동적으로 삽입할 때, 파싱 시 템플릿의 “부모”는 중간 문서 프래그먼트(document fragment)입니다. 따라서 이 메서드로 HTML을 삽입해도 기존 DOM을 수정할 수 없으며 패치는 프래그먼트 내부에서 제자리에 발생합니다. 반면 곧 다룰 <code class=\"language-text\">streamHTMLUnsafe</code> 같은 메서드로 스트리밍할 때는 중간 프래그먼트가 없으므로 템플릿이 기존 콘텐츠를 교체할 수 있습니다.</li>\n</ul>\n<h3 id=\"향후-추가될-수-있는-기능\" style=\"position:relative;\"><a href=\"#%ED%96%A5%ED%9B%84-%EC%B6%94%EA%B0%80%EB%90%A0-%EC%88%98-%EC%9E%88%EB%8A%94-%EA%B8%B0%EB%8A%A5\" aria-label=\"향후 추가될 수 있는 기능 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>향후 추가될 수 있는 기능</h3>\n<p>현재 검토 중인 향후 추가 기능은 다음과 같습니다.</p>\n<ul>\n<li><strong>클라이언트 측 인클루드(client side includes).</strong> 예를 들어 <code class=\"language-text\">&lt;template for=\"footer\" patchsrc=\"/partials/footer.html\"></code>와 같은 방식입니다.</li>\n<li><strong>일괄 처리(batching).</strong> 클라이언트 측 프래그먼트 인클루드를 확장하여 여러 업데이트가 동시에 발생하도록 일괄 처리를 지원할 수 있습니다.</li>\n<li><strong>변경되지 않는 콘텐츠 덮어쓰기 방지.</strong> 콘텐츠 리비전 번호나 버전 관리로 구현할 수 있습니다. 콘텐츠를 초기화하는 대신 라우트 변경이나 다른 업데이트 사이에서도 상태를 유지할 수 있습니다.</li>\n<li><strong>패치 중 새니타이징(sanitizing).</strong> 예를 들어 <code class=\"language-text\">&lt;template for=icon safe>&lt;svg id=\"from-untrusted-source\">...&lt;/svg>&lt;/template></code>와 같은 방식입니다.</li>\n</ul>\n<h3 id=\"폴리필\" style=\"position:relative;\"><a href=\"#%ED%8F%B4%EB%A6%AC%ED%95%84\" aria-label=\"폴리필 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>폴리필</h3>\n<p>Chrome 팀은 다른 브라우저에 이 기능이 도입되기 전에도 바로 사용할 수 있도록 <a href=\"https://github.com/GoogleChromeLabs/template-for-polyfill\"><code class=\"language-text\">template-for-polyfill</code>을 출시했으며</a> <a href=\"https://www.npmjs.com/package/template-for-polyfill\">npm에서 사용 가능합니다</a>.</p>\n<p>브라우저의 HTML 파서를 직접 업데이트할 수 없어 <a href=\"https://github.com/GoogleChromeLabs/template-for-polyfill#limitations\">몇 가지 제한 사항</a>이 있지만, 가장 일반적인 사용 사례는 모두 지원합니다. 다른 브라우저에서도 계속 테스트해야 합니다.</p>\n<h2 id=\"새로운-html-삽입-및-스트리밍-메서드\" style=\"position:relative;\"><a href=\"#%EC%83%88%EB%A1%9C%EC%9A%B4-html-%EC%82%BD%EC%9E%85-%EB%B0%8F-%EC%8A%A4%ED%8A%B8%EB%A6%AC%EB%B0%8D-%EB%A9%94%EC%84%9C%EB%93%9C\" aria-label=\"새로운 html 삽입 및 스트리밍 메서드 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>새로운 HTML 삽입 및 스트리밍 메서드</h2>\n<p>모든 콘텐츠를 HTML로 전달할 수는 없습니다. Chrome이 이 영역에서 진행하는 작업의 두 번째 부분은 자바스크립트로 콘텐츠를 업데이트하는 과정을 더 쉽게 만드는 것입니다.</p>\n<p>자바스크립트로 기존 문서에 HTML을 동적으로 삽입하는 방법은 이미 여러 가지가 있습니다.</p>\n<ul>\n<li><code class=\"language-text\">setHTML</code></li>\n<li><code class=\"language-text\">setHTMLUnsafe</code></li>\n<li><code class=\"language-text\">innerHTML</code> 및 <code class=\"language-text\">outerHTML</code> setter</li>\n<li><code class=\"language-text\">createContextualFragment</code></li>\n<li><code class=\"language-text\">insertAdjacentHTML</code></li>\n</ul>\n<p>그러나 이 API들은 모두 개발자가 항상 인지하지 못할 수 있는 미묘한 차이와 다른 동작 방식을 가지고 있습니다.</p>\n<ul>\n<li>새 콘텐츠가 덮어쓰기되는지, 아니면 추가되는지</li>\n<li><code class=\"language-text\">&lt;script></code> 태그를 이스케이프하는 등 잠재적으로 위험한 HTML을 새니타이징(sanitizing)하는지</li>\n<li>그렇지 않다면 <code class=\"language-text\">&lt;script></code>를 실행해야 하는지</li>\n<li>TrustedTypes와 어떻게 작동하는지</li>\n</ul>\n<p>솔직히 이 API들을 보고 각각에 대한 질문에 자신 있게 답할 수 있는 개발자는 거의 없을 것입니다.</p>\n<p>큰 제한 사항은 <a href=\"https://github.com/whatwg/html/issues/2142\">HTML 스트리밍을 허용해야 한다는 요청</a>이 있었음에도 불구하고, 미리 알고 있는 완전한 HTML 세트에만 사용할 수 있다는 점입니다. 실질적으로 콘텐츠를 바로 스트리밍할 수 있다는 HTML의 강점에도 불구하고, 삽입 전에 전체 콘텐츠를 다운로드해야 합니다. 페이로드를 분할하거나 <code class=\"language-text\">document.write</code> 같은 임시방편의 사용 중단된 메서드를 활용하여 제한적으로 우회할 수 있지만, 이 방법들도 자체적인 문제를 야기합니다.</p>\n<h3 id=\"새로운-정적-및-스트리밍-api-세트\" style=\"position:relative;\"><a href=\"#%EC%83%88%EB%A1%9C%EC%9A%B4-%EC%A0%95%EC%A0%81-%EB%B0%8F-%EC%8A%A4%ED%8A%B8%EB%A6%AC%EB%B0%8D-api-%EC%84%B8%ED%8A%B8\" aria-label=\"새로운 정적 및 스트리밍 api 세트 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>새로운 정적 및 스트리밍 API 세트</h3>\n<p>Chrome은 기존 <code class=\"language-text\">setHTML</code>과 <code class=\"language-text\">setHTMLUnsafe</code>를 정리하고 스트리밍 기능을 도입하는 <a href=\"https://github.com/WICG/declarative-partial-updates/blob/main/dynamic-markup-revamped-explainer.md\">새로운 API 모음</a>을 제안했습니다.</p>\n<p>기존 HTML 앞뒤에 콘텐츠를 삽입하는 메서드와 함께 설정하거나 대체하는 메서드가 있습니다. 각 메서드에는 스트리밍 버전이 있습니다.</p>\n<table>\n<thead>\n<tr>\n<th>동작</th>\n<th>정적</th>\n<th>스트리밍</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>요소의 HTML 콘텐츠 설정</td>\n<td><code class=\"language-text\">setHTML(html, options);</code></td>\n<td><code class=\"language-text\">streamHTML(options);</code></td>\n</tr>\n<tr>\n<td>전체 요소를 이 HTML로 교체</td>\n<td><code class=\"language-text\">replaceWithHTML(html, options);</code></td>\n<td><code class=\"language-text\">streamReplaceWithHTML(options);</code></td>\n</tr>\n<tr>\n<td>요소 앞에 HTML 추가</td>\n<td><code class=\"language-text\">beforeHTML(html, options);</code></td>\n<td><code class=\"language-text\">streamBeforeHTML(options);</code></td>\n</tr>\n<tr>\n<td>요소의 첫 번째 자식으로 HTML 추가</td>\n<td><code class=\"language-text\">prependHTML(html, options);</code></td>\n<td><code class=\"language-text\">streamPrependHTML(options);</code></td>\n</tr>\n<tr>\n<td>요소의 마지막 자식으로 HTML 추가</td>\n<td><code class=\"language-text\">appendHTML(html, options);</code></td>\n<td><code class=\"language-text\">streamAppendHTML(options);</code></td>\n</tr>\n<tr>\n<td>요소 뒤에 HTML 추가</td>\n<td><code class=\"language-text\">afterHTML(html, options);</code></td>\n<td><code class=\"language-text\">streamAfterHTML(options);</code></td>\n</tr>\n</tbody>\n</table>\n<p><em>새로운 삽입 및 스트리밍 메서드</em></p>\n<p>곧 다룰 <code class=\"language-text\">Unsafe</code> 버전도 있습니다. <code class=\"language-text\">Unsafe</code> 버전까지 포함하면 많아 보일 수 있지만, 일관된 명명 규칙 덕분에 앞서 언급한 서로 관련 없는 메서드들에 비해 각 메서드의 기능을 훨씬 명확하게 파악할 수 있습니다.</p>\n<p>정적 버전은 새 HTML을 DOM 문자열 인수로 받으며 선택적 옵션도 지정할 수 있습니다.</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> newHTML <span class=\"token operator\">=</span> <span class=\"token string\">'&lt;p>This is a new paragraph&lt;/p>'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> contentElement <span class=\"token operator\">=</span> document<span class=\"token punctuation\">.</span><span class=\"token function\">querySelector</span><span class=\"token punctuation\">(</span><span class=\"token string\">'#content-to-update'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\ncontentElement<span class=\"token punctuation\">.</span><span class=\"token function\">setHTML</span><span class=\"token punctuation\">(</span>newHTML<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>스트리밍 버전은 <code class=\"language-text\">getWriter()</code>와 함께 <a href=\"https://developer.mozilla.org/docs/Web/API/Streams_API\">Streams API</a>와 연동하여 작동합니다.</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> contentElement <span class=\"token operator\">=</span> document<span class=\"token punctuation\">.</span><span class=\"token function\">querySelector</span><span class=\"token punctuation\">(</span><span class=\"token string\">'#content-to-update'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> writer <span class=\"token operator\">=</span> contentElement<span class=\"token punctuation\">.</span><span class=\"token function\">streamHTMLUnsafe</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">getWriter</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// Example stream of updating content</span>\n<span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">await</span> writer<span class=\"token punctuation\">.</span><span class=\"token function\">write</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">&lt;p></span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span><span class=\"token operator\">++</span>i<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\">&lt;/p></span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">await</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Promise</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">resolve</span> <span class=\"token operator\">=></span> <span class=\"token function\">setTimeout</span><span class=\"token punctuation\">(</span>resolve<span class=\"token punctuation\">,</span> <span class=\"token number\">1000</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\nwriter<span class=\"token punctuation\">.</span><span class=\"token function\">close</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>fetch 응답에서 <a href=\"https://developer.mozilla.org/docs/Web/API/Streams_API/Concepts#pipe_chains\">파이프 체인(pipe chains)</a>을 활용할 수도 있습니다.</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> contentElement <span class=\"token operator\">=</span> document<span class=\"token punctuation\">.</span><span class=\"token function\">querySelector</span><span class=\"token punctuation\">(</span><span class=\"token string\">'#content-to-update'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> response <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> <span class=\"token function\">fetch</span><span class=\"token punctuation\">(</span><span class=\"token string\">'/api/content.html'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\nresponse<span class=\"token punctuation\">.</span>body\n  <span class=\"token punctuation\">.</span><span class=\"token function\">pipeThrough</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">new</span> <span class=\"token class-name\">TextDecoderStream</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">.</span><span class=\"token function\">pipeTo</span><span class=\"token punctuation\">(</span>contentElement<span class=\"token punctuation\">.</span><span class=\"token function\">streamHTMLUnsafe</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>중간 <code class=\"language-text\">TextDecoderStream()</code> 단계 없이 직접 스트리밍할 수 있는 <a href=\"https://chromestatus.com/feature/5146752165478400\">편의 메서드도 추가할 계획</a>입니다.</p>\n<p><code class=\"language-text\">options</code> 인수를 사용하면 커스텀 <code class=\"language-text\">sanitizer</code>를 지정할 수 있으며, 기본값은 <code class=\"language-text\">default</code>로 <a href=\"https://developer.mozilla.org/docs/Web/API/HTML_Sanitizer_API/Default_sanitizer_configuration\">기본 새니타이저 설정</a>을 사용합니다.</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> newHTML <span class=\"token operator\">=</span> <span class=\"token string\">'&lt;p>This is a new paragraph&lt;/p>'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> contentElement <span class=\"token operator\">=</span> document<span class=\"token punctuation\">.</span><span class=\"token function\">querySelector</span><span class=\"token punctuation\">(</span><span class=\"token string\">'#content-to-update'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// Only allows basic formatting</span>\n<span class=\"token keyword\">const</span> basicFormattingSanitzer <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Sanitizer</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">elements</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'em'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'i'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'b'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'strong'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\ncontentElement<span class=\"token punctuation\">.</span><span class=\"token function\">setHTML</span><span class=\"token punctuation\">(</span>newHTML<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">sanitizer</span><span class=\"token operator\">:</span> basicFormattingSanitzer <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<h3 id=\"안전하지-않은-메서드\" style=\"position:relative;\"><a href=\"#%EC%95%88%EC%A0%84%ED%95%98%EC%A7%80-%EC%95%8A%EC%9D%80-%EB%A9%94%EC%84%9C%EB%93%9C\" aria-label=\"안전하지 않은 메서드 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>“안전하지 않은” 메서드</h3>\n<p>각 API의 “안전하지 않은(unsafe)” 버전도 있습니다.</p>\n<table>\n<thead>\n<tr>\n<th>동작</th>\n<th>정적</th>\n<th>스트리밍</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>요소의 HTML 콘텐츠 설정</td>\n<td><code class=\"language-text\">setHTMLUnsafe(html,options);</code></td>\n<td><code class=\"language-text\">streamHTMLUnsafe(options);</code></td>\n</tr>\n<tr>\n<td>전체 요소를 이 HTML로 교체</td>\n<td><code class=\"language-text\">replaceWithHTMLUnsafe(html, options);</code></td>\n<td><code class=\"language-text\">streamReplaceWithHTMLUnsafe(options);</code></td>\n</tr>\n<tr>\n<td>요소 앞에 HTML 추가</td>\n<td><code class=\"language-text\">beforeHTMLUnsafe(html, options);</code></td>\n<td><code class=\"language-text\">streamBeforeHTMLUnsafe(options);</code></td>\n</tr>\n<tr>\n<td>요소의 첫 번째 자식으로 HTML 추가</td>\n<td><code class=\"language-text\">prependHTMLUnsafe(html, options);</code></td>\n<td><code class=\"language-text\">streamPrependHTMLUnsafe(options);</code></td>\n</tr>\n<tr>\n<td>요소의 마지막 자식으로 HTML 추가</td>\n<td><code class=\"language-text\">appendHTMLUnsafe(html, options);</code></td>\n<td><code class=\"language-text\">streamAppendHTMLUnsafe(options);</code></td>\n</tr>\n<tr>\n<td>요소 뒤에 HTML 추가</td>\n<td><code class=\"language-text\">afterHTMLUnsafe(html, options);</code></td>\n<td><code class=\"language-text\">streamAfterHTMLUnsafe(options);</code></td>\n</tr>\n</tbody>\n</table>\n<p><em>“안전하지 않은” 삽입 및 스트리밍 메서드</em></p>\n<p>“안전하지 않은” 메서드들은 기본적으로 새니타이저를 비활성화하며(원하는 경우 커스텀 새니타이저 지정 가능), 기본값이 <code class=\"language-text\">false</code>인 선택적 <code class=\"language-text\">runScripts</code> 옵션으로 스크립트 실행도 허용할 수 있습니다.</p>\n<p><code class=\"language-text\">setHTML</code>과 마찬가지로 <code class=\"language-text\">setHTMLUnsafe</code>는 기존 메서드이지만, 스크립트 실행과 함께 사용할 수 있도록 <code class=\"language-text\">runScripts</code> 옵션 매개변수가 추가되었습니다.</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> newHTML <span class=\"token operator\">=</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">&lt;p>This is a new paragraph&lt;/p>\n                 &lt;script src=script.js>&lt;/script></span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> contentElement <span class=\"token operator\">=</span> document<span class=\"token punctuation\">.</span><span class=\"token function\">querySelector</span><span class=\"token punctuation\">(</span><span class=\"token string\">'#content-to-update'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\ncontentElement<span class=\"token punctuation\">.</span><span class=\"token function\">setHTMLUnsafe</span><span class=\"token punctuation\">(</span>newHTML<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">runScripts</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>메서드 이름의 “안전하지 않은(unsafe)“이라는 표현은 사용하지 말라는 뜻이 아니라, 잠재적 위험과 스크립트를 새니타이징하거나 제한하는 방법을 상기시키기 위한 것입니다.</p>\n<p>얼마나 “안전하지 않은지”는 입력의 신뢰도에 따라 다릅니다. <code class=\"language-text\">Unsafe</code> 정적 메서드는 모두 DOM 문자열 또는 <code class=\"language-text\">TrustedHTML</code>을 <code class=\"language-text\">html</code> 인수로 받으며 새니타이저를 사용할 수도 있습니다. 다만 <code class=\"language-text\">runScripts</code>의 목적 자체가 스크립트 실행을 허용하는 것이므로 기본적으로 새니타이저가 사용되지 않습니다.</p>\n<h3 id=\"사용-사례-1\" style=\"position:relative;\"><a href=\"#%EC%82%AC%EC%9A%A9-%EC%82%AC%EB%A1%80-1\" aria-label=\"사용 사례 1 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>사용 사례</h3>\n<p>이 새로운 API들은 일관된 이름과 옵션으로 기존 페이지에 HTML을 더 쉽게 추가할 수 있게 해줍니다. 스트리밍 API는 새 콘텐츠가 모두 준비될 때까지 기다리지 않아도 되는 성능상의 이점을 제공합니다.</p>\n<p>사용 사례는 다음과 같습니다.</p>\n<ul>\n<li><strong>단일 페이지 앱에서 대용량 콘텐츠 업데이트의 동적 스트리밍.</strong> 앞서 언급했듯이, 현재 SPA(단일 페이지 앱, Single Page App)의 큰 단점은 초기 HTML 로드의 스트리밍 특성을 활용할 수 없다는 것이었습니다. 이제는 가능합니다!</li>\n<li><strong>HTML 바닥글과 같은 공통 콘텐츠 삽입.</strong> 자바스크립트 API를 사용하면 모든 페이지에 반복해서 포함하는 대신 파셜 파일을 불러와 페이지에 삽입하여 캐싱의 이점을 누릴 수 있습니다. 다만 자바스크립트 실행에 의존하므로 초기 로드에서 표시되지 않는 콘텐츠에만 사용해야 합니다.</li>\n</ul>\n<p>몇 가지 예시에 불과하며, 여러분이 어떤 아이디어를 내놓을지 기대됩니다!</p>\n<h3 id=\"제한-사항-및-주의점-1\" style=\"position:relative;\"><a href=\"#%EC%A0%9C%ED%95%9C-%EC%82%AC%ED%95%AD-%EB%B0%8F-%EC%A3%BC%EC%9D%98%EC%A0%90-1\" aria-label=\"제한 사항 및 주의점 1 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>제한 사항 및 주의점</h3>\n<p>이 새로운 API들에도 몇 가지 제한 사항과 주의할 점이 있습니다.</p>\n<ul>\n<li>Trusted Types API와 스트리밍을 통합하려면 모든 HTML 설정 작업에 새니타이저를 주입할 수 있는 새로운 <code class=\"language-text\">createParserOptions</code> 메서드를 사용해야 합니다. 신뢰할 수 있는 타입 통합에 관한 자세한 내용은 <a href=\"https://github.com/WICG/declarative-partial-updates/blob/main/dynamic-markup-revamped-explainer.md#trusted-types-integration\">설명자를 참고하세요</a>.</li>\n<li><code class=\"language-text\">&lt;template for></code>와 마찬가지로, 스트리밍 중인 요소를 이동하면 예기치 않은 결과나 스트림 오류가 발생할 수 있습니다.</li>\n<li><code class=\"language-text\">streamHTMLUnsafe</code>는 기본 문서에 추가될 때 <code class=\"language-text\">&lt;template for></code> 명령어를 처리하고 <code class=\"language-text\">defer</code> 스크립트를 스트림 끝까지 지연하는 등 여러 면에서 기본 파서와 더 유사하게 동작합니다.</li>\n</ul>\n<h3 id=\"폴리필-1\" style=\"position:relative;\"><a href=\"#%ED%8F%B4%EB%A6%AC%ED%95%84-1\" aria-label=\"폴리필 1 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>폴리필</h3>\n<p>Chrome 팀은 다른 브라우저에 이 기능이 도입되기 전에도 바로 사용할 수 있도록 <a href=\"https://github.com/GoogleChromeLabs/html-setters-polyfill\"><code class=\"language-text\">html-setters-polyfill</code>을 출시했으며</a> <a href=\"https://www.npmjs.com/package/html-setters-polyfill\">npm에서 사용 가능합니다</a>.</p>\n<p>이 폴리필은 스트리밍을 지원하지 않으며, 완료될 때까지 버퍼링한 후 적용합니다. 기능 자체보다는 API 형태에 대한 폴리필에 가깝습니다.</p>\n<p>안전한 콘텐츠 설정은 <code class=\"language-text\">setHTML</code>과 Safari에서 지원하지 않는 <a href=\"https://developer.mozilla.org/docs/Web/API/HTML_Sanitizer_API\">Sanitizer API</a>에 의존합니다.</p>\n<h2 id=\"이-두-가지를-함께-사용하기\" style=\"position:relative;\"><a href=\"#%EC%9D%B4-%EB%91%90-%EA%B0%80%EC%A7%80%EB%A5%BC-%ED%95%A8%EA%BB%98-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0\" aria-label=\"이 두 가지를 함께 사용하기 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>이 두 가지를 함께 사용하기</h2>\n<p>두 가지 별개의 API지만, 함께 사용할 때 진정한 효과를 발휘합니다. 새로운 <code class=\"language-text\">&lt;template for></code> 요소를 HTML로 스트리밍하면 DOM에 대한 별도의 자바스크립트 참조 없이도 콘텐츠의 여러 부분을 동적으로 업데이트할 수 있습니다.</p>\n<p>기본적인 SPA 방식의 페이지 로드는 처리 명령어가 포함된 개요 페이지를 로드한 다음, 각 새 페이지의 템플릿을 HTML 하단으로 스트리밍하여 해당 처리 명령어에 삽입하는 방식으로 구현할 수 있습니다.</p>\n<p>두 API 모두 더 많은 가능성과 사용 사례가 있으니, (제한된!) 상상력에 제약을 받지 마세요. 부분 업데이트를 더 쉽게 관리할 수 있게 함으로써 보일러플레이트 코드를 줄이고, 업데이트를 단순화하며, 웹의 새로운 잠재력을 열어줄 것입니다.</p>\n<br/>\n<blockquote>\n<p>🚀 한국어로 된 프런트엔드 아티클을 빠르게 받아보고 싶다면 Korean FE Article(<a href=\"https://kofearticle.substack.com/\">https://kofearticle.substack.com/</a>)을 구독해주세요!</p>\n</blockquote>","frontmatter":{"title":"(번역) 선언적 부분 업데이트","date":"June 19, 2026","thumbnail":null,"canonicalUrl":null}}},"pageContext":{"slug":"/translation/2026/declarative-partial-updates/","previous":{"fields":{"slug":"/translation/2026/what-to-know-in-js-2026/"},"frontmatter":{"title":"(번역) 2026년판 자바스크립트 개발자가 알아야 할 것들"}},"next":null}},"staticQueryHashes":["1873090088","3128451518"]}