์ธ๋ถ ์๋ฐ์คํฌ๋ฆฝํธ ์ ์ด ๋ฐ MutationObserver๋ฅผ ์ด์ฉํ ํ์ด์ง ์๋ ๊ฐ์ ๋ฐฉ๋ฒ
๋ธ๋ก๊ทธ ๋ก๋ฉ ์๋๋ฅผ ๋์ด๊ณ ๋ถํ์ํ ๋ฆฌ์์ค๋ฅผ ์ฐจ๋จํ๋ ์น์ฌ์ดํธ ์ฑ๋ฅ ์ต์ ํ ์ ๋ต์ ์์๋ณด์ธ์. MutationObserver API์ ์ง์ฐ ๋ก๋(Lazy Load)๋ฅผ ํ์ฉํด ๋ฐฉ๋ฌธ์ ๊ฒฝํ(UX)๊ณผ ๊ตฌ๊ธ SEO ์ ์๋ฅผ ๋น์ฝ์ ์ผ๋ก ํฅ์์ํฌ ์ ์์ต๋๋ค.
ํฐ์คํ ๋ฆฌ๋ ์๋ํ๋ ์ค ํ๋ซํผ ์ด์ ์, ์ฌ์ฉ์๊ฐ ์ง์ ์ค์นํ์ง ์์ ์๋ง์ ์ธ๋ถ ์๋ฐ์คํฌ๋ฆฝํธ(External JavaScript)์ ๋ถํ์ํ ํธ๋ํน ๋ฆฌ์์ค๋ค์ด ๋ธ๋ก๊ทธ ์๋๋ฅผ ์ ํ์ํค๋ ๊ฒ์ ํํ ๋ณผ ์ ์์ต๋๋ค. ์ด๋ ๊ตฌ๊ธ์ ํต์ฌ ์์ ๊ฒฐ์ ์์์ธ ์ฝ์ด ์น ๋ฐ์ดํ(Core Web Vitals) ์ ์์ ์น๋ช ์ ์ธ ์ํฅ์ ๋ฏธ์นฉ๋๋ค.
๋ธ๋ก๊ทธ ์ต์ ํ 2ํธ์ ํต์ฌ์ธ ์ด ๋ฐฉ๋ฒ์, ๋ธ๋ผ์ฐ์ ๊ฐ ๋ฆฌ์์ค๋ฅผ ์์ฒญํ๊ธฐ ์ ์ ๊ฐ์ ํ์ฌ ๋ถํ์ํ ์คํฌ๋ฆฝํธ๋ฅผ ์์ฒ ์ฐจ๋จํ๊ณ ํ์ ๋ฆฌ์์ค๋ฅผ ์ ๋ณ์ ์ผ๋ก ๋ก๋ํ์ฌ ์น ์ฑ๋ฅ์ ํฅ์์ํต๋๋ค.
1. ์ธ๋ถ ์๋ฐ์คํฌ๋ฆฝํธ๊ฐ ๋ธ๋ก๊ทธ ์๋ ๋ฐ SEO์ ๋ฏธ์น๋ ์ํฅ
๋๋ถ๋ถ์ ์คํจ์ ์ฌ์ฉ์ ๋ถ์ ๋๊ตฌ(Tiara), ์ธ๋ถ ๊ด๊ณ ์๋ฒ(Pubmatic, Dable), ๋ผ์ด๋ธ๋ฌ๋ฆฌ(jQuery) ๋ฑ์ ๊ธฐ๋ณธ ํธ์ถํฉ๋๋ค. ์ด๋ฌํ ๋ฆฌ์์ค ์ ์ด๊ฐ ๋์ง ์์ ๊ฒฝ์ฐ ๋ค์๊ณผ ๊ฐ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํฉ๋๋ค.
- ๋ ๋๋ง ์ฐจ๋จ ๋ฆฌ์์ค(Render-Blocking): ๋ธ๋ผ์ฐ์ ๊ฐ ์คํฌ๋ฆฝํธ๋ฅผ ์์ ํ ๋ก๋ํ๊ณ ์คํํ ๋๊น์ง ํ๋ฉด ์ถ๋ ฅ์ ๋ฉ์ถ๋ฏ๋ก ํ์ด์ง ๋ก๋ฉ ์๋๊ฐ ๊ธ๊ฒฉํ ๋๋ ค์ง๋๋ค.
- ๋ถํ์ํ CPU ์ ์ : ๋ชจ๋ฐ์ผ ํ๊ฒฝ์์ ๊ณผ๋ํ ์๋ฐ์คํฌ๋ฆฝํธ ์คํ์ ๊ธฐ๊ธฐ ๋ฐ์ด์ ์ ๋ฐํ๊ณ FID(์ต์ด ์ ๋ ฅ ์ง์ฐ) ์๊ฐ์ ์ฆ๊ฐ์ํต๋๋ค.
- ๋ฐ์ดํฐ ์๋ชจ ๋ฐ ์ดํ๋ฅ ์ฆ๊ฐ: ๋ณด์ด์ง ์๋ ์์ญ์ ๊ด๊ณ ์คํฌ๋ฆฝํธ ๋ก๋ฉ์ผ๋ก ์ค์ ์ฝํ ์ธ ํ์ธ์ด ๋ฆ์ด์ง๋ฉด ๋ฐฉ๋ฌธ์๋ ์ฆ์ ์ฌ์ดํธ๋ฅผ ์ดํํฉ๋๋ค.
2. MutationObserver๋ฅผ ํ์ฉํ ๊ณ ๊ธ ์๋ฐ์คํฌ๋ฆฝํธ ์ ์ด ๋ฐฉ์
์ต์ ํ์ ํต์ฌ์ ๋ฆฌ์์ค ์์ฒญ ์ ๋จ๊ณ์์์ ๊ฐ์ ์ ๋๋ค. MutationObserver API๋ DOM(Document Object Model)์ ๋ณํ๋ฅผ ์ค์๊ฐ์ผ๋ก ๊ฐ์ํ์ฌ ํน์ ์์๊ฐ ์ถ๊ฐ๋๋ ์ฆ์ ์ ์ด๊ถ์ ๊ฐ์ง๋๋ค.
2.1 MutationObserver์ ํต์ฌ ๊ฐ๋ ๊ณผ ๋์ ์๋ฆฌ
์ผ๋ฐ์ ์ธ ์ด๋ฒคํธ ๋ฆฌ์ค๋๊ฐ ์ฌ์ฉ์์ ์ํธ์์ฉ์ ๋ฐ์ํ๋ค๋ฉด, ์ด API๋ HTML ๊ตฌ์กฐ ์์ฒด๊ฐ ๋ณํ๋ ์๊ฐ์ ํฌ์ฐฉํฉ๋๋ค.
- Mutation(๋ณํ): ์๋ก์ด ํ๊ทธ(Node)๊ฐ ์ถ๊ฐ๋๊ฑฐ๋ ์์ฑ์ด ๋ณ๊ฒฝ๋๋ ๋ชจ๋ ํ์.
- Observer(๊ด์ฐฐ์): ์ค์๊ฐ ๊ฐ์๋ฅผ ํตํด ์กฐ๊ฑด์ ๋ง๋ ์์ ๋ฐ๊ฒฌ ์ ์ฆ์ ์ฐจ๋จ ๋๋ ์์ ๋ก์ง ์คํ.
2.2 ์ฝ๋ ๋ด ์ค์๊ฐ ๊ฐ์ ๋ฐ ๋ ธ๋ ํํฐ๋ง 4๋จ๊ณ
- ์ ์ฒด ๊ฐ์ ์์:
observer.observe๋ฅผ ํตํด HTML ๋ฌธ์ ์ ์ฒด๋ฅผ ๊ฐ์ ๋์์ผ๋ก ์ค์ ํฉ๋๋ค. - ๋ ธ๋ ์ฝ์ ํฌ์ฐฉ: ์ธ๋ถ ์๋ฒ๋ ๊ด๊ณ ๋ชจ๋์ด ์คํฌ๋ฆฝํธ๋ฅผ ์ฝ์ ํ๋ ค๋ ์ฐฐ๋๋ฅผ ๊ฐ๋ก์ฑ๋๋ค.
- ๋ธ๋๋ฆฌ์คํธ ๊ฒ๋ฌธ: ํด๋น ๊ฒฝ๋ก๊ฐ ์ฐจ๋จ ๋ฆฌ์คํธ(blockList)์ ํฌํจ๋์ด ์๋์ง ์ฆ์ ๋์กฐํฉ๋๋ค.
- ๊ฐ์ ์ ๊ฑฐ ๋ฐ ์ง์ฐ ๋ก๋: ๊ด๊ณ ๋ ํธ๋ํน ์์๋
node.remove()๋ก ์์ฒ ์ ๊ฑฐํ๊ณ , ํ์ ๋ฆฌ์์ค๋ ์ง์ฐ ๋ก๋ํ์ฌ ์ด๊ธฐ ์๋๋ฅผ ํ๋ณดํฉ๋๋ค.
2.3 ์ฑ๋ฅ ์ต์ ํ์ ์นํธํค๊ฐ ๋๋ ์ด์
์ฌํ์ ์ง์ฐ๋ ๋ฐฉ์์ด ์๋๋ผ, ๋ธ๋ผ์ฐ์ ๊ฐ ํ์ผ์ ๋ค์ด๋ก๋ํ๊ธฐ ์ DOM ์ถ๊ฐ ์์ ์ ๊ฐ๋ก์ฑ๊ธฐ ๋๋ฌธ์ ๋คํธ์ํฌ ๋์ญํญ ๋ญ๋น๋ฅผ ๋ง๊ณ ๋ฉ์ธ ์ค๋ ๋ ๋ถํ๋ฅผ ํ๊ธฐ์ ์ผ๋ก ์ค์ ๋๋ค. ์ด๊ฒ์ด ๋ฐ๋ก ๊ตฌ๊ธ PageSpeed Insights ์ ์๋ฅผ ์ฌ๋ฆฌ๋ ๋น๊ฒฐ์ ๋๋ค.
// MutationObserver๋ฅผ ํ์ฉํ ๊ธฐ๋ณธ ์ต์ ํ ๊ตฌ์กฐ
const observer = new MutationObserver(mutations = {
for (let m of mutations) {
for (let node of m.addedNodes) {
// ์คํฌ๋ฆฝํธ, ๋งํฌ, ์ดํ๋ ์ ๋ฑ์ ์ค์๊ฐ ๊ฐ์ง ๋ฐ ์ ์ด
}
}
});
3. ๊ธฐ์ ์ SEO ์ต์ ํ ์ธ๋ถ ์ ๋ต
๊ฒ์ ์์ง์ด ์ ํธํ๋ ์ต์ ํ๋ ๊ตฌ์กฐ๋ฅผ ๋ง๋ค๊ธฐ ์ํ ์ธ๋ถ ๊ธฐ์ ๋ค์ ๋๋ค.
3.1 ์ ํ๋ธ ์ดํ๋ ์ ์ต์ ํ (Lazy Load No-Cookie)
๋ธ๋ก๊ทธ ์๋ ์ ํ์ ์ฃผ๋ฒ์ธ ๋์์(์ ํ๋ธ ์๋ฒ ๋ ์์)์ ํจ์จ์ ์ผ๋ก ๊ด๋ฆฌํฉ๋๋ค.
- ๋ ์ด์ง ๋ก๋ฉ(Lazy Loading):
loading='lazy'์์ฑ์ ์ฃผ์ ํ์ฌ ์ฌ์ฉ์๊ฐ ์์ ์์น๊น์ง ์คํฌ๋กคํ๊ธฐ ์ ์๋ ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์ค์ง ์์ต๋๋ค. - ๊ฐ์ธ์ ๋ณด ๋ณดํธ ๋๋ฉ์ธ ์ฌ์ฉ: ์ฃผ์๋ฅผ
youtube-nocookie.com์ผ๋ก ์ ํํ์ฌ ๊ฐ์ธ์ ๋ณด ์์ง์ ์ค์ด๊ณ ์์ ๋ก๋ฉ ์๋๋ฅผ ๊ฐ์ ํฉ๋๋ค.
3.2 ๋ถํ์ํ ๋ฉํ ๋ฐ์ดํฐ ๋ฐ ์คํ์ผ์ํธ(CSS) ์ ๊ฑฐ
ํ์ ์๋ ์ฝ๋๋ ๊ธฐ๋ณธ ๋ฉ๋ด ์คํ์ผ์ ์ฐพ์ ์ง์ฐ๋ฉด ๋ธ๋ผ์ฐ์ ๊ฐ ์ฝ์ด์ผ ํ ํ์ผ์ด ์ค์ด๋ค์ด ํ์ด์ง ์๋ต์ฑ์ด ๋์์ง๋๋ค. ๊ธฐ๋ณธ ๋ฉ๋ด๋ฐ๋ฅผ ์ ๊ฑฐํด๋ ์ฌ์ด๋๋ฐ์ ๋งํฌ๋ฅผ ๊ตฌ์ฑํ๋ฉด ๊ธฐ๋ฅ ์์ค ์์ด ํ์ด์ง ์๋ ๊ฐ์ ์ด ๊ฐ๋ฅํฉ๋๋ค.

4. ๋ธ๋ก๊ทธ ์ฝํ ์ธ ๋ณดํธ ๋ฐ ๋ถ๋ฒ ๋ณต์ ๋ฐฉ์ง
์๋ ์ต์ ํ๋งํผ ์ค์ํ ๋ณด์ ์ค์ ์ ๋๋ค. ํน์ ๋๋ฉ์ธ์์๋ง ์๋ํ๋ ๋ณดํธ ๊ธฐ๋ฅ์ ํตํด ์ ์ฑ๊ป ์์ฑํ ํฌ์คํ ์ ๊ณ ์ ์ฑ์ ์งํต๋๋ค. ๊ธฐ๋ณธ ํ๋ฌ๊ทธ์ธ ๋์ ์ฝ๋๋ฅผ ์ง์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ฑ๋ฅ ๋ฉด์์ ์ ๋ฆฌํฉ๋๋ค.
- ์ฐํด๋ฆญ ๋ฐ ๋๋๊ทธ ์ฐจ๋จ:
contextmenu์ด๋ฒคํธ๋ฅผ ์ ์ดํ์ฌ ๋ฌด๋จ ๋ณต์ฌ๋ฅผ ๋ฐฉ์งํฉ๋๋ค. - ๋จ์ถํค ์ ํ: Ctrl+U, Ctrl+S, F12 ๋ฑ์ ํค ์ ๋ ฅ์ ์ฐจ๋จํ์ฌ ์ฝ๋ ๋ฐ ํ ์คํธ ์ ์ถ์ ์ต์ํํฉ๋๋ค.
5. ๋ธ๋ก๊ทธ ์ ์ฉ ๋ฐฉ๋ฒ ๋ฐ ์ค์ ์ฝ๋
- ๋ธ๋ก๊ทธ ๊ด๋ฆฌ์์ [์คํจ ํธ์ง] - [html ํธ์ง]์ผ๋ก ์ง์ ํฉ๋๋ค.
- ์ต์ ํ ์คํฌ๋ฆฝํธ๋ฅผ
headํ๊ทธ ์ต์๋จ ํน์body์์ ์งํ์ ์ฝ์ ํฉ๋๋ค. - ์ฝ๋ ๋ด ๋๋ฉ์ธ ํ์ธ ๋ถ๋ถ์ ์์ ์ ๋ธ๋ก๊ทธ ์ฃผ์๋ฅผ ์ ํํ ๊ธฐ์ ํฉ๋๋ค.
- ์ ์ฅ ํ PageSpeed Insights์์ ์งํ ๊ฐ์ ์ฌ๋ถ๋ฅผ ํ์ธํฉ๋๋ค.
5.1 ์ ์ญ ๊ฐ์ฒด ์ด๊ธฐํ ๋ฐ ๊ธฐ์กด ๊ธฐ๋ฅ ๋ฌด๋ ฅํ
// 1. ์ด๊ธฐ ์ํ ์ค์ ๋ฐ ํฐ์คํ ๋ฆฌ ๊ธฐ๋ณธ ๋ถ์ ๋๊ตฌ(Tiara) ๋ฌด๋ ฅํ
window.loadedComments = true; // ๋๊ธ ์ค๋ณต ๋ก๋ฉ ๋ฐฉ์ง
window.Tiara = window.Tiara || { __track: function(){} }; // ํต๊ณ ๋๊ตฌ ๋ฌด๋ ฅํ
window.tistoryCommentInit = function(){}; // ๋๊ธ ์ด๊ธฐํ ๋ฌด๋ ฅํ
var deferredScripts = {};
var deferredStyles = {};
5.2 ์ ์ด ๋์ ๋ฆฌ์คํธ ์ ์ (ํํฐ๋ง ๊ธฐ์ค)
// ์ด์ ์ค์ธ ๋ธ๋ก๊ทธ ํ๊ฒฝ์ ๋ง์ถฐ ๋์์ ์ ๋ณ ์ ์ฉํฉ๋๋ค.
var deferTargets = ['์ง์ฐํ ์ฝ๋'];
var blockList = ['์ฐจ๋จํ ์ฝ๋'];
5.3 MutationObserver๋ฅผ ์ด์ฉํ ์ค์๊ฐ ๊ฐ๋ก์ฑ๊ธฐ
const observer = new MutationObserver(mutations = {
for (let m of mutations) {
for (let node of m.addedNodes) {
// ์คํฌ๋ฆฝํธ ํ๊ทธ ์ ์ด
if (node.tagName === 'SCRIPT') {
const src = node.src || '';
if (deferTargets.some(t = src.includes(t))) {
deferredScripts[src] = true;
node.remove();
continue;
}
if (blockList.some(b = src.includes(b))) node.remove();
}
// ์ ํ๋ธ ์ต์ ํ ๋ฐ ๊ธฐํ ์์ ์ ๊ฑฐ
if (node.tagName === 'IFRAME' && (node.src || '').includes('youtube.com/embed/')) {
node.setAttribute('loading', 'lazy');
node.src = node.src.replace('youtube.com', 'youtube-nocookie.com');
}
if (node.tagName === 'INS') node.remove();
}
}
});
observer.observe(document.documentElement, { childList: true, subtree: true });
setTimeout(() = observer.disconnect(), 5000);
์ด ์ฝ๋๋ ๋ธ๋ก๊ทธ์ "๋ฌธ์ง๊ธฐ" ์ญํ ์ ์ํํฉ๋๋ค. ์ฐจ๋จ ๋์์ ์ฆ์ ๋๋ ค๋ณด๋ด๊ณ , ์ง์ฐ ๋ก๋ฉ ๋์์ ํ์ด์ง์ ํต์ฌ ํ ์คํธ๊ฐ ๋ชจ๋ ๋ํ๋ ํ ์คํ๋๋๋ก ๋๊ธฐ์ํต๋๋ค. ๊ฒฐ๊ณผ์ ์ผ๋ก ๋ฐฉ๋ฌธ์๋ ๋ฌด๊ฑฐ์ด ๊ด๊ณ ๋ ๋ถ์ ํด์ ๊ธฐ๋ค๋ฆด ํ์ ์์ด ์ฆ์ ์ฝํ ์ธ ๋ฅผ ์ฆ๊ธธ ์ ์์ต๋๋ค.
์น ํ๊ฒฝ์ด ๊ณ ๋ํ๋ ์๋ก ๋ธ๋ก๊ทธ ์๋ ์ต์ ํ๋ ํ์์ ๋๋ค. ์ฌ๋ฐ๋ฅธ ์๋ฐ์คํฌ๋ฆฝํธ ์ ์ด๋ฅผ ํตํด ์ฌ์ฉ์์๊ฒ๋ ์พ์ ํ UX๋ฅผ ์ ๊ณตํ๊ณ ๊ฒ์ ์์ง์๊ฒ๋ ์ต์ ํ๋ ์ฌ์ดํธ๋ผ๋ ๊ฐ๋ ฅํ ์ ํธ๋ฅผ ๋ณด๋ด์ญ์์ค.