Lobsters

Inline rendering with document.currentScript

document.currentScript로 HTML 안에서 바로 렌더링하기

실행 중인 script 요소를 document.currentScript로 찾아 자기 자리에 결과를 렌더링하는 방법을 소개합니다. 별도 템플릿 언어나 ID 선택자 없이 날짜, 문구, 간단한 상호작용을 HTML 가까이에서 처리하지만, 비동기 데이터 처리에는 추가 요청과 HTML 보안 처리가 따릅니다.

에디터 노트

이 방식의 장점은 동적 콘텐츠의 코드와 표시 위치를 가까이 두는 데 있습니다. 연도 표시부터 글 안의 카운터까지 예시가 이를 뒷받침하며, 댓글도 프레임워크 컴포넌트와 비슷한 추상화를 가볍게 구현한다는 점을 짚습니다. 다만 템플릿 언어를 대체하는 범위는 좁습니다. 업데이트는 저장해 둔 script 요소를 이용해 비동기 데이터도 렌더링할 수 있음을 보여주지만, 클라이언트 요청이 추가되고 외부 HTML은 정화해야 합니다. 따라서 정적인 페이지에 작은 동작을 곁들이는 사례와 데이터 중심 템플릿을 구분하는 설명이 설득력 있습니다.

AI 요약

간단한 동적 콘텐츠를 표시할 때는 Handlebars 같은 템플릿 언어나 PHP 백엔드가 꼭 필요하지 않습니다. document.currentScript는 현재 실행 중인 script 요소를 가리키므로, 스크립트가 자기 자신을 계산한 값으로 바꾸면 HTML 안에서 결과를 바로 렌더링합니다.

스크립트가 자기 자리를 바꾸는 방식

예를 들어 “Come on, it’s ” 뒤에 현재 연도를 붙이려면 다음처럼 작성합니다.

<pre>Come on, it’s &lt;script&gt;document.currentScript.replaceWith(new Date().getFullYear())&lt;/script&gt;</pre>

스크립트는 실행되면서 자기 요소를 연도로 교체합니다. 별도 ID나 class, querySelector가 필요하지 않습니다. 글에서는 document.currentScript.replaceWith를 짧게 감싼 $ 별칭도 제시합니다. 다만 별칭을 여러 페이지에서 쓰려고 외부 스크립트로 불러오면 HTML 파싱과 렌더링을 막는 요청이 생길 수 있어, 저자는 별칭 없이 document.currentScript를 직접 쓰는 편이라고 설명합니다.

텍스트와 상호작용을 가까이 배치하기

같은 방식으로 페이지 방문 때마다 인사말을 고르거나, 2017년을 “몇 년 전”으로 표시할 수 있습니다. script 요소의 outerHTML을 바꾸면 문자열을 문자별 strong 요소로 나눠 애니메이션을 적용하는 마크업도 만들 수 있습니다. 게시물 제목은 title 메타데이터에서 읽어 본문 제목에 표시하고, 저작권 표기에는 현재 연도를 넣습니다. JavaScript가 꺼진 환경을 위해 noscript 안에 대체 문구를 두는 예도 나옵니다.

카운터 예시는 script 요소의 부모에서 span과 버튼을 찾아 각각 증감 동작을 연결합니다. 로직이 관련 HTML 바로 옆에 있어 긴 글 중간의 인터랙티브 요소를 해당 위치에서 관리하기 편하다는 설명입니다. 글쓴이는 이런 구성을 상호작용하는 작은 영역, 즉 islands of interactivity를 관리하는 방법으로 제시합니다.

데이터 렌더링과 제약

본문은 처음에 이 기법으로 데이터 기반 템플릿을 만들 수 없다고 설명했지만, 업데이트에서 그 제한을 바로잡습니다. 실행 중인 script 요소를 변수에 저장하면 비동기 작업이 끝난 뒤에도 그 요소를 참조할 수 있습니다. 예시에서는 fetch로 /posts.json을 가져와 게시물 링크 목록을 만들고, 저장해 둔 script 요소의 outerHTML을 결과 HTML로 바꿉니다. 이 방식은 클라이언트에서 추가 HTTP 요청을 발생시키며, 외부에서 가져온 내용으로 innerHTML이나 outerHTML을 바꿀 때는 먼저 HTML을 정화해야 합니다. 글은 setHTML도 대안으로 언급합니다.

저자는 게시물 날짜나 제목, 태그를 프런트매터에서 읽어 템플릿에 적용하는 작업에는 Liquid 같은 템플릿 언어가 더 적합하다고 설명합니다. 다만 업데이트에서 보인 것처럼 비동기 데이터 렌더링 자체가 불가능한 것은 아닙니다. document.write는 과거 비슷한 용도로 쓰였지만 동작이 일관되지 않아 폐기된 API라고 덧붙입니다.

Lobsters 반응

  • @kchanqvq — 멋진 요령이네요! 이런 시대에도 귀여운 코드를 즐기는 동료 개발자를 만나 반갑습니다.
  • @freddyb — innerHTML이나 outerHTML을 쓴다면 HTML을 정화해야 한다고 다시 알립니다. 특히 외부에서 가져온 콘텐츠라면 더욱 그렇습니다. 아니면 setHTML을 쓰세요.
  • @BasicallyEternity — 카운터 예시가 정말 마음에 듭니다. 현대적인 컴포넌트 기반 JavaScript 프레임워크 코드와 추상화 수준이 비슷하지만 훨씬 가볍고 브라우저에 내장되어 있습니다.

원문: leanrada.com / 번역·요약: Trawling