๐ 1๏ธโฃ ์๋งจํฑ ํ๊ทธ ์ฌํ ํ์ฅ
ํ๊ทธ | ์ค๋ช | ๋น์ ๐ | ์ค๋ฌด ํฌ์ธํธ ๐ |
---|---|---|---|
<header> |
๋ฌธ์ or ์น์ ์ ๋จธ๋ฆฟ๋ง (๋ก๊ณ , ๋ด๋น ํฌํจ ๊ฐ๋ฅ) | ๐ ์ง ํ๊ด, ๊ฐํ | ์ ์ฒด๋ฟ ์๋๋ผ ๊ฐ <section> ์์๋ ์ฌ์ฉ ๊ฐ๋ฅ |
<footer> |
๊ผฌ๋ฆฌ๋ง (์ ์๊ถ, ์ฐ๋ฝ์ฒ ๋ฑ) | ๐ก ์ง ๋ท๋ง๋น, ๋ช ํจ | ์ฌ์ดํธ ์ ์ฒด & ๊ฐ๋ณ ์น์ ๋ด์์๋ ์ฌ์ฉ |
<nav> |
๋ด๋น๊ฒ์ด์ ๋งํฌ ๋ชจ์ | ๐ ๊ธธ ์๋ด ํ์งํ | ARIA role=โnavigationโ ๋ณํ ์ถ์ฒ |
<section> |
์ฃผ์ ๋ณ ๊ตฌํ | ๐ ์ฑํฐ ๊ตฌ๋ถ | ๋ฐ๋์ ์ ๋ชฉ(h1~h6) ํฌํจ! |
<article> |
๋ ๋ฆฝ ์ฝํ ์ธ | ๐ฐ ์ ๋ฌธ๊ธฐ์ฌ | RSS๋ก ํผ๊ฐ๋ ์๋ฏธ ์ ์ง |
<aside> |
๋ณด์กฐ ์ ๋ณด (๊ด๊ณ , ๋งํฌ) | ๐ ์ฐธ๊ณ ์๋ฃ, ์ฌ์ด๋๋ฐ | ๊ฒ์์์ง์ ๋ณธ๋ฌธ๊ณผ ๊ตฌ๋ถ |
โ ์ฌํ ์์ + ์ฃผ์
<body>
<header>
<h1>๐ My Website</h1>
<nav> <!-- ๋ด๋น๊ฒ์ด์
-->
<a href="#home">Home</a>
<a href="#about">About</a>
</nav>
</header>
<main>
<section>
<h2>๐ About Us</h2>
<article>
<h3>๐ฐ Company Story</h3>
<p>๋
๋ฆฝ์ ๊ธฐ์ฌ ๋ด์ฉ...</p>
</article>
<aside>
๐ ๊ด๋ จ ๋งํฌ, ๊ด๊ณ ๋ฐฐ๋
</aside>
</section>
</main>
<footer>
<p>ยฉ 2025 My Company</p>
</footer>
</body>
โ ๋ฉด์ ํฌ์ธํธ:
- ์๋งจํฑ ๊ตฌ์กฐ โ SEO & ์คํฌ๋ฆฐ๋ฆฌ๋ ์ ๊ทผ์ฑ ๊ฐํ
- div ๋จ๋ฐ X โ ์๋ฏธ ์๋ ๊ตฌ์ญ์ ๋ฐ๋์ ์๋งจํฑ ํ๊ทธ ์ฌ์ฉ
๐ฆ 2๏ธโฃ Web Storage ์ฌํ
์ ์ฅ์ | ํน์ง | ๋น์ ๐ | ์ค๋ฌด ํฌ์ธํธ ๐ |
---|---|---|---|
localStorage |
๋ธ๋ผ์ฐ์ ์ ์๊ตฌ ์ ์ฅ (ํญ/๋ธ๋ผ์ฐ์ ์ข ๋ฃํด๋ ์ ์ง) | ๐ฆ ์ฅ๊ธฐ ๋ณด๊ด ์ฐฝ๊ณ | ์ต๋ 5~10MB, ๋ฏผ๊ฐ ์ ๋ณด ์ ์ฅ ๊ธ์ง |
sessionStorage |
ํญ ๋ซํ๋ฉด ์ญ์ ๋จ | ๐ ์์ ์ฅ๋ฐ๊ตฌ๋ | ๋ก๊ทธ์ธ ์ธ์ , ์์ ๋ฐ์ดํฐ |
์ฟ ํค | ์๋ฒ์ ๋งค ์์ฒญ ํจ๊ป ์ ์ก (4KB ์ ํ) | ๐ช ํญ์ ๋ค๊ณ ๋ค๋๋ ๋ฉ๋ชจ์ฅ | ์ธ์ ๊ด๋ฆฌ, ์๋ฒ ์ธ์ฆ |
โ ์ค์ ์์ + ์ฃผ์
// localStorage - ์๊ตฌ ๋ฐ์ดํฐ ์ ์ฅ
localStorage.setItem('theme', 'dark'); // ์ ์ฅ
console.log(localStorage.getItem('theme')); // ์ฝ๊ธฐ
// sessionStorage - ํญ ๋ซ์ผ๋ฉด ์ญ์
sessionStorage.setItem('user', 'ํ๊ธธ๋');
// ์ฟ ํค ์์
document.cookie = "username=hong; path=/; max-age=86400"; // ํ๋ฃจ ๋์ ์ ์ง
โ ๋ณด์ ํฌ์ธํธ:
- local/sessionStorage โ XSS ๊ณต๊ฒฉ ์ ๋ฐ์ดํฐ ํ์ทจ ์ํ ์์
- ๋ฏผ๊ฐ ์ ๋ณด๋ ์๋ฒ or HTTP-only ์ฟ ํค ์ฌ์ฉ!
๐ต 3๏ธโฃ ์ค๋์ค & ๋น๋์ค ์ฌํ
ํ๊ทธ | ์ค๋ช | ๋น์ ๐ | ์ค๋ฌด ํฌ์ธํธ ๐ |
---|---|---|---|
<audio> , <video> |
๋ฉํฐ๋ฏธ๋์ด ์ฝ์ | ๐ต, ๐ฅ ๋ฏธ๋์ด ํ๋ ์ด์ด | controls ํ์, autoplay+muted ์ฃผ์ |
controls |
์ฌ์, ์ ์ง, ๋ณผ๋ฅจ ๋ฑ ์กฐ์ ๋ฒํผ ํ์ | ๐ฎ ๋ฆฌ๋ชจ์ปจ | UX ํฅ์ |
autoplay , loop |
์๋ ์ฌ์, ๋ฐ๋ณต ์ฌ์ | ๐ ์๋ ํ๋ ์ด | SEO/์ ๊ทผ์ฑ ๊ณ ๋ คํด ์ฌ์ฉ |
โ ์ฌํ ์์ + ์ฃผ์
<video width="320" controls autoplay muted loop poster="thumbnail.jpg">
<source src="video.mp4" type="video/mp4">
๋ธ๋ผ์ฐ์ ๊ฐ ๋น๋์ค๋ฅผ ์ง์ํ์ง ์์์!
</video>
๐ ํฌ์ธํธ:
- poster โ ๋น๋์ค ์ธ๋ค์ผ ์ ๊ณต
- muted ์์ผ๋ฉด autoplay ๋๋ถ๋ถ ๋นํ์ฑ (UX ์ฃผ์)
๐ 4๏ธโฃ HTML5 ํผ ๊ณ ๊ธ ๊ธฐ๋ฅ ์ฌํ
์์ฑ | ์ค๋ช | ๋น์ ๐ | ์ค๋ฌด ํฌ์ธํธ ๐ |
---|---|---|---|
input[type="email"] |
์ด๋ฉ์ผ ํ์ ์๋ ๊ฒ์ฆ | ๐ง ์ด๋ฉ์ผ ํํฐ | pattern ์์ฑ์ผ๋ก ์ถ๊ฐ ๊ฒ์ฆ ๊ฐ๋ฅ |
input[type="date"] |
๋ฌ๋ ฅ ํ์ | ๐ ๋ ์ง ์ ํ๊ธฐ | ๋ชจ๋ฐ์ผ์์ UX ๊ฐ์ |
input[type="range"] |
์ฌ๋ผ์ด๋๋ก ์ซ์ ์ ํ | ๐๏ธ ๋ณผ๋ฅจ ์กฐ์ | ์ค์๊ฐ ์๊ฐ ํผ๋๋ฐฑ ์ ๊ณต |
โ ์์ + ์ฃผ์
<form>
<input type="email" placeholder="์ด๋ฉ์ผ ์
๋ ฅ" required>
<input type="date">
<input type="range" min="1" max="100" value="50">
<button>์ ์ถ</button>
</form>
๐ ์ค๋ฌด ํ:
- ๊ธฐ๋ณธ ๊ฒ์ฆ + JS ์ถ๊ฐ ๊ฒ์ฆ ๋ณํ
- aria- ์์ฑ ํ์ฉ โ ์ ๊ทผ์ฑโ
โ๏ธ 5๏ธโฃ ์น ํฐํธ ์ฌํ
๊ฐ๋ | ์ค๋ช | ๋น์ ๐ | ์ค๋ฌด ํฌ์ธํธ ๐ |
---|---|---|---|
@font-face |
์ธ๋ถ ํฐํธ ๋ถ๋ฌ์ ์ปค์คํ | โ๏ธ ๊ธ์จ์ฒด ๊ฐ์ ธ์ค๊ธฐ | woff2 ํฌ๋งท ๊ถ์ฅ, ์ต์ ํฌ๊ธฐ ์ ์ง |
Google Fonts | ๋ฌด๋ฃ ํฐํธ CDN | ๐ ํฐํธ ๋์๊ด | font-display: swap ์ ์ฉ ํ์ |
โ ์์ + ์ฃผ์
@font-face {
font-family: 'CustomFont';
src: url('font.woff2') format('woff2');
font-display: swap; /* ํฐํธ ๋ก๋ฉ ์ ๊ธฐ๋ณธ ํฐํธ ๋จผ์ ๋ณด์ฌ์ค */
}
body {
font-family: 'CustomFont', sans-serif;
}
๐ 6๏ธโฃ SVG & Canvas ์ฌํ
๊ฐ๋ | ํน์ง | ๋น์ ๐ | ์ค๋ฌด ํฌ์ธํธ ๐ |
---|---|---|---|
<svg> |
๋ฒกํฐ ๊ทธ๋ํฝ, ํ๋ํด๋ ๊นจ์ง X | ๐ ๋๋ฉด ๊ทธ๋ฆฌ๊ธฐ | DOM ์ ๊ทผ ๊ฐ๋ฅ, ๊ฐ๋จํ UI ์์ด์ฝ |
<canvas> |
๋นํธ๋งต ๊ทธ๋ํฝ, ๋น ๋ฅธ ์ค์๊ฐ ๋ ๋๋ง | ๐ฎ ๊ทธ๋ฆผํ, ๊ฒ์ | ๊ณ ์ฑ๋ฅ ๊ฒ์, ์ค์๊ฐ ๋ฐ์ดํฐ ์๊ฐํ |
โ ์ฌํ ์์ + ์ฃผ์
<!-- ๐ SVG ์์ : ๋ฒกํฐ ๊ทธ๋ํฝ (ํ๋ํด๋ ๊นจ์ง์ง ์์) -->
<svg width="100" height="100"> <!-- SVG ์บ๋ฒ์ค ํฌ๊ธฐ: 100x100 -->
<!-- ์(circle) ์์
cx, cy โ ์์ ์ค์ฌ ์ขํ
r โ ๋ฐ์ง๋ฆ
stroke โ ํ
๋๋ฆฌ ์
fill โ ๋ด๋ถ ์ -->
<circle cx="50" cy="50" r="40" stroke="blue" fill="lightblue" />
</svg>
<!-- ๐ฎ Canvas ์์ : ๋นํธ๋งต ๊ทธ๋ํฝ (ํฝ์
๊ธฐ๋ฐ, ์ค์๊ฐ ๋ ๋๋ง์ ๊ฐ์ ) -->
<canvas id="myCanvas" width="200" height="100"></canvas>
<script>
// 1๏ธโฃ canvas ์์ ๊ฐ์ ธ์ค๊ธฐ
const ctx = document.getElementById('myCanvas').getContext('2d');
// 2๏ธโฃ ์ฑ์ฐ๊ธฐ ์์ ์ค์ (fillStyle โ ์ฑ์ธ ์์)
ctx.fillStyle = 'green';
// 3๏ธโฃ ์ฌ๊ฐํ ๊ทธ๋ฆฌ๊ธฐ: (x์ขํ, y์ขํ, ๋๋น, ๋์ด)
ctx.fillRect(10, 10, 150, 80); // ์ข์๋จ (10,10)๋ถํฐ 150x80 ํฌ๊ธฐ์ ๋
น์ ์ฌ๊ฐํ
</script>
๐ ํฌ์ธํธ:
- SVG: ์์ด์ฝ, ์ฐจํธ, UI ์์ โ DOM ์กฐ์ ๊ฐ๋ฅ
- Canvas: ๊ฒ์, ๊ทธ๋ํ โ ํฝ์ ๊ธฐ๋ฐ, ๋น ๋ฆ
๐ ๊ธฐ์ ๋ฉด์ ์์ ์ง๋ฌธ ์ฌํ
์ง๋ฌธ | ์ฌํ ํฌ์ธํธ |
---|---|
localStorage, sessionStorage, ์ฟ ํค ์ฐจ์ด? | ์ ์ฅ ๊ธฐ๊ฐ, ํฌ๊ธฐ ์ ํ, ์๋ฒ ์ ์ก ์ฌ๋ถ |
์๋งจํฑ ํ๊ทธ SEO ์ํฅ? | ๊ฒ์์์ง โ ๊ตฌ์กฐ ๋ช ํ, ์คํฌ๋ฆฐ๋ฆฌ๋ ์ ๊ทผ์ฑ โ |
Canvas vs SVG ์ ํ ๊ธฐ์ค? | SVG: UI, ํ๋ ๊ฐ๋ฅ / Canvas: ์ค์๊ฐ, ๊ณ ์ฑ๋ฅ |
HTML5 form ๊ฒ์ฆ ์ฅ์ ? | ๊ธฐ๋ณธ ๊ฒ์ฆ ์ ๊ณต โ JS ๋ถ๋ด โ, ํ์ง๋ง JS ๋ณํ ํ์ |
์นํฐํธ ์ฑ๋ฅ ์ต์ ํ ๋ฐฉ๋ฒ? | woff2, font-display: swap, preload ์ฌ์ฉ ๊ถ์ฅ |
๐ผ ์ค๋ฌด Best Practice ์ ๋ฆฌ
ํฌ์ธํธ | ์ด์ |
---|---|
์๋งจํฑ ํ๊ทธ ์ ๊ทน ์ฌ์ฉ | SEO & ์ ๊ทผ์ฑ ๊ฐํ |
Web Storage โ ๋น๋ฏผ๊ฐ ๋ฐ์ดํฐ๋ง | ๋ณด์ (XSS) ๊ณ ๋ ค |
๋น๋์ค โ controls ํ์, autoplay ์ฃผ์ | UX/์ ๊ทผ์ฑ โ |
์นํฐํธ โ swap + preload | ๋ ๋๋ง ์ต์ ํ |
SVG vs Canvas ์ํฉ๋ณ ์ ํ | ์ฑ๋ฅ, UI ๋ชฉ์ ์ ๋ง๊ฒ ์ ํ |