document.write을 사용하면 돔 랜더링이 멈추기 때문에 느리게 보인다. 그래서document.write을 대신하기 위한 다양한 방법이 나와있다. 하지만, 광고의 경우 다양한 곳에 삽입되기 때문에 대부분은 document.write을 사용한다.
이 문제를 해결하고자 최근에 웹성능의 본좌인 사우더스 아저씨가 HTML import을 활용한 방법을 제안했다.[링크] (HTML import는 본인과 크게 상관도 없고 아직 완성도가 있는 스팩인데 이런걸 활용하다니 좀 놀랐다.)
HTML import를 간단히 설명하면 Web Components을 사용하기 위한 방법으로 link태그를 이용하여 html을 로딩하는 방법이다.[링크]
자세한 내용은 원문[링크]을 참고하고 요약하면 사우더스 아저씨는 아래와 같이 import안에서 document.write를 하는 방법을 제안했다.
main.html
<link rel="import" href="ad.html"> <div id="ad_area" style="width: 480px; height: 60px; margin-left: 2em; margin-bottom: 2em;"></div> <script> var link = document.querySelector('link[rel=import]'); var content = link.import.querySelector('#ad'); document.getElementById('ad_area').appendChild(content.cloneNode(true)); </script>
<div id="ad" style="background: #E99; border: 2px; font-size: 2em; text-align: center; padding: 8px;"> <script> document.write("IMPORTED CONTENT<div style='font-size=0.8em;'>(using document.write)</div>"); </script>
근데 문제가 있다.
1. import는 동기로 로딩된다.[링크]
2. import한 html에서 document.write을 하면 main페이지에서 context로 실행되는 문제가 있다.[링크]
그래서 이를 해결하고자 아래와 같이 스크립트로 import을 삽입하고 ad.html에서 document.write을 재정의하여 현재 context로 실행하도록 했다.
main.html
<div id="ad_area" style="width: 480px; height: 60px; margin-left: 2em; margin-bottom: 2em;"></div> <script> var link = document.createElement('link'); link.rel = 'import'; link.onload = function() { var link = document.querySelector('link[rel=import]'); var content = link.import.querySelector('#ad'); document.getElementById('ad_area').appendChild(content.cloneNode(true)); }; link.href = "ad.html"; document.getElementsByTagName('head')[0].appendChild(link); </script>
ad.html
<div id="ad" style="background: #E99; border: 2px; font-size: 2em; text-align: center; padding: 8px;"> <script> document.write = function(msg) { document.currentScript.ownerDocument.write(msg); }; document.write("IMPORTED CONTENT<div style='font-size=0.8em;'>(using document.write)</div>"); </script>
이렇게 document.write를 사용하면서 돔의 랜더링을 지연하지 않도록 개선할 수 있다.[링크]
물론 import의 안에서 실행되는 context의 이슈등 문제가 있어 당장 사용하기 힘들지만 아이디어는 좋은 것 같다.
그리고 사우더스는 HTML import가 기본으로 랜더링을 막지 말고 동작해야 한다고 제안했지만 이 문제는 쉽지 않다. 이 문제에 대해서는 다음에 알아보자. 또한 위의 방법은 오해가 있기 때문에 반드시 [링크]을 추가로 읽기 바란다.
관련글