๐Ÿงฉ 04. ๋„ค์ดํ‹ฐ๋ธŒ HTML ์‹ฌํ™” ์š”์†Œ: JavaScript ์—†์ด ๋ชจ๋‹ฌ์ด ๋œ๋‹ค๊ณ ?

2026๋…„ 3์›” 5์ผ ์ˆ˜์ •๋จ

๐Ÿ“‹ ๊ฐœ์š”

dialog, details/summary, popover API, template/slot โ€” ํ˜„๋Œ€ ๋ธŒ๋ผ์šฐ์ € ๋„ค์ดํ‹ฐ๋ธŒ HTML ๊ธฐ๋Šฅ์œผ๋กœ JS ์—†์ด ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ๋“ค์„ ํŒŒํ—ค์นฉ๋‹ˆ๋‹ค.

๐Ÿ“Œ ์ด ๋ฌธ์„œ๋ฅผ ์ฝ๊ธฐ ์ „์—

โฑ๏ธ ์˜ˆ์ƒ ์ฝ๊ธฐ ์‹œ๊ฐ„: 18๋ถ„ / ํ•ต์‹ฌ ํŒŒํŠธ๋งŒ: 10๋ถ„

๐ŸŽฏ ์ด ๋ฌธ์„œ์˜ ์œ„์น˜

HTML guide 01~04๋ฒˆ์„ ๋จผ์ € ์ฝ์–ด๋ณด์„ธ์š”. ๋„ค์ดํ‹ฐ๋ธŒ dialog API์™€ React ๋ชจ๋‹ฌ ํŒจํ„ด์„ ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ—บ๏ธ ์ด ๋ฌธ์„œ์˜ ํ๋ฆ„

[<dialog> โ€” ๋„ค์ดํ‹ฐ๋ธŒ ๋ชจ๋‹ฌ] โ†’ [<details>/<summary> โ€” ์•„์ฝ”๋””์–ธ] โ†’ [Popover API] โ†’ [React์™€์˜ ํ†ตํ•ฉ]

๐ŸŽฏ ์ด ๋ฌธ์„œ๋ฅผ ๋‹ค ์ฝ์œผ๋ฉด ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ

  • <dialog> ๋กœ ๋ชจ๋‹ฌ์„ ๊ตฌํ˜„ํ•˜๊ณ  .showModal() / .close() API๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • <details> + <summary> ๋กœ JS ์—†๋Š” ์•„์ฝ”๋””์–ธ/FAQ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.
  • Popover API๋กœ ํˆดํŒ/๋“œ๋กญ๋‹ค์šด์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • React์—์„œ <dialog> ๋ฅผ ํ™œ์šฉํ•˜๋Š” ํŒจํ„ด์„ ์ดํ•ดํ•œ๋‹ค.

๐Ÿ—บ๏ธ ์ด ๋ฌธ์„œ์˜ ๋ฐฐ๊ฒฝ ์„ธ๊ณ„๊ด€: '์˜์ˆ˜๋„ค ์ปค๋ฎค๋‹ˆํ‹ฐ'

  • ๐Ÿฃ ์˜์ฒ  ( ์‹ ์ž… ): "์˜ํ˜ธ ๋‹˜, ์ € React Portal์ด๋ž‘ useRef, useEffect ์กฐํ•ฉ์œผ๋กœ ๋ชจ๋‹ฌ ๋งŒ๋“ค์—ˆ๋Š”๋ฐ ์ฝ”๋“œ๊ฐ€ ๋งŽ์ด ๋ณต์žกํ•ด์กŒ์–ด์š”. ์ ‘๊ทผ์„ฑ๋„ ์ง์ ‘ ๊ตฌํ˜„ํ•˜๋ ค๋‹ˆ ํฌ์ปค์Šค ํŠธ๋žฉ์ด๋ž‘ ESC ํ‚ค ์ฒ˜๋ฆฌ๊นŒ์ง€ ํ•ด์•ผ ํ•˜๋”๋ผ๊ณ ์š”. ๋” ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ• ์—†๋‚˜์š”?"
  • ๐Ÿฆ ์˜ํ˜ธ ( ๋ฆฌ๋“œ ): "๋ธŒ๋ผ์šฐ์ € ๋„ค์ดํ‹ฐ๋ธŒ <dialog> ์š”์†Œ๊ฐ€ ํฌ์ปค์Šค ํŠธ๋žฉ, ESC ํ‚ค, backdrop ๋ชจ๋‘ ๊ธฐ๋ณธ ์ œ๊ณตํ•ด์š”. 2024๋…„ ๊ธฐ์ค€ ๋ชจ๋˜ ๋ธŒ๋ผ์šฐ์ € ์ „๋ถ€ ์ง€์›ํ•˜๊ณ ์š”. ์ง์ ‘ ๊ตฌํ˜„ํ•œ ๋ชจ๋‹ฌ๋ณด๋‹ค ํ›จ์”ฌ ์ ์€ ์ฝ”๋“œ๋กœ, ์ ‘๊ทผ์„ฑ๋„ ๋” ์ข‹์•„์š”."

๐ŸชŸ 1. <dialog> โ€” ๋„ค์ดํ‹ฐ๋ธŒ ๋ชจ๋‹ฌ

<!-- HTML ๊ตฌ์กฐ -->
<dialog id="confirm-modal">
  <h2>์ •๋ง ์‚ญ์ œํ•˜์‹œ๊ฒ ์–ด์š”?</h2>
  <p>์‚ญ์ œํ•œ ๊ฒŒ์‹œ๊ธ€์€ ๋ณต๊ตฌํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.</p>
  <div>
    <!-- form method="dialog": dialog ์ž๋™ ๋‹ซํž˜ + returnValue ์„ค์ • -->
    <form method="dialog">
      <button value="cancel">์ทจ์†Œ</button>
      <button value="confirm">์‚ญ์ œ</button>
    </form>
  </div>
</dialog>
 
<button onclick="document.getElementById('confirm-modal').showModal()">
  ๊ฒŒ์‹œ๊ธ€ ์‚ญ์ œ
</button>
const modal = document.getElementById('confirm-modal');
 
// ๋ชจ๋‹ฌ ์—ด๊ธฐ: .showModal() โ†’ ์ „์ฒดํ™”๋ฉด ์˜ค๋ฒ„๋ ˆ์ด + ํฌ์ปค์Šค ํŠธ๋žฉ ์ž๋™ ์ ์šฉ
modal.showModal();
 
// ๋ชจ๋‹ฌ ๋‹ซ๊ธฐ ์ด๋ฒคํŠธ: form method="dialog" ์ œ์ถœ ์‹œ ์ž๋™ ๋ฐœ์ƒ
modal.addEventListener('close', () => {
  if (modal.returnValue === 'confirm') {
    // ์‚ญ์ œ ๋กœ์ง ์‹คํ–‰
  }
});

<dialog> ๊ฐ€ ๊ธฐ๋ณธ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ๋“ค:

  • ํฌ์ปค์Šค ํŠธ๋žฉ: ๋ชจ๋‹ฌ์ด ์—ด๋ฆฌ๋ฉด ํฌ์ปค์Šค๊ฐ€ ๋ชจ๋‹ฌ ์•ˆ์—๋งŒ ๊ฐ‡ํž˜ (Tab ํ‚ค ํฌํ•จ)
  • ESC ํ‚ค: ์ž๋™์œผ๋กœ ๋ชจ๋‹ฌ ๋‹ซํž˜
  • backdrop: ::backdrop CSS ๊ฐ€์ƒ ์š”์†Œ๋กœ ๋ฐฐ๊ฒฝ dimming ๊ฐ€๋Šฅ
  • ARIA: role="dialog", aria-modal="true" ์ž๋™ ์ ์šฉ
/* dialog ๊ธฐ๋ณธ ์Šคํƒ€์ผ๋ง */
dialog {
  border: none;
  border-radius: 12px;
  padding: 2rem;
  max-width: min(90vw, 480px);
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
}
 
/* ๋ฐฐ๊ฒฝ ์˜ค๋ฒ„๋ ˆ์ด */
dialog::backdrop {
  background: rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(4px);
}

โš›๏ธ 2. React์—์„œ <dialog> ํ™œ์šฉ

import { useRef, useEffect } from "react";
 
interface ConfirmDialogProps {
  isOpen: boolean;
  onClose: (confirmed: boolean) => void;
  title: string;
  message: string;
}
 
function ConfirmDialog({ isOpen, onClose, title, message }: ConfirmDialogProps) {
  const dialogRef = useRef<HTMLDialogElement>(null);
 
  useEffect(() => {
    const dialog = dialogRef.current;
    if (!dialog) return;
 
    if (isOpen) {
      // ์ด๋ฏธ ์—ด๋ ค์žˆ์ง€ ์•Š์œผ๋ฉด showModal
      if (!dialog.open) dialog.showModal();
    } else {
      dialog.close();
    }
  }, [isOpen]);
 
  // close ์ด๋ฒคํŠธ: ESC ํ‚ค๋กœ ๋‹ซํž ๋•Œ๋„ ์บ์น˜
  const handleClose = () => {
    onClose(dialogRef.current?.returnValue === "confirm");
  };
 
  return (
    <dialog ref={dialogRef} onClose={handleClose}>
      <h2>{title}</h2>
      <p>{message}</p>
      <form method="dialog">
        <button value="cancel" type="submit">์ทจ์†Œ</button>
        <button value="confirm" type="submit">ํ™•์ธ</button>
      </form>
    </dialog>
  );
}

๐Ÿ“‹ 3. <details> + <summary> โ€” JS ์—†๋Š” ์•„์ฝ”๋””์–ธ

<!-- FAQ ์„น์…˜: JS ์—†์ด ์™„์ „ํ•œ ์•„์ฝ”๋””์–ธ ๊ตฌํ˜„ -->
<section>
  <h2>์ž์ฃผ ๋ฌป๋Š” ์งˆ๋ฌธ</h2>
 
  <details>
    <summary>์˜์ˆ˜๋„ค ์ปค๋ฎค๋‹ˆํ‹ฐ๋Š” ๋ฌด๋ฃŒ์ธ๊ฐ€์š”?</summary>
    <p>๋„ค, ์™„์ „ ๋ฌด๋ฃŒ ์„œ๋น„์Šค์ž…๋‹ˆ๋‹ค. ์Šคํ„ฐ๋”” ๋งค์นญ๋ถ€ํ„ฐ ์ง„ํ–‰๊นŒ์ง€ ๋ชจ๋‘ ๋ฌด๋ฃŒ์˜ˆ์š”.</p>
  </details>
 
  <details>
    <summary>์Šคํ„ฐ๋”” ์ตœ์†Œ ์ธ์›์ด ์žˆ๋‚˜์š”?</summary>
    <p>์ตœ์†Œ 2๋ช…๋ถ€ํ„ฐ ์ตœ๋Œ€ 8๋ช…๊นŒ์ง€ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์–ด์š”.</p>
  </details>
 
  <!-- open ์†์„ฑ: ์ดˆ๊ธฐ ์—ด๋ฆผ ์ƒํƒœ -->
  <details open>
    <summary>์–ด๋–ค ๊ฐœ๋ฐœ ๋ถ„์•ผ๋ฅผ ๊ณต๋ถ€ํ•  ์ˆ˜ ์žˆ๋‚˜์š”?</summary>
    <p>ํ”„๋ก ํŠธ์—”๋“œ, ๋ฐฑ์—”๋“œ, ์•Œ๊ณ ๋ฆฌ์ฆ˜, ๋””์ž์ธ ๋“ฑ ๋‹ค์–‘ํ•œ ๋ถ„์•ผ์˜ ์Šคํ„ฐ๋””๊ฐ€ ์žˆ์–ด์š”.</p>
  </details>
</section>
/* details/summary ์Šคํƒ€์ผ๋ง */
details {
  border: 1px solid #e2e8f0;
  border-radius: 8px;
  margin-bottom: 0.5rem;
}
 
summary {
  padding: 1rem;
  cursor: pointer;
  font-weight: 600;
  list-style: none; /* ๊ธฐ๋ณธ ์‚ผ๊ฐํ˜• ์ œ๊ฑฐ */
  display: flex;
  justify-content: space-between;
  align-items: center;
}
 
summary::after {
  content: "+";
  font-size: 1.5rem;
  transition: transform 0.2s;
}
 
details[open] summary::after {
  transform: rotate(45deg); /* ์—ด๋ฆฌ๋ฉด X ๋ชจ์–‘์œผ๋กœ */
}
 
details > *:not(summary) {
  padding: 0 1rem 1rem;
}

๐Ÿ’ฌ 4. Popover API โ€” ํˆดํŒ/๋“œ๋กญ๋‹ค์šด ๋„ค์ดํ‹ฐ๋ธŒ ๊ตฌํ˜„

<!-- Popover API: ๋ฒ„ํŠผ ํด๋ฆญ์œผ๋กœ ํŒ์˜ค๋ฒ„ ํ† ๊ธ€ -->
<button popovertarget="user-menu">๋‚ด ๊ณ„์ •</button>
 
<div id="user-menu" popover>
  <ul>
    <li><a href="/profile">ํ”„๋กœํ•„ ์ˆ˜์ •</a></li>
    <li><a href="/settings">์„ค์ •</a></li>
    <li><button type="button">๋กœ๊ทธ์•„์›ƒ</button></li>
  </ul>
</div>
/* Popover ์Šคํƒ€์ผ๋ง */
[popover] {
  border: none;
  border-radius: 8px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
  padding: 0.5rem;
  min-width: 200px;
  /* ํŠธ๋žœ์ง€์…˜: Discrete Animation (Chrome 117+) */
}
 
[popover]:popover-open {
  display: block;
}

Popover API๊ฐ€ ๊ธฐ๋ณธ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ๋“ค:

  • popovertarget ๋ฒ„ํŠผ ํด๋ฆญ์œผ๋กœ ์ž๋™ ํ† ๊ธ€
  • Light dismiss: ํŒ์˜ค๋ฒ„ ์™ธ๋ถ€ ํด๋ฆญ ์‹œ ์ž๋™ ๋‹ซํž˜
  • Top Layer: z-index ๊ณ„์ธต ์ƒ๊ด€์—†์ด ํ™”๋ฉด ์ตœ์ƒ๋‹จ์— ํ‘œ์‹œ
  • ESC ํ‚ค ๋‹ซํž˜

๐Ÿ ํ•ต์‹ฌ ํŒจํ„ด ์ด์ •๋ฆฌ

ํ•„์š”ํ•œ UI๋„ค์ดํ‹ฐ๋ธŒ HTMLํŠน์ง•
๋ชจ๋‹ฌ/๋‹ค์ด์–ผ๋กœ๊ทธ<dialog> + .showModal()ํฌ์ปค์Šค ํŠธ๋žฉ, ESC, backdrop ์ž๋™
์•„์ฝ”๋””์–ธ/FAQ<details> + <summary>JS ์—†์ด ์™„์ „ ๋™์ž‘
๋“œ๋กญ๋‹ค์šด ๋ฉ”๋‰ดPopover APILight dismiss, Top Layer
์ง„ํ–‰๋ฅ  ํ‘œ์‹œ<progress value="70" max="100">๋„ค์ดํ‹ฐ๋ธŒ UI
๋ฒ”์œ„ ์„ ํƒ<input type="range">์Šฌ๋ผ์ด๋” UI ์ž๋™
์ƒ‰์ƒ ์„ ํƒ<input type="color">์ปฌ๋Ÿฌ ํ”ผ์ปค UI ์ž๋™


๐Ÿ“ ๋งˆ๋ฌด๋ฆฌ ํ€ด์ฆˆ

Q1. <dialog> ๋ฅผ showModal() ๋กœ ์—ด์—ˆ์„ ๋•Œ ์ž๋™์œผ๋กœ ์ ์šฉ๋˜๋Š” ๊ธฐ๋Šฅ์ด ์•„๋‹Œ ๊ฒƒ์€?

  • A) ESC ํ‚ค๋กœ ๋ชจ๋‹ฌ ๋‹ซ๊ธฐ
  • B) ๋ชจ๋‹ฌ ์™ธ๋ถ€ ํฌ์ปค์Šค ์ฐจ๋‹จ (ํฌ์ปค์Šค ํŠธ๋žฉ)
  • ๊ฐ€) ๋ฐฐ๊ฒฝ dimming ์Šคํƒ€์ผ (::backdrop)
  • ๋ผ) ๋ชจ๋‹ฌ ๋‚ด ์ž…๋ ฅ๊ฐ’ ์ž๋™ ์ €์žฅ

โœ… ์ •๋‹ต: ๋ผ

๐Ÿ’ก ์ƒ์„ธ ํ•ด์„ค:

  • <dialog>.showModal() ์€ ํฌ์ปค์Šค ํŠธ๋žฉ, ESC ํ‚ค ์ฒ˜๋ฆฌ, ::backdrop ๊ฐ€์ƒ ์š”์†Œ ์ž๋™ ์ƒ์„ฑ์„ ์ œ๊ณตํ•ด์š”. ๋‹ค๋งŒ ::backdrop ๋Š” CSS๋กœ ์ง์ ‘ ์Šคํƒ€์ผ๋งํ•ด์•ผ ์ƒ‰์ƒ์ด ๋ณด์—ฌ์š”. ์ž…๋ ฅ๊ฐ’ ์ €์žฅ์€ ๋ณ„๋„ ๋กœ์ง์ด ํ•„์š”ํ•ด์š”.
  • ๐Ÿ“Œ ํ•ต์‹ฌ ๊ธฐ์–ต๋ฒ•: "<dialog>.showModal() = ํฌ์ปค์Šค ํŠธ๋žฉ + ESC + backdrop ์ž๋™, ์Šคํƒ€์ผ์€ CSS๋กœ"

Q2. Popover API์˜ "Light Dismiss" ๋ž€ ๋ฌด์—‡์ธ๊ฐ€?

โœ… ์ •๋‹ต: ํŒ์˜ค๋ฒ„ ์˜์—ญ ๋ฐ”๊นฅ์„ ํด๋ฆญํ•˜๊ฑฐ๋‚˜ ESC ํ‚ค๋ฅผ ๋ˆ„๋ฅด๋ฉด ํŒ์˜ค๋ฒ„๊ฐ€ ์ž๋™์œผ๋กœ ๋‹ซํžˆ๋Š” ๋™์ž‘

๐Ÿ’ก ์ƒ์„ธ ํ•ด์„ค:

  • Light Dismiss๋Š” ๋“œ๋กญ๋‹ค์šด ๋ฉ”๋‰ด, ํˆดํŒ ๋“ฑ์˜ ํ•ต์‹ฌ UX ํŒจํ„ด์ด์—์š”. ์ง์ ‘ ๊ตฌํ˜„ํ•˜๋ฉด document.addEventListener('click') ์ด๋ฒคํŠธ ๋ฒ„๋ธ”๋ง ์ฒ˜๋ฆฌ๊ฐ€ ๋ณต์žกํ•˜์ง€๋งŒ, popover ์†์„ฑ์„ ์“ฐ๋ฉด ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌํ•ด์ค˜์š”.

Q3. ์˜์ฒ ์ด์˜ ํ…Œ์ŠคํŠธ ํƒ€์ž„

์˜์ˆ˜๋„ค ์ปค๋ฎค๋‹ˆํ‹ฐ์— ๊ฐ ๊ธฐ์ˆ  ์Šคํƒ์— ๋Œ€ํ•œ FAQ ์„น์…˜์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•œ๋‹ค.
๋””์ž์ด๋„ˆ๊ฐ€ "๊ฐ ์งˆ๋ฌธ ํด๋ฆญํ•˜๋ฉด ๋‹ต๋ณ€์ด ํŽผ์ณ์ง€๋Š” ์•„์ฝ”๋””์–ธ UI๋กœ ํ•ด์ฃผ์„ธ์š”"๋ผ๊ณ  ์š”์ฒญํ–ˆ๋‹ค.
JavaScript ์—†์ด ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋Š”๊ฐ€?

โœ… ์ •๋‹ต: <details> + <summary> ์กฐํ•ฉ์œผ๋กœ JS ์—†์ด ์™„์ „ํžˆ ๊ตฌํ˜„ ๊ฐ€๋Šฅ

๐Ÿ’ก ์ƒ์„ธ ํ•ด์„ค:

  • <details> ๋Š” open ์†์„ฑ์˜ ์กด์žฌ ์—ฌ๋ถ€๋กœ ์—ด๋ฆผ/๋‹ซํž˜ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•ด์š”. ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ํด๋ฆญ ์ด๋ฒคํŠธ๋ฅผ ๋ฐ›์•„ ์ž๋™์œผ๋กœ ํ† ๊ธ€ํ•ด์ฃผ๋ฏ€๋กœ JS๊ฐ€ ํ•„์š”์—†์–ด์š”. CSS details[open] summary::after ์…€๋ ‰ํ„ฐ๋กœ ์—ด๋ฆผ ์ƒํƒœ ์•„์ด์ฝ˜ ๋ณ€๊ฒฝ๋„ ๊ฐ€๋Šฅํ•ด์š”.
  • ๐Ÿ“Œ ํ•ต์‹ฌ ๊ธฐ์–ต๋ฒ•: "์•„์ฝ”๋””์–ธ/FAQ = <details> + <summary> โ†’ CSS๋งŒ์œผ๋กœ ์™„์„ฑ"

๐Ÿฃ ์˜์ฒ ์ด์˜ ํ‡ด๊ทผ ์ผ๊ธฐ

<dialog> ํ•˜๋‚˜๋กœ ๋‚ด๊ฐ€ useRef, useEffect, Portal, ํฌ์ปค์Šค ํŠธ๋žฉ, ESC ํ‚ค ํ•ธ๋“ค๋Ÿฌ๊นŒ์ง€ ์ง์ ‘ ์งฐ๋˜ 150์ค„์งœ๋ฆฌ ๋ชจ๋‹ฌ์ด 30์ค„๋กœ ์ค„์—ˆ๋‹ค. ์ง„์งœ ๋ง์ด ์•ˆ ๋œ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ๋Š”๋ฐ, ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ด๋ฏธ ์ด ๋ชจ๋“  ๊ฑธ ํ•ด์ฃผ๊ณ  ์žˆ์—ˆ๋˜ ๊ฑฐ๋‹ค.

๐Ÿ’ก "'์ง์ ‘ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค'๋Š” ์ƒ๊ฐ์ด ์˜คํžˆ๋ ค ํ’ˆ์งˆ์„ ๋‚ฎ์ถœ ์ˆ˜ ์žˆ๋‹ค. ๋ธŒ๋ผ์šฐ์ € ๋„ค์ดํ‹ฐ๋ธŒ ๊ธฐ๋Šฅ์„ ๋จผ์ € ํŒŒ์•…ํ•˜๋Š” ๊ฒŒ 5๋…„ ์ฐจ์˜ ์ž์„ธ๋‹ค. dialog, details, popover โ€” ์ด๊ฒƒ๋“ค์ด ์ด๋ฏธ ์™„์„ฑ๋œ ํ•ด๋‹ต์ด๋‹ค."

<details> + <summary> ๋กœ FAQ ๋งŒ๋“ค์—ˆ๋”๋‹ˆ ์˜์ˆ™ ๋””์ž์ด๋„ˆ ๋‹˜์ด "์ด๊ฒŒ CSS ์• ๋‹ˆ๋ฉ”์ด์…˜๊นŒ์ง€ ๋˜๋„ค์š”?" ํ•˜๊ณ  ์‹ ๊ธฐํ•ดํ•˜์…จ๋‹ค. ๋ธŒ๋ผ์šฐ์ € API๋ฅผ ๋” ๊ณต๋ถ€ํ•ด์•ผ๊ฒ ๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค. HTML ์ž์ฒด๊ฐ€ ์ด๋ ‡๊ฒŒ ๊ฐ•๋ ฅํ•œ๋ฐ ์™œ ์—ฌํƒœ๊นŒ์ง€ div๋กœ ๋งŒ๋“ค๊ณ  ์žˆ์—ˆ์ง€.


๐Ÿ”— ๋” ์•Œ์•„๋ณด๊ธฐ