์ƒˆ๋กœ์šด DOM API, setHTML์„ ์•Œ์•„๋ณด์ž

์ƒˆ๋กœ์šด DOM API, setHTML์„ ์•Œ์•„๋ณด์ž

D
dongAuthor
4 min read

์›น ๊ฐœ๋ฐœ์„ ํ•˜๋‹ค ๋ณด๋ฉด ๋™์ ์œผ๋กœ HTML์„ ์‚ฝ์ž…ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค. ์ด๋•Œ ๊ฐ€์žฅ ํ”ํ•˜๊ฒŒ ์‚ฌ์šฉ๋˜๋Š” ๋ฐฉ๋ฒ•์€ innerHTML์ด์ง€๋งŒ, ์ด ๋ฐฉ๋ฒ•์€ ํฌ๋กœ์Šค ์‚ฌ์ดํŠธ ์Šคํฌ๋ฆฝํŒ…(XSS) ๊ณต๊ฒฉ์— ์ทจ์•ฝํ•˜๋‹ค๋Š” ํฐ ๋‹จ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋งŽ์€ ๊ฐœ๋ฐœ์ž๋“ค์ด DOMPurify์™€ ๊ฐ™์€ ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ด HTML์„ ์•ˆ์ „ํ•˜๊ฒŒ ์‚ฝ์ž…ํ•ด์™”์Šต๋‹ˆ๋‹ค.

์ด์ œ๋Š” ์›น ํ‘œ์ค€์— ๋‚ด์žฅ๋œ ์•ˆ์ „ํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ HTML์„ ์‚ฝ์ž…ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋  ์ „๋ง์ž…๋‹ˆ๋‹ค. ๋ฐ”๋กœ ์ƒˆ๋กœ์šด DOM API์ธ setHTML()์ด ๋“ฑ์žฅํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ด ๊ธ€์—์„œ๋Š” setHTML()์ด ๋ฌด์—‡์ธ์ง€, ์™œ ํ•„์š”ํ•œ์ง€, ๊ทธ๋ฆฌ๊ณ  ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•˜๋Š”์ง€์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

setHTML()์ด๋ž€ ๋ฌด์—‡์ธ๊ฐ€์š”?

setHTML()์€ Element ์ธํ„ฐํŽ˜์ด์Šค์˜ ์ƒˆ๋กœ์šด ๋ฉ”์„œ๋“œ๋กœ, ์ด๋ฆ„์—์„œ ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด HTML ๋ฌธ์ž์—ด์„ DOM ์š”์†Œ์— ์•ˆ์ „ํ•˜๊ฒŒ ์„ค์ •ํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฉ”์„œ๋“œ๋Š” ๋‹จ์ˆœํžˆ HTML์„ ์‚ฝ์ž…ํ•˜๋Š” ๊ฒƒ์„ ๋„˜์–ด, ๋‚ด์žฅ๋œ HTML Sanitizer API๋ฅผ ์‚ฌ์šฉํ•ด ๋ฌธ์ž์—ด์„ ํŒŒ์‹ฑํ•˜๊ณ  ์†Œ๋…(sanitize)ํ•˜๋Š” ๊ณผ์ •์„ ๊ฑฐ์นฉ๋‹ˆ๋‹ค.

setHTML()์˜ ์ฃผ์š” ํŠน์ง•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • XSS ๋ฐฉ์ง€: ์ž…๋ ฅ๋œ HTML ๋ฌธ์ž์—ด์—์„œ ์ž ์žฌ์ ์œผ๋กœ ์œ„ํ—˜ํ•œ <script> ํƒœ๊ทธ๋‚˜ onerror์™€ ๊ฐ™์€ ์ธ๋ผ์ธ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ๋“ฑ XSS ๊ณต๊ฒฉ์„ ์œ ๋ฐœํ•  ์ˆ˜ ์žˆ๋Š” ์š”์†Œ๋ฅผ ์ž๋™์œผ๋กœ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.
  • ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ: ํ˜„์žฌ ์š”์†Œ์˜ ์ปจํ…์ŠคํŠธ์— ๋งž์ง€ ์•Š๋Š” ์ž˜๋ชป๋œ ์š”์†Œ๋ฅผ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.
  • ๊ธฐ๋ณธ Sanitizer ์ œ๊ณต: ๋ณ„๋„์˜ ์„ค์ • ์—†์ด๋„ ๊ธฐ๋ณธ Sanitizer ๊ตฌ์„ฑ์„ ํ†ตํ•ด ์•ˆ์ „ํ•˜๊ฒŒ HTML์„ ์‚ฝ์ž…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

MDN ๋ฌธ์„œ์— ๋”ฐ๋ฅด๋ฉด, setHTML()์€ ํ—ˆ์šฉ๋˜์ง€ ์•Š์€ HTML ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ œ๊ฑฐํ•  ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ, Sanitizer ์„ค์ •์—์„œ ํ—ˆ์šฉ๋˜์—ˆ๋”๋ผ๋„ XSS์— ์•ˆ์ „ํ•˜์ง€ ์•Š์€ ์š”์†Œ๋‚˜ ์†์„ฑ์€ ๋ฌด์กฐ๊ฑด ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค. ๋•๋ถ„์— ๊ฐœ๋ฐœ์ž๋Š” ๋ณด์•ˆ ๊ฑฑ์ •์„ ๋œ๊ณ  ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์— ๋” ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์™œ setHTML()์„ ์‚ฌ์šฉํ•ด์•ผ ํ• ๊นŒ?

innerHTML์ด ์žˆ๋Š”๋ฐ ๊ตณ์ด setHTML()์„ ์จ์•ผ ํ•˜๋Š” ์ด์œ ๊ฐ€ ๊ถ๊ธˆํ•˜์‹ค ๊ฒ๋‹ˆ๋‹ค. ๋‘ ๋ฉ”์„œ๋“œ๋ฅผ ๋น„๊ตํ•˜๋ฉฐ setHTML()์˜ ์žฅ์ ์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

innerHTML๊ณผ์˜ ๋น„๊ต

innerHTML์€ ์‚ฌ์šฉํ•˜๊ธฐ ๊ฐ„ํŽธํ•˜์ง€๋งŒ, ๊ฐ€์žฅ ํฐ ๋ฌธ์ œ๋Š” ๋ณด์•ˆ์ž…๋‹ˆ๋‹ค. ์™ธ๋ถ€์—์„œ ๋ฐ›์€ ์‹ ๋ขฐํ•  ์ˆ˜ ์—†๋Š” ๋ฌธ์ž์—ด์„ innerHTML์— ๊ทธ๋Œ€๋กœ ํ• ๋‹นํ•˜๋ฉด, ๊ณต๊ฒฉ์ž๊ฐ€ ์‚ฝ์ž…ํ•œ ์•…์„ฑ ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ๊ทธ๋Œ€๋กœ ์‹คํ–‰๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

const userInput = `<img src=x onerror="alert('XSS ๊ณต๊ฒฉ!')">`;
const container = document.getElementById('container');

// userInput์— ํฌํ•จ๋œ ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์‹คํ–‰๋˜์–ด ๊ฒฝ๊ณ ์ฐฝ์ด ๋œน๋‹ˆ๋‹ค.
container.innerHTML = userInput;

๋ฐ˜๋ฉด, setHTML()์€ ์ด๋Ÿฐ ์œ„ํ—˜์„ ์›์ฒœ์ ์œผ๋กœ ์ฐจ๋‹จํ•ฉ๋‹ˆ๋‹ค.

const userInput = `<img src=x onerror="alert('XSS ๊ณต๊ฒฉ!')">`;
const container = document.getElementById('container');

// onerror ์†์„ฑ์ด Sanitizer์— ์˜ํ•ด ์ œ๊ฑฐ๋˜์–ด ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์‹คํ–‰๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
container.setHTML(userInput);

setHTMLUnsafe()์™€์˜ ๋น„๊ต

setHTML()๊ณผ ํ•จ๊ป˜ setHTMLUnsafe()๋ผ๋Š” ๋ฉ”์„œ๋“œ๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฆ„์— "Unsafe"๊ฐ€ ๋ถ™์€ ๊ฒƒ์—์„œ ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด, ์ด ๋ฉ”์„œ๋“œ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ HTML์„ ์†Œ๋…ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. XSS์— ์ทจ์•ฝํ•œ ์š”์†Œ๋ฅผ ํฌํ•จ์‹œ์ผœ์•ผ ํ•˜๋Š” ์•„์ฃผ ํŠน์ˆ˜ํ•œ ๊ฒฝ์šฐ๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด setHTML() ์‚ฌ์šฉ์ด ๊ฐ•๋ ฅํžˆ ๊ถŒ์žฅ๋ฉ๋‹ˆ๋‹ค. setHTMLUnsafe()๋Š” ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ์†Œ์Šค์˜ HTML์„ ์‚ฝ์ž…ํ•  ๋•Œ๋งŒ ์ œํ•œ์ ์œผ๋กœ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ฒฐ๋ก ์ ์œผ๋กœ, setHTML()์€ innerHTML์˜ ํŽธ๋ฆฌํ•จ์€ ์œ ์ง€ํ•˜๋ฉด์„œ ๋ณด์•ˆ์„ฑ์„ ํฌ๊ฒŒ ๋†’์ธ, innerHTML์˜ ์•ˆ์ „ํ•œ ๋Œ€์•ˆ์ด๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Element: setHTMLUnsafe() method

setHTML() ์‚ฌ์šฉ ๋ฐฉ๋ฒ•

setHTML()์˜ ๊ธฐ๋ณธ์ ์ธ ์‚ฌ์šฉ๋ฒ•์€ ๋งค์šฐ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค !

// ๊ธฐ๋ณธ์ ์ธ ์‚ฌ์šฉ๋ฒ•
const unsanitizedString = "์ด๊ฑด <b>์•ˆ์ „ํ•œ</b> HTML์ž…๋‹ˆ๋‹ค. <script>alert('์ด๊ฑด ์‹คํ–‰๋˜์ง€ ์•Š์•„์š”!')</script>";
const targetElement = document.getElementById("target");

// ๊ธฐ๋ณธ Sanitizer๋ฅผ ์‚ฌ์šฉํ•ด HTML ์‚ฝ์ž…
targetElement.setHTML(unsanitizedString);

์œ„ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด <script> ํƒœ๊ทธ๋Š” ์ œ๊ฑฐ๋˜๊ณ  "์ด๊ฑด ์•ˆ์ „ํ•œ HTML์ž…๋‹ˆ๋‹ค."๋ผ๋Š” ํ…์ŠคํŠธ๋งŒ ๋ Œ๋”๋ง๋ฉ๋‹ˆ๋‹ค.

options.sanitizer๋กœ ์‚ฌ์šฉ์ž ์ •์˜ํ•˜๊ธฐ

setHTML()์€ ๋‘ ๋ฒˆ์งธ ์ธ์ž๋กœ options ๊ฐ์ฒด๋ฅผ ๋ฐ›์•„ Sanitizer์˜ ๋™์ž‘์„ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. options.sanitizer ์†์„ฑ์„ ์‚ฌ์šฉํ•ด ํ—ˆ์šฉํ•˜๊ฑฐ๋‚˜ ์ œ๊ฑฐํ•  ํƒœ๊ทธ ๋ฐ ์†์„ฑ์„ ์ง์ ‘ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

const unsanitizedString = "<div>div ํƒœ๊ทธ</div> <p>p ํƒœ๊ทธ</p> <button>button ํƒœ๊ทธ</button>";
const targetElement = document.getElementById("target");

// 1. Sanitizer ๊ฐ์ฒด๋ฅผ ์ง์ ‘ ์ƒ์„ฑํ•˜์—ฌ ์ „๋‹ฌ
// div, p, button ํƒœ๊ทธ๋งŒ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค.
const customSanitizer = new Sanitizer({
  elements: ["div", "p", "button"],
});
targetElement.setHTML(unsanitizedString, { sanitizer: customSanitizer });

// 2. SanitizerConfig ๊ฐ์ฒด๋ฅผ ์ธ๋ผ์ธ์œผ๋กœ ์ „๋‹ฌ
// div์™€ p ํƒœ๊ทธ๋ฅผ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.
targetElement.setHTML(unsanitizedString, {
  sanitizer: { removeElements: ["div", "p"] },
});

SanitizerConfig๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ allowElements์™€ removeElements๋ฅผ ๋™์‹œ์— ์ •์˜ํ•˜๋Š” ๋“ฑ ์ •๊ทœํ™”๋˜์ง€ ์•Š์€ ์„ค์ •์„ ์ „๋‹ฌํ•˜๋ฉด TypeError๊ฐ€ ๋ฐœ์ƒํ•˜๋‹ˆ ์ฃผ์˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋ธŒ๋ผ์šฐ์ € ํ˜ธํ™˜์„ฑ์€ ์•„์ง๊นŒ์ง„โ€ฆ?

์•„์‰ฝ๊ฒŒ๋„ setHTML()์€ ์•„์ง ์‹คํ—˜์ ์ธ ๊ธฐ๋Šฅ์ด๋ฉฐ, ๊ธ€์„ ์ž‘์„ฑํ•˜๋Š” ์‹œ์  ๊ธฐ์ค€์œผ๋กœ ๋Œ€๋ถ€๋ถ„์˜ ์ฃผ์š” ๋ธŒ๋ผ์šฐ์ €์—์„œ ์ง€์›๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. Firefox Nightly ๋ฒ„์ „์—์„œ ๊ธฐ๋ณธ์œผ๋กœ ํ™œ์„ฑํ™”๋˜์—ˆ์œผ๋ฉฐ, ์ ์ฐจ ๋‹ค๋ฅธ ๋ธŒ๋ผ์šฐ์ €๋กœ ํ™•์‚ฐ๋  ๊ฒƒ์œผ๋กœ ๊ธฐ๋Œ€๋ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์‹ค์ œ ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ ์ „์—๋Š” ๋ฐ˜๋“œ์‹œ MDN์˜ ๋ธŒ๋ผ์šฐ์ € ํ˜ธํ™˜์„ฑ ํ‘œ๋ฅผ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ˜ธํ™˜์„ฑ์ด ํ™•๋ณด๋˜๊ธฐ ์ „๊นŒ์ง€๋Š” Sanitizer API Polyfill์„ ์‚ฌ์šฉํ•ด ๋น„์Šทํ•œ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ปค๋ฎค๋‹ˆํ‹ฐ์˜ ์‹œ์„ 

setHTML()์˜ ๋“ฑ์žฅ์€ ๋งŽ์€ ๊ฐœ๋ฐœ์ž ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ ๊ธ์ •์ ์ธ ๋ฐ˜์‘์„ ์–ป๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ํŠนํžˆ Hacker News์™€ ๊ฐ™์€ ํฌ๋Ÿผ์—์„œ๋Š” "25๋…„ ๋งŒ์— ๋“œ๋””์–ด ๋‚˜์™”๋‹ค"๋ฉฐ ํ™˜์˜ํ•˜๋Š” ๋ถ„์œ„๊ธฐ์ž…๋‹ˆ๋‹ค.

  • ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์˜์กด์„ฑ ๊ฐ์†Œ: ๊ฒฝ๋Ÿ‰ํ™” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ Lit์˜ ๊ฐœ๋ฐœ์ž๋Š” setHTML()์ด ํ‘œ์ค€์œผ๋กœ ์ž๋ฆฌ ์žก์œผ๋ฉด unsafeHTML ์ง€์‹œ์–ด ๋Œ€์‹  ์ด๋ฅผ ํ™œ์šฉํ•˜์—ฌ DOMPurify์™€ ๊ฐ™์€ ์™ธ๋ถ€ ์˜์กด์„ฑ ์—†์ด๋„ ์•ˆ์ „ํ•œ HTML ๋ Œ๋”๋ง์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋ผ๋ฉฐ ๊ธฐ๋Œ€๊ฐ์„ ํ‘œํ–ˆ์Šต๋‹ˆ๋‹ค. DOMPurify๋Š” ๊ฐ•๋ ฅํ•˜์ง€๋งŒ, lit-html ์ฝ”์–ด๋ณด๋‹ค ๋ช‡ ๋ฐฐ ๋” ํฌ๊ธฐ ๋•Œ๋ฌธ์— ๋‚ด์žฅ API์˜ ๋“ฑ์žฅ์€ ํฐ ์ด์ ์ž…๋‹ˆ๋‹ค.
  • innerHTML์˜ ์•ˆ์ „ํ•œ ๋Œ€์•ˆ: ๋งŽ์€ ๊ฐœ๋ฐœ์ž๋“ค์ด setHTML()์„ innerHTML์˜ ์•ˆ์ „ํ•œ ๋ฒ„์ „์ด์ž, npm์—์„œ ๋„๋ฆฌ ์“ฐ์ด๋Š” DOMPurify์˜ ๋‚ด์žฅ ๋ฒ„์ „์œผ๋กœ ์ดํ•ดํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์›น ํ”Œ๋žซํผ ์ž์ฒด์˜ ๋ณด์•ˆ์„ฑ์ด ํ•œ ๋‹จ๊ณ„ ๋ฐœ์ „ํ–ˆ์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

Hacker news

๊ฐœ์ธ์ ์œผ๋กœ ์ •๋ง ๋ฐ˜๊ฐ€์šด ์†Œ์‹์ž…๋‹ˆ๋‹ค !

setHTML()์€ innerHTML์˜ ๊ณ ์งˆ์ ์ธ ๋ณด์•ˆ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ณ  ์›น ํ‘œ์ค€์— ๋‚ด์žฅ๋œ ์•ˆ์ „ํ•œ HTML ์‚ฝ์ž… ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•˜๋Š” ์ค‘์š”ํ•œ API์ž…๋‹ˆ๋‹ค. ๋น„๋ก ์•„์ง ์‹คํ—˜ ๋‹จ๊ณ„์— ์žˆ์ง€๋งŒ, ์ด ๊ธฐ๋Šฅ์ด ๋ชจ๋“  ๋ธŒ๋ผ์šฐ์ €์— ์ •์‹์œผ๋กœ ๋„์ž…๋˜๋ฉด ๊ฐœ๋ฐœ์ž๋“ค์€ ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์˜์กด์„ฑ์„ ์ค„์ด๊ณ  ๋”์šฑ ์•ˆ์ „ํ•˜๊ณ  ๊ฒฌ๊ณ ํ•œ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ง€๊ธˆ ๋‹น์žฅ ํ”„๋กœ๋•์…˜์— ์ ์šฉํ•˜๊ธฐ๋Š” ์–ด๋ ต๊ฒ ์ง€๋งŒ, ์ด ์ƒˆ๋กœ์šด API์˜ ์กด์žฌ๋ฅผ ์ธ์ง€ํ•˜๊ณ  ํ…Œ์ŠคํŠธํ•ด๋ณด๋ฉด์„œ ๋ฏธ๋ž˜๋ฅผ ์ค€๋น„ํ•˜๋Š” ๊ฒƒ์€ ์–ด๋–จ๊นŒ์š”? setHTML()์ด ๊ฐ€์ ธ์˜ฌ ๋” ์•ˆ์ „ํ•œ ์›น ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์„ ๊ธฐ๋Œ€ํ•ด ๋ด…๋‹ˆ๋‹ค.

๊ฐœ์ธ์ ์œผ๋กœ ์ง€๊ธˆ ์ด ๋ธ”๋กœ๊ทธ๋„ HTML์„ ์ง์ ‘์ ์œผ๋กœ ๋‹ค๋ฃจ๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์€๋ฐ ์ •๋ง ํฌ์†Œ์‹์ด๋„ค์š”! ๐Ÿคฃ
์–ผ๋ฅธ ์•ˆ์ •ํ™” ๋˜์—ˆ์œผ๋ฉด ์ข‹๊ฒ ์Šต๋‹ˆ๋‹ค ! ๐Ÿฅน

References

์ƒˆ๋กœ์šด DOM API, setHTML์„ ์•Œ์•„๋ณด์ž | devdong