Alert

์ด ๊ธ€์€ Claude Code์˜ ๋„์›€์„ ๋ฐ›์•„ ์ž‘์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค

์•Œ์•„๋ณผ ๋‚ด์šฉ

  1. ์›น ํŽ˜์ด์ง€์˜ 3์š”์†Œ โ€” HTML, CSS, JavaScript
  2. HTML โ€” ๊ตฌ์กฐ์™€ ์ฝ˜ํ…์ธ 
  3. CSS โ€” ์Šคํƒ€์ผ๊ณผ ๋ ˆ์ด์•„์›ƒ
  4. JavaScript โ€” ๋™์ž‘๊ณผ ๋กœ์ง
  5. ์…‹์ด ์–ด๋–ป๊ฒŒ ํ•ฉ์ณ์ง€๋Š”๊ฐ€
  6. TypeScript
  7. ํ”„๋ก ํŠธ์—”๋“œ ํ”„๋ ˆ์ž„์›Œํฌ โ€” React, Vue, Next.js

์›น ํŽ˜์ด์ง€์˜ 3์š”์†Œ

  • ์›น ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ดํ•ดํ•˜๋Š” ์–ธ์–ด๋Š” ๋”ฑ ์„ธ ๊ฐ€์ง€ : HTML, CSS, JavaScript
  • ์–ด๋–ค ํ”„๋ ˆ์ž„์›Œํฌ(React, Vue, Next.js)๋ฅผ ์“ฐ๋“  ์ตœ์ข…์ ์œผ๋กœ ๋ธŒ๋ผ์šฐ์ €์— ์ „๋‹ฌ๋˜๋Š” ๊ฒƒ์€ ์ด ์„ธ ๊ฐ€์ง€
์›น์˜ 3์š”์†Œ ๋น„์œ 
HTML  = ๋ผˆ๋Œ€ (๊ตฌ์กฐ)     โ†’ "์ด ํŽ˜์ด์ง€์— ์ œ๋ชฉ, ๋ฌธ๋‹จ, ๋ฒ„ํŠผ, ์ด๋ฏธ์ง€๊ฐ€ ์žˆ๋‹ค"
CSS   = ์˜ท (์Šคํƒ€์ผ)     โ†’ "์ œ๋ชฉ์€ ๋นจ๊ฐ„์ƒ‰, ๋ฒ„ํŠผ์€ ๋‘ฅ๊ธ€๊ฒŒ, ์—ฌ๋ฐฑ์€ ์ด๋งŒํผ"
JS    = ๊ทผ์œก (๋™์ž‘)     โ†’ "๋ฒ„ํŠผ ํด๋ฆญํ•˜๋ฉด ํŒ์—… ๋„์›Œ, ๋ฐ์ดํ„ฐ ๋ถˆ๋Ÿฌ์™€์„œ ํ‘œ์‹œํ•ด"
์—ญํ• HTMLCSSJavaScript
ํ•˜๋Š” ์ผ์ฝ˜ํ…์ธ  ๊ตฌ์กฐ ์ •์˜์‹œ๊ฐ์  ์Šคํƒ€์ผ ์ง€์ •๋™์  ๋™์ž‘/๋กœ์ง ์ฒ˜๋ฆฌ
ํŒŒ์ผ ํ™•์žฅ์ž.html.css.js
์—†์œผ๋ฉด?ํŽ˜์ด์ง€ ์ž์ฒด๊ฐ€ ์—†์Œ๋ชป์ƒ๊ธด ํŽ˜์ด์ง€ (๊ธฐ๋Šฅ์€ ๋™์ž‘)์ •์  ํŽ˜์ด์ง€ (์ƒํ˜ธ์ž‘์šฉ ๋ถˆ๊ฐ€)

HTML (HyperText Markup Language) โ€” ๊ตฌ์กฐ์™€ ์ฝ˜ํ…์ธ 

๊ฐœ๋…
  • ์›น ํŽ˜์ด์ง€์˜ ๊ตฌ์กฐ์™€ ๋‚ด์šฉ์„ ์ •์˜ํ•˜๋Š” ๋งˆํฌ์—… ์–ธ์–ด
  • ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด๊ฐ€ ์•„๋‹˜ โ€” ๋กœ์ง์ด๋‚˜ ๋ฐ˜๋ณต๋ฌธ ์—†์ด โ€œ์ด ํŽ˜์ด์ง€์— ๋ญ๊ฐ€ ์žˆ๋Š”์ง€โ€๋งŒ ์„œ์ˆ 
  • ํƒœ๊ทธ(Tag) ๋กœ ๊ตฌ์„ฑ๋˜๋ฉฐ, ํƒœ๊ทธ๊ฐ€ ์ฝ˜ํ…์ธ ๋ฅผ ๊ฐ์‹ธ๋Š” ํ˜•ํƒœ
๊ธฐ๋ณธ ๊ตฌ์กฐ
HTML ๊ธฐ๋ณธ ๊ตฌ์กฐ
<!DOCTYPE html>               <!-- ์ด ๋ฌธ์„œ๊ฐ€ HTML5 ์ž„์„ ์„ ์–ธ -->
<html lang="ko">              <!-- HTML ๋ฌธ์„œ์˜ ์‹œ์ž‘, ์–ธ์–ด ์ง€์ • -->
 
<head>                         <!-- ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์˜์—ญ (๋ธŒ๋ผ์šฐ์ €์— ๋ณด์ด์ง€ ์•Š์Œ) -->
    <meta charset="UTF-8">    <!-- ๋ฌธ์ž ์ธ์ฝ”๋”ฉ -->
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>๋‚ด ํŽ˜์ด์ง€</title>    <!-- ๋ธŒ๋ผ์šฐ์ € ํƒญ์— ํ‘œ์‹œ๋˜๋Š” ์ œ๋ชฉ -->
    <link rel="stylesheet" href="style.css">  <!-- CSS ํŒŒ์ผ ์—ฐ๊ฒฐ -->
</head>
 
<body>                         <!-- ์‹ค์ œ ํ™”๋ฉด์— ํ‘œ์‹œ๋˜๋Š” ์ฝ˜ํ…์ธ  ์˜์—ญ -->
    <h1>์•ˆ๋…•ํ•˜์„ธ์š”</h1>         <!-- ์ œ๋ชฉ -->
    <p>์ด๊ฒƒ์€ ๋ฌธ๋‹จ์ž…๋‹ˆ๋‹ค.</p>    <!-- ๋ฌธ๋‹จ -->
    <button>ํด๋ฆญ</button>       <!-- ๋ฒ„ํŠผ -->
 
    <script src="app.js"></script>  <!-- JavaScript ํŒŒ์ผ ์—ฐ๊ฒฐ -->
</body>
 
</html>
์ฃผ์š” ํƒœ๊ทธ ์ •๋ฆฌ

๋ฌธ์„œ ๊ตฌ์กฐ ํƒœ๊ทธ

ํƒœ๊ทธ์—ญํ• ์„ค๋ช…
<html>์ตœ์ƒ์œ„ ์ปจํ…Œ์ด๋„ˆHTML ๋ฌธ์„œ ์ „์ฒด๋ฅผ ๊ฐ์Œˆ
<head>๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์ œ๋ชฉ, CSS ์—ฐ๊ฒฐ, ์ธ์ฝ”๋”ฉ ๋“ฑ ๋ธŒ๋ผ์šฐ์ €์— ์•ˆ ๋ณด์ด๋Š” ์ •๋ณด
<body>๋ณธ๋ฌธ ์ฝ˜ํ…์ธ ์‹ค์ œ ํ™”๋ฉด์— ํ‘œ์‹œ๋˜๋Š” ๋ชจ๋“  ๊ฒƒ

์ฝ˜ํ…์ธ  ํƒœ๊ทธ

ํƒœ๊ทธ์—ญํ• ์˜ˆ์‹œ
<h1> ~ <h6>์ œ๋ชฉ (ํฌ๊ธฐ์ˆœ)<h1>๋Œ€์ œ๋ชฉ</h1> <h3>์†Œ์ œ๋ชฉ</h3>
<p>๋ฌธ๋‹จ<p>๋ณธ๋ฌธ ํ…์ŠคํŠธ</p>
<a>๋งํฌ (anchor)<a href="https://...">ํด๋ฆญ</a>
<img>์ด๋ฏธ์ง€<img src="photo.jpg" alt="์„ค๋ช…">
<ul>, <ol>, <li>๋ชฉ๋ก<ul><li>ํ•ญ๋ชฉ1</li><li>ํ•ญ๋ชฉ2</li></ul>
<div>๋ฒ”์šฉ ๋ธ”๋ก ์ปจํ…Œ์ด๋„ˆ๋ ˆ์ด์•„์›ƒ์„ ์žก์„ ๋•Œ ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉ
<span>๋ฒ”์šฉ ์ธ๋ผ์ธ ์ปจํ…Œ์ด๋„ˆํ…์ŠคํŠธ ์ผ๋ถ€์— ์Šคํƒ€์ผ์„ ์ ์šฉํ•  ๋•Œ

ํผ(์ž…๋ ฅ) ํƒœ๊ทธ

ํƒœ๊ทธ์—ญํ• ์˜ˆ์‹œ
<form>์ž…๋ ฅ ํผ ์ปจํ…Œ์ด๋„ˆ<form action="/submit" method="POST">
<input>์ž…๋ ฅ ํ•„๋“œ<input type="text" placeholder="์ด๋ฆ„">
<button>๋ฒ„ํŠผ<button type="submit">์ „์†ก</button>
<select>๋“œ๋กญ๋‹ค์šด<select><option>์˜ต์…˜1</option></select>
<textarea>์—ฌ๋Ÿฌ ์ค„ ์ž…๋ ฅ<textarea rows="5"></textarea>

์‹œ๋งจํ‹ฑ ํƒœ๊ทธ (์˜๋ฏธ๋ฅผ ๊ฐ€์ง„ ํƒœ๊ทธ)

  • <div>๋กœ ๋‹ค ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์˜๋ฏธ๋ฅผ ๋ช…ํ™•ํžˆ ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ
  • ๊ฒ€์ƒ‰ ์—”์ง„ ์ตœ์ ํ™”(SEO)์™€ ์ ‘๊ทผ์„ฑ(Accessibility)์— ์œ ๋ฆฌ
ํƒœ๊ทธ์˜๋ฏธ<div> ๋Œ€์‹  ์“ฐ๋Š” ์ด์œ 
<header>ํŽ˜์ด์ง€/์„น์…˜ ์ƒ๋‹จ๋กœ๊ณ , ๋„ค๋น„๊ฒŒ์ด์…˜ ์˜์—ญ
<nav>๋„ค๋น„๊ฒŒ์ด์…˜๋ฉ”๋‰ด, ๋งํฌ ๋ชจ์Œ
<main>๋ฉ”์ธ ์ฝ˜ํ…์ธ ํŽ˜์ด์ง€์˜ ํ•ต์‹ฌ ๋‚ด์šฉ
<article>๋…๋ฆฝ์ ์ธ ์ฝ˜ํ…์ธ ๋ธ”๋กœ๊ทธ ๊ธ€, ๋‰ด์Šค ๊ธฐ์‚ฌ
<section>์ฃผ์ œ๋ณ„ ๊ตฌํš๊ด€๋ จ ์ฝ˜ํ…์ธ  ๊ทธ๋ฃน
<footer>ํ•˜๋‹จ ์ •๋ณด์ €์ž‘๊ถŒ, ์—ฐ๋ฝ์ฒ˜
<aside>๋ถ€๊ฐ€ ์ •๋ณด์‚ฌ์ด๋“œ๋ฐ”, ๊ด€๋ จ ๋งํฌ
์‹œ๋งจํ‹ฑ ํƒœ๊ทธ ํ™œ์šฉ ์˜ˆ์‹œ
<body>
    <header>
        <nav>
            <a href="/">ํ™ˆ</a>
            <a href="/about">์†Œ๊ฐœ</a>
        </nav>
    </header>
 
    <main>
        <article>
            <h1>๊ธ€ ์ œ๋ชฉ</h1>
            <p>๊ธ€ ๋‚ด์šฉ...</p>
        </article>
 
        <aside>
            <h3>๊ด€๋ จ ๊ธ€</h3>
            <ul><li><a href="/other">๋‹ค๋ฅธ ๊ธ€</a></li></ul>
        </aside>
    </main>
 
    <footer>
        <p>ยฉ 2026 My Blog</p>
    </footer>
</body>
ํƒœ๊ทธ์˜ ์†์„ฑ (Attributes)
  • ํƒœ๊ทธ์— ์ถ”๊ฐ€ ์ •๋ณด๋ฅผ ๋ถ€์—ฌํ•˜๋Š” ์ด๋ฆ„="๊ฐ’" ์Œ
์ž์ฃผ ์“ฐ๋Š” ์†์„ฑ
<!-- id : ํŽ˜์ด์ง€ ๋‚ด์—์„œ ๊ณ ์œ ํ•œ ์‹๋ณ„์ž (ํ•˜๋‚˜๋งŒ ์กด์žฌ) -->
<div id="main-content">...</div>
 
<!-- class : ์—ฌ๋Ÿฌ ์š”์†Œ์— ๋™์ผ ์Šคํƒ€์ผ์„ ์ ์šฉํ•  ๋•Œ (์—ฌ๋Ÿฌ ๊ฐœ ๊ฐ€๋Šฅ) -->
<p class="highlight bold">๊ฐ•์กฐ ํ…์ŠคํŠธ</p>
 
<!-- href : ๋งํฌ ๋Œ€์ƒ URL -->
<a href="https://google.com" target="_blank">์ƒˆ ํƒญ์—์„œ ์—ด๊ธฐ</a>
 
<!-- src : ์™ธ๋ถ€ ๋ฆฌ์†Œ์Šค ๊ฒฝ๋กœ (์ด๋ฏธ์ง€, ์Šคํฌ๋ฆฝํŠธ ๋“ฑ) -->
<img src="photo.jpg" alt="์‚ฌ์ง„ ์„ค๋ช…">
<script src="app.js"></script>
 
<!-- style : ์ธ๋ผ์ธ CSS (๊ฐ€๊ธ‰์  ๋น„์ถ”์ฒœ, CSS ํŒŒ์ผ ์‚ฌ์šฉ ๊ถŒ์žฅ) -->
<p style="color: red;">๋นจ๊ฐ„ ๊ธ€์”จ</p>

CSS (Cascading Style Sheets) โ€” ์Šคํƒ€์ผ๊ณผ ๋ ˆ์ด์•„์›ƒ

๊ฐœ๋…
  • HTML ์š”์†Œ์˜ ์‹œ๊ฐ์  ํ‘œํ˜„์„ ์ •์˜ํ•˜๋Š” ์Šคํƒ€์ผ ์–ธ์–ด
  • ์ƒ‰์ƒ, ํฌ๊ธฐ, ์—ฌ๋ฐฑ, ์œ„์น˜, ์• ๋‹ˆ๋ฉ”์ด์…˜ ๋“ฑ ํ™”๋ฉด์— ๋ณด์ด๋Š” ๋ชจ๋“  ๊ฒƒ์„ ์ œ์–ด
  • โ€œCascadingโ€ : ์—ฌ๋Ÿฌ ์Šคํƒ€์ผ ๊ทœ์น™์ด ๊ฒน์น  ๋•Œ ์šฐ์„ ์ˆœ์œ„์— ๋”ฐ๋ผ ๋‹จ๊ณ„์ ์œผ๋กœ ์ ์šฉ๋œ๋‹ค๋Š” ์˜๋ฏธ
CSS ์ ์šฉ ๋ฐฉ๋ฒ• 3๊ฐ€์ง€
CSS ์ ์šฉ ๋ฐฉ๋ฒ•
<!-- 1. ์™ธ๋ถ€ ํŒŒ์ผ (๊ฐ€์žฅ ๊ถŒ์žฅ) -->
<head>
    <link rel="stylesheet" href="style.css">
</head>
 
<!-- 2. <style> ํƒœ๊ทธ (ํ•ด๋‹น ํŽ˜์ด์ง€์—๋งŒ ์ ์šฉ) -->
<head>
    <style>
        h1 { color: blue; }
    </style>
</head>
 
<!-- 3. ์ธ๋ผ์ธ ์Šคํƒ€์ผ (๋น„์ถ”์ฒœ โ€” ์œ ์ง€๋ณด์ˆ˜ ์–ด๋ ค์›€) -->
<p style="color: red; font-size: 16px;">๋นจ๊ฐ„ ๊ธ€์”จ</p>
CSS ๊ธฐ๋ณธ ๋ฌธ๋ฒ•
CSS ๊ธฐ๋ณธ ๊ตฌ์กฐ
/* ์„ ํƒ์ž { ์†์„ฑ: ๊ฐ’; } */
 
h1 {
    color: #333;              /* ๊ธ€์ž์ƒ‰ */
    font-size: 24px;          /* ๊ธ€์ž ํฌ๊ธฐ */
    font-weight: bold;        /* ๊ธ€์ž ๊ตต๊ธฐ */
    margin-bottom: 16px;      /* ์•„๋ž˜ ๋ฐ”๊นฅ ์—ฌ๋ฐฑ */
}
 
.card {                       /* ํด๋ž˜์Šค ์„ ํƒ์ž (.์œผ๋กœ ์‹œ์ž‘) */
    background-color: #f5f5f5;
    border: 1px solid #ddd;
    border-radius: 8px;       /* ๋ชจ์„œ๋ฆฌ ๋‘ฅ๊ธ€๊ฒŒ */
    padding: 20px;            /* ์•ˆ์ชฝ ์—ฌ๋ฐฑ */
}
 
#header {                     /* ID ์„ ํƒ์ž (#์œผ๋กœ ์‹œ์ž‘) */
    position: fixed;          /* ์Šคํฌ๋กคํ•ด๋„ ๊ณ ์ • */
    top: 0;
    width: 100%;
}
์„ ํƒ์ž (Selector) ์ •๋ฆฌ
์„ ํƒ์ž๋ฌธ๋ฒ•๋Œ€์ƒ์˜ˆ์‹œ
ํƒœ๊ทธํƒœ๊ทธ๋ช…ํ•ด๋‹น ํƒœ๊ทธ ์ „์ฒดp { color: gray; }
ํด๋ž˜์Šค.ํด๋ž˜์Šค๋ช…class ์†์„ฑ์ด ์ผ์น˜ํ•˜๋Š” ์š”์†Œ.card { padding: 20px; }
ID#์•„์ด๋””๋ช…id ์†์„ฑ์ด ์ผ์น˜ํ•˜๋Š” ์š”์†Œ (1๊ฐœ)#header { height: 60px; }
์ž์†A BA ์•ˆ์— ์žˆ๋Š” ๋ชจ๋“  B.card p { font-size: 14px; }
์ง์ ‘ ์ž์‹A > BA ๋ฐ”๋กœ ์•„๋ž˜์˜ B.nav > li { display: inline; }
์—ฌ๋Ÿฌ ์„ ํƒA, BA์™€ B ๋ชจ๋‘h1, h2 { color: blue; }
์ž์ฃผ ์“ฐ๋Š” CSS ์†์„ฑ

ํ…์ŠคํŠธ ๊ด€๋ จ

์†์„ฑ์„ค๋ช…์˜ˆ์‹œ
color๊ธ€์ž์ƒ‰color: #333;
font-size๊ธ€์ž ํฌ๊ธฐfont-size: 16px;
font-weight๊ตต๊ธฐfont-weight: bold;
text-align์ •๋ ฌtext-align: center;
line-height์ค„ ๊ฐ„๊ฒฉline-height: 1.6;

๋ฐ•์Šค ๋ชจ๋ธ (Box Model) โ€” CSS์—์„œ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ฐœ๋…

  • ๋ชจ๋“  HTML ์š”์†Œ๋Š” 4๊ฒน์˜ ์ƒ์ž๋กœ ๊ตฌ์„ฑ๋จ (๋ฐ”๊นฅ โ†’ ์•ˆ์ชฝ ์ˆœ์„œ)
์ธต (๋ฐ”๊นฅ โ†’ ์•ˆ์ชฝ)์†์„ฑ์—ญํ• 
1. marginmargin: 16px;๋ฐ”๊นฅ ์—ฌ๋ฐฑ โ€” ๋‹ค๋ฅธ ์š”์†Œ์™€์˜ ๊ฑฐ๋ฆฌ
2. borderborder: 1px solid #ccc;ํ…Œ๋‘๋ฆฌ โ€” ๋ˆˆ์— ๋ณด์ด๋Š” ๊ฒฝ๊ณ„์„ 
3. paddingpadding: 20px;์•ˆ์ชฝ ์—ฌ๋ฐฑ โ€” ํ…Œ๋‘๋ฆฌ์™€ ์ฝ˜ํ…์ธ  ์‚ฌ์ด ๊ณต๊ฐ„
4. contentwidth: 300px; height: 200px;์‹ค์ œ ์ฝ˜ํ…์ธ ๊ฐ€ ๋“ค์–ด๊ฐ€๋Š” ์˜์—ญ
๋ฐ•์Šค ๋ชจ๋ธ ์†์„ฑ
.box {
    width: 300px;              /* ์ฝ˜ํ…์ธ  ๋„ˆ๋น„ */
    height: 200px;             /* ์ฝ˜ํ…์ธ  ๋†’์ด */
    padding: 20px;             /* ์•ˆ์ชฝ ์—ฌ๋ฐฑ (์ƒํ•˜์ขŒ์šฐ ๋™์ผ) */
    padding: 10px 20px;        /* ์•ˆ์ชฝ ์—ฌ๋ฐฑ (์ƒํ•˜ 10px, ์ขŒ์šฐ 20px) */
    border: 1px solid #ccc;    /* ํ…Œ๋‘๋ฆฌ */
    margin: 16px;              /* ๋ฐ”๊นฅ ์—ฌ๋ฐฑ */
    margin: 0 auto;            /* ์ˆ˜ํ‰ ๊ฐ€์šด๋ฐ ์ •๋ ฌ */
}

๋ ˆ์ด์•„์›ƒ โ€” Flexbox (ํ˜„๋Œ€ CSS์˜ ํ•ต์‹ฌ)

Flexbox ๋ ˆ์ด์•„์›ƒ
/* ๊ฐ€๋กœ ์ •๋ ฌ */
.row {
    display: flex;                     /* ์ž์‹ ์š”์†Œ๋“ค์„ ๊ฐ€๋กœ๋กœ ๋ฐฐ์น˜ */
    justify-content: space-between;    /* ์ขŒ์šฐ๋กœ ๊ท ๋“ฑ ๋ถ„๋ฐฐ */
    align-items: center;               /* ์„ธ๋กœ ๊ฐ€์šด๋ฐ ์ •๋ ฌ */
    gap: 16px;                         /* ์š”์†Œ ์‚ฌ์ด ๊ฐ„๊ฒฉ */
}
 
/* ์„ธ๋กœ ์ •๋ ฌ */
.column {
    display: flex;
    flex-direction: column;            /* ์„ธ๋กœ๋กœ ๋ฐฐ์น˜ */
    gap: 8px;
}
 
/* ์ •๊ฐ€์šด๋ฐ ๋ฐฐ์น˜ (๊ฐ€๋กœ + ์„ธ๋กœ ๋ชจ๋‘ ๊ฐ€์šด๋ฐ) */
.center {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;                     /* ํ™”๋ฉด ์ „์ฒด ๋†’์ด */
}

๋ฐ˜์‘ํ˜• ๋””์ž์ธ โ€” ํ™”๋ฉด ํฌ๊ธฐ์— ๋”ฐ๋ผ ์Šคํƒ€์ผ ๋ณ€๊ฒฝ

๋ฏธ๋””์–ด ์ฟผ๋ฆฌ
/* ๊ธฐ๋ณธ ์Šคํƒ€์ผ (๋ชจ๋ฐ”์ผ) */
.container {
    width: 100%;
    padding: 16px;
}
 
/* ํƒœ๋ธ”๋ฆฟ ์ด์ƒ (768px~) */
@media (min-width: 768px) {
    .container {
        width: 720px;
        margin: 0 auto;
    }
}
 
/* ๋ฐ์Šคํฌํ†ฑ ์ด์ƒ (1024px~) */
@media (min-width: 1024px) {
    .container {
        width: 960px;
    }
}

JavaScript โ€” ๋™์ž‘๊ณผ ๋กœ์ง

๊ฐœ๋…
  • ์›น ํŽ˜์ด์ง€์— ๋™์ ์ธ ๋™์ž‘์„ ๋ถ€์—ฌํ•˜๋Š” ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด
  • HTML์ด โ€œ๋ญ๊ฐ€ ์žˆ๋Š”์ง€โ€, CSS๊ฐ€ โ€œ์–ด๋–ป๊ฒŒ ๋ณด์ด๋Š”์ง€โ€๋ฅผ ์ •์˜ํ–ˆ๋‹ค๋ฉด JavaScript๋Š” โ€œ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€โ€ ๋ฅผ ์ •์˜
  • ์›๋ž˜ ๋ธŒ๋ผ์šฐ์ € ์ „์šฉ์ด์—ˆ์œผ๋‚˜, Node.js๋กœ ์„œ๋ฒ„์—์„œ๋„ ์‹คํ–‰ ๊ฐ€๋Šฅํ•ด์ง
HTML์—์„œ JavaScript๋ฅผ ์—ฐ๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•
JavaScript ์—ฐ๊ฒฐ
<!-- 1. ์™ธ๋ถ€ ํŒŒ์ผ ์—ฐ๊ฒฐ (๊ฐ€์žฅ ๊ถŒ์žฅ) -->
<!-- body ๋งจ ์•„๋ž˜์— ๋‘๋Š” ๊ฒƒ์ด ๊ด€๋ก€ โ€” HTML์ด ๋‹ค ๊ทธ๋ ค์ง„ ํ›„ JS ์‹คํ–‰ -->
<body>
    <h1>์•ˆ๋…•ํ•˜์„ธ์š”</h1>
    <button id="myBtn">ํด๋ฆญ</button>
 
    <script src="app.js"></script>    <!-- ์™ธ๋ถ€ JS ํŒŒ์ผ -->
</body>
 
<!-- 2. <script> ํƒœ๊ทธ ์•ˆ์— ์ง์ ‘ ์ž‘์„ฑ -->
<script>
    console.log("Hello!");
</script>
 
<!-- 3. defer ์†์„ฑ โ€” head์— ๋„ฃ์–ด๋„ HTML ํŒŒ์‹ฑ ํ›„ ์‹คํ–‰ -->
<head>
    <script src="app.js" defer></script>
</head>

script ํƒœ๊ทธ์˜ ์œ„์น˜๊ฐ€ ์ค‘์š”ํ•œ ์ด์œ 

  • ๋ธŒ๋ผ์šฐ์ €๋Š” HTML์„ ์œ„์—์„œ ์•„๋ž˜๋กœ ์ฝ์œผ๋ฉฐ ํ™”๋ฉด์„ ๊ทธ๋ฆผ (ํŒŒ์‹ฑ)
  • <script>๋ฅผ ๋งŒ๋‚˜๋ฉด ํŒŒ์‹ฑ์„ ๋ฉˆ์ถ”๊ณ  JS๋ฅผ ๋‹ค์šด๋กœ๋“œ+์‹คํ–‰
  • ๋”ฐ๋ผ์„œ <head>์— ๋„ฃ์œผ๋ฉด JS ์‹คํ–‰ ์ค‘์— ์•„์ง <body>๊ฐ€ ์—†์–ด์„œ ์š”์†Œ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Œ
  • ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•:
    1. <body> ๋งจ ์•„๋ž˜์— <script> ๋ฐฐ์น˜ (์ „ํ†ต์  ๋ฐฉ๋ฒ•)
    2. <script defer> ์‚ฌ์šฉ (HTML ํŒŒ์‹ฑ ์™„๋ฃŒ ํ›„ ์‹คํ–‰)
    3. <script async> ์‚ฌ์šฉ (๋‹ค์šด๋กœ๋“œ ์™„๋ฃŒ ์ฆ‰์‹œ ์‹คํ–‰, ์ˆœ์„œ ๋ณด์žฅ ์•ˆ๋จ)
JavaScript ๊ธฐ๋ณธ ๋ฌธ๋ฒ•
๋ณ€์ˆ˜์™€ ์ž๋ฃŒํ˜•
// ๋ณ€์ˆ˜ ์„ ์–ธ
const name = "ํ™๊ธธ๋™";      // ์ƒ์ˆ˜ (์žฌํ• ๋‹น ๋ถˆ๊ฐ€) โ€” ๊ธฐ๋ณธ์ ์œผ๋กœ const ์‚ฌ์šฉ
let age = 25;               // ๋ณ€์ˆ˜ (์žฌํ• ๋‹น ๊ฐ€๋Šฅ)
var old = "์“ฐ์ง€ ๋งˆ์„ธ์š”";     // ์˜›๋‚  ๋ฐฉ์‹ (์Šค์ฝ”ํ”„ ๋ฌธ์ œ ์žˆ์Œ, ์‚ฌ์šฉ ๋น„์ถ”์ฒœ)
 
// ์ž๋ฃŒํ˜•
const str = "๋ฌธ์ž์—ด";                  // String
const num = 42;                       // Number (์ •์ˆ˜/์‹ค์ˆ˜ ๊ตฌ๋ถ„ ์—†์Œ)
const bool = true;                    // Boolean
const arr = [1, 2, 3];               // Array (Python์˜ list)
const obj = { name: "ํ™๊ธธ๋™", age: 25 };  // Object (Python์˜ dict)
const nothing = null;                 // ์˜๋„์ ์œผ๋กœ "์—†์Œ"
const notDefined = undefined;         // ์•„์ง ๊ฐ’์ด ํ• ๋‹น๋˜์ง€ ์•Š์Œ
ํ•จ์ˆ˜
// ํ•จ์ˆ˜ ์„ ์–ธ
function greet(name) {
    return `์•ˆ๋…•ํ•˜์„ธ์š”, ${name}๋‹˜!`;     // ํ…œํ”Œ๋ฆฟ ๋ฆฌํ„ฐ๋Ÿด (Python์˜ f-string)
}
 
// ํ™”์‚ดํ‘œ ํ•จ์ˆ˜ (Arrow Function) โ€” ํ˜„๋Œ€ JS์—์„œ ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉ
const greet = (name) => {
    return `์•ˆ๋…•ํ•˜์„ธ์š”, ${name}๋‹˜!`;
};
 
// ํ•œ ์ค„์ด๋ฉด ์ค‘๊ด„ํ˜ธ์™€ return ์ƒ๋žต ๊ฐ€๋Šฅ
const greet = (name) => `์•ˆ๋…•ํ•˜์„ธ์š”, ${name}๋‹˜!`;
 
// Python๊ณผ ๋น„๊ต
// def greet(name):
//     return f"์•ˆ๋…•ํ•˜์„ธ์š”, {name}๋‹˜!"
์กฐ๊ฑด๋ฌธ๊ณผ ๋ฐ˜๋ณต๋ฌธ
// ์กฐ๊ฑด๋ฌธ
if (age >= 20) {
    console.log("์„ฑ์ธ");
} else if (age >= 13) {
    console.log("์ฒญ์†Œ๋…„");
} else {
    console.log("์–ด๋ฆฐ์ด");
}
 
// ์‚ผํ•ญ ์—ฐ์‚ฐ์ž (Python๊ณผ ๋™์ผํ•œ ๊ฐœ๋…)
const status = age >= 20 ? "์„ฑ์ธ" : "๋ฏธ์„ฑ๋…„";
// Python: status = "์„ฑ์ธ" if age >= 20 else "๋ฏธ์„ฑ๋…„"
 
// ๋ฐ˜๋ณต๋ฌธ
for (let i = 0; i < 5; i++) {
    console.log(i);
}
 
// ๋ฐฐ์—ด ์ˆœํšŒ (Python์˜ for item in list)
const fruits = ["์‚ฌ๊ณผ", "๋ฐ”๋‚˜๋‚˜", "ํฌ๋„"];
for (const fruit of fruits) {
    console.log(fruit);
}
 
// ๋ฐฐ์—ด ๋ฉ”์„œ๋“œ (Python์˜ ๋ฆฌ์ŠคํŠธ ์ปดํ”„๋ฆฌํ—จ์…˜๊ณผ ์œ ์‚ฌ)
const doubled = [1, 2, 3].map(x => x * 2);        // [2, 4, 6]
const evens = [1, 2, 3, 4].filter(x => x % 2 === 0);  // [2, 4]
DOM ์กฐ์ž‘ โ€” JavaScript๊ฐ€ HTML์„ ๋™์ ์œผ๋กœ ์ œ์–ดํ•˜๋Š” ๋ฐฉ๋ฒ•
  • DOM (Document Object Model) : ๋ธŒ๋ผ์šฐ์ €๊ฐ€ HTML์„ ์ฝ๊ณ  ๋งŒ๋“œ๋Š” ํŠธ๋ฆฌ ๊ตฌ์กฐ์˜ ๊ฐ์ฒด ๋ชจ๋ธ
  • JavaScript๋Š” DOM์„ ํ†ตํ•ด HTML ์š”์†Œ๋ฅผ ์ฐพ๊ณ , ๋ณ€๊ฒฝํ•˜๊ณ , ์ถ”๊ฐ€/์‚ญ์ œํ•  ์ˆ˜ ์žˆ์Œ
DOM ์กฐ์ž‘ ์˜ˆ์‹œ
<h1 id="title">์›๋ž˜ ์ œ๋ชฉ</h1>
<button id="changeBtn">์ œ๋ชฉ ๋ณ€๊ฒฝ</button>
<ul id="list"></ul>
 
<script>
// ์š”์†Œ ์ฐพ๊ธฐ
const title = document.getElementById("title");
const btn = document.getElementById("changeBtn");
const list = document.getElementById("list");
 
// ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ โ€” ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ๋™์ž‘ ์ •์˜
btn.addEventListener("click", () => {
    // ํ…์ŠคํŠธ ๋ณ€๊ฒฝ
    title.textContent = "๋ณ€๊ฒฝ๋œ ์ œ๋ชฉ!";
 
    // ์Šคํƒ€์ผ ๋ณ€๊ฒฝ
    title.style.color = "blue";
 
    // ์ƒˆ ์š”์†Œ ์ถ”๊ฐ€
    const li = document.createElement("li");
    li.textContent = "์ƒˆ ํ•ญ๋ชฉ ์ถ”๊ฐ€๋จ";
    list.appendChild(li);
});
</script>
๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ โ€” JavaScript์˜ ํ•ต์‹ฌ ํŠน์ง•
  • JavaScript๋Š” ์‹ฑ๊ธ€ ์Šค๋ ˆ๋“œ ์–ธ์–ด์ด์ง€๋งŒ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋กœ ์—ฌ๋Ÿฌ ์ž‘์—…์„ ํšจ์œจ์ ์œผ๋กœ ์ˆ˜ํ–‰
  • ์„œ๋ฒ„์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ฑฐ๋‚˜ ํƒ€์ด๋จธ๋ฅผ ์„ค์ •ํ•  ๋•Œ ์‚ฌ์šฉ
๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ
// 1. ์ฝœ๋ฐฑ (์˜›๋‚  ๋ฐฉ์‹)
setTimeout(() => {
    console.log("2์ดˆ ํ›„ ์‹คํ–‰");
}, 2000);
 
// 2. Promise
fetch("https://api.example.com/data")
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(error => console.error(error));
 
// 3. async/await (ํ˜„๋Œ€ ๋ฐฉ์‹, ๊ฐ€์žฅ ๊ถŒ์žฅ)
// Python์˜ async/await์™€ ๊ฑฐ์˜ ๋™์ผํ•œ ๋ฌธ๋ฒ•
async function fetchData() {
    try {
        const response = await fetch("https://api.example.com/data");
        const data = await response.json();
        console.log(data);
    } catch (error) {
        console.error(error);
    }
}
 
// Python ๋น„๊ต
// async def fetch_data():
//     async with aiohttp.ClientSession() as session:
//         async with session.get("https://api.example.com/data") as resp:
//             data = await resp.json()
//             print(data)
Python vs JavaScript ๋ฌธ๋ฒ• ๋น ๋ฅธ ๋น„๊ต
๊ฐœ๋…PythonJavaScript
์ถœ๋ ฅprint("hello")console.log("hello")
๋ฌธ์ž์—ด ํฌ๋งทf"์ด๋ฆ„: {name}"`์ด๋ฆ„: ${name}`
๋ฆฌ์ŠคํŠธ/๋ฐฐ์—ด[1, 2, 3][1, 2, 3]
๋”•์…”๋„ˆ๋ฆฌ/๊ฐ์ฒด{"key": "value"}{key: "value"}
None/nullNonenull / undefined
ํ•จ์ˆ˜def fn(x):const fn = (x) => {}
ํด๋ž˜์Šคclass Foo:class Foo {}
๋ชจ๋“ˆ ๊ฐ€์ ธ์˜ค๊ธฐimport osimport fs from 'fs'
ํƒ€์ž… ํ™•์ธtype(x)typeof x
๋น„๋™๊ธฐasync def / awaitasync function / await

HTML + CSS + JavaScript๊ฐ€ ํ•ฉ์ณ์ง€๋Š” ๊ตฌ์กฐ

์ „ํ˜•์ ์ธ ํ”„๋กœ์ ํŠธ ํŒŒ์ผ ๊ตฌ์กฐ
์ •์  ์›น์‚ฌ์ดํŠธ ๊ตฌ์กฐ
my-website/
โ”œโ”€โ”€ index.html          # ๋ฉ”์ธ ํŽ˜์ด์ง€ (๊ตฌ์กฐ)
โ”œโ”€โ”€ about.html          # ์†Œ๊ฐœ ํŽ˜์ด์ง€
โ”œโ”€โ”€ css/
โ”‚   โ””โ”€โ”€ style.css       # ์Šคํƒ€์ผ
โ”œโ”€โ”€ js/
โ”‚   โ””โ”€โ”€ app.js          # ๋™์ž‘/๋กœ์ง
โ””โ”€โ”€ images/
    โ””โ”€โ”€ logo.png        # ์ด๋ฏธ์ง€ ๋ฆฌ์†Œ์Šค
ํ•˜๋‚˜์˜ ์™„์„ฑ๋œ ์˜ˆ์‹œ
index.html
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ํ•  ์ผ ๋ชฉ๋ก</title>
    <link rel="stylesheet" href="css/style.css">
</head>
<body>
    <div class="container">
        <h1>ํ•  ์ผ ๋ชฉ๋ก</h1>
        <div class="input-area">
            <input type="text" id="todoInput" placeholder="ํ•  ์ผ์„ ์ž…๋ ฅํ•˜์„ธ์š”">
            <button id="addBtn">์ถ”๊ฐ€</button>
        </div>
        <ul id="todoList"></ul>
    </div>
 
    <script src="js/app.js"></script>
</body>
</html>
css/style.css
.container {
    max-width: 500px;
    margin: 40px auto;
    padding: 20px;
    font-family: sans-serif;
}
 
.input-area {
    display: flex;
    gap: 8px;
    margin-bottom: 20px;
}
 
.input-area input {
    flex: 1;                    /* ๋‚จ์€ ๊ณต๊ฐ„ ์ „๋ถ€ ์ฐจ์ง€ */
    padding: 8px 12px;
    border: 1px solid #ccc;
    border-radius: 4px;
}
 
.input-area button {
    padding: 8px 16px;
    background-color: #4CAF50;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
}
 
#todoList li {
    padding: 8px 0;
    border-bottom: 1px solid #eee;
}
js/app.js
const input = document.getElementById("todoInput");
const addBtn = document.getElementById("addBtn");
const todoList = document.getElementById("todoList");
 
addBtn.addEventListener("click", () => {
    const text = input.value.trim();
    if (text === "") return;
 
    const li = document.createElement("li");
    li.textContent = text;
    todoList.appendChild(li);
 
    input.value = "";           // ์ž…๋ ฅ์ฐฝ ๋น„์šฐ๊ธฐ
    input.focus();              // ์ปค์„œ๋ฅผ ๋‹ค์‹œ ์ž…๋ ฅ์ฐฝ์œผ๋กœ
});
 
// Enter ํ‚ค๋กœ๋„ ์ถ”๊ฐ€ ๊ฐ€๋Šฅ
input.addEventListener("keypress", (e) => {
    if (e.key === "Enter") addBtn.click();
});

TypeScript โ€” JavaScript์— ํƒ€์ž…์„ ์ถ”๊ฐ€ํ•œ ์–ธ์–ด

๊ฐœ๋…
  • Microsoft๊ฐ€ ๊ฐœ๋ฐœํ•œ JavaScript์˜ ์ƒ์œ„ ์ง‘ํ•ฉ(Superset)
  • JavaScript ์ฝ”๋“œ์— ์ •์  ํƒ€์ž…์„ ์ถ”๊ฐ€ํ•˜์—ฌ ์ปดํŒŒ์ผ ์‹œ์ ์— ์˜ค๋ฅ˜๋ฅผ ์žก์„ ์ˆ˜ ์žˆ์Œ
  • Python์—์„œ ํƒ€์ž… ํžŒํŠธ(def fn(x: int) -> str)๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๊ณผ ์œ ์‚ฌํ•˜์ง€๋งŒ, TypeScript๋Š” ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ๊ฐ•์ œ๋กœ ๊ฒ€์‚ฌ
  • .ts ํŒŒ์ผ์„ ์ž‘์„ฑํ•˜๋ฉด ์ปดํŒŒ์ผ๋Ÿฌ(tsc)๊ฐ€ .js ํŒŒ์ผ๋กœ ๋ณ€ํ™˜ โ†’ ๋ธŒ๋ผ์šฐ์ €๋Š” JS๋งŒ ์ดํ•ดํ•˜๋ฏ€๋กœ
TypeScript ์˜ˆ์‹œ
// TypeScript โ€” ํƒ€์ž…์ด ์žˆ์Œ
function greet(name: string): string {
    return `์•ˆ๋…•ํ•˜์„ธ์š”, ${name}๋‹˜!`;
}
 
greet("ํ™๊ธธ๋™");    // โœ… OK
greet(123);         // โŒ ์ปดํŒŒ์ผ ์—๋Ÿฌ: number๋Š” string์— ํ• ๋‹นํ•  ์ˆ˜ ์—†์Œ
 
// ์ธํ„ฐํŽ˜์ด์Šค โ€” ๊ฐ์ฒด์˜ ๊ตฌ์กฐ๋ฅผ ์ •์˜
interface User {
    name: string;
    age: number;
    email?: string;    // ?๋Š” ์„ ํƒ์  ํ•„๋“œ (์—†์–ด๋„ ๋จ)
}
 
const user: User = {
    name: "ํ™๊ธธ๋™",
    age: 25
};
TypeScript โ†’ JavaScript ๋ณ€ํ™˜ ํ๋ฆ„
hello.ts  โ†’  tsc (TypeScript ์ปดํŒŒ์ผ๋Ÿฌ)  โ†’  hello.js  โ†’  ๋ธŒ๋ผ์šฐ์ €/Node.js ์‹คํ–‰
             (ํƒ€์ž… ๊ฒ€์‚ฌ + ๋ณ€ํ™˜)              (ํƒ€์ž… ์ •๋ณด ์ œ๊ฑฐ๋œ ์ˆœ์ˆ˜ JS)

ํ”„๋ก ํŠธ์—”๋“œ ํ”„๋ ˆ์ž„์›Œํฌ โ€” React, Vue, Next.js

์™œ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์“ฐ๋Š”๊ฐ€
  • ์œ„์˜ ์ˆœ์ˆ˜ HTML + CSS + JS ๋ฐฉ์‹(Vanilla)์€ ๊ฐ„๋‹จํ•œ ํŽ˜์ด์ง€์—๋Š” ์ถฉ๋ถ„
  • ํ•˜์ง€๋งŒ ๋ณต์žกํ•œ ์›น ์•ฑ(Gmail, Notion, Slack ๋“ฑ)์„ ์ˆœ์ˆ˜ JS๋กœ ๋งŒ๋“ค๋ฉด
    • DOM ์กฐ์ž‘ ์ฝ”๋“œ๊ฐ€ ๋งค์šฐ ๋ณต์žกํ•ด์ง
    • ์ƒํƒœ ๊ด€๋ฆฌ(์–ด๋–ค ๋ฐ์ดํ„ฐ๊ฐ€ ์–ด๋””์— ํ‘œ์‹œ๋˜๋Š”์ง€)๊ฐ€ ์–ด๋ ค์›€
    • ์ฝ”๋“œ ์žฌ์‚ฌ์šฉ๊ณผ ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ํž˜๋“ฆ
  • ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ์ด๋Ÿฐ ๋ฌธ์ œ๋ฅผ ์ปดํฌ๋„ŒํŠธ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ด๊ฒฐ
์ฃผ์š” ํ”„๋ ˆ์ž„์›Œํฌ
ํ”„๋ ˆ์ž„์›Œํฌ๊ฐœ๋ฐœํŠน์ง•๋น„์œ 
ReactMeta (Facebook)UI ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ, ์ปดํฌ๋„ŒํŠธ ๊ธฐ๋ฐ˜, JSX ๋ฌธ๋ฒ•๊ฐ€์žฅ ๋„“์€ ์ƒํƒœ๊ณ„, ์ทจ์—… ์‹œ์žฅ 1์œ„
Vue.jsEvan You (๊ฐœ์ธ)์‰ฌ์šด ํ•™์Šต ๊ณก์„ , ํ…œํ”Œ๋ฆฟ ๊ธฐ๋ฐ˜React๋ณด๋‹ค ๋ฐฐ์šฐ๊ธฐ ์‰ฌ์›€
AngularGoogleํ’€ ํ”„๋ ˆ์ž„์›Œํฌ, TypeScript ๊ธฐ๋ณธ๋Œ€๊ทœ๋ชจ ์—”ํ„ฐํ”„๋ผ์ด์ฆˆ์šฉ
Next.jsVercelReact ๊ธฐ๋ฐ˜, ์„œ๋ฒ„ ์‚ฌ์ด๋“œ ๋ Œ๋”๋ง(SSR)React์˜ โ€œํ’€์Šคํƒ ํ™•์žฅํŒโ€
Nuxt.js์ปค๋ฎค๋‹ˆํ‹ฐVue ๊ธฐ๋ฐ˜, SSR ์ง€์›Vue์˜ โ€œํ’€์Šคํƒ ํ™•์žฅํŒโ€
React ๋ง›๋ณด๊ธฐ โ€” ์ปดํฌ๋„ŒํŠธ๋ž€
React ์ปดํฌ๋„ŒํŠธ ์˜ˆ์‹œ (JSX)
// ์ปดํฌ๋„ŒํŠธ = ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ UI ์กฐ๊ฐ
// HTML์ฒ˜๋Ÿผ ๋ณด์ด์ง€๋งŒ JavaScript ์•ˆ์— ์ž‘์„ฑ (JSX ๋ฌธ๋ฒ•)
function TodoItem({ text, done }) {
    return (
        <li style={{ textDecoration: done ? "line-through" : "none" }}>
            {text}
        </li>
    );
}
 
function TodoList() {
    const todos = [
        { text: "์žฅ๋ณด๊ธฐ", done: false },
        { text: "์šด๋™ํ•˜๊ธฐ", done: true },
    ];
 
    return (
        <ul>
            {todos.map((todo, i) => (
                <TodoItem key={i} text={todo.text} done={todo.done} />
            ))}
        </ul>
    );
}

ํ”„๋ ˆ์ž„์›Œํฌ์™€ pnpm์˜ ๊ด€๊ณ„

  • ํ”„๋ ˆ์ž„์›Œํฌ๋Š” npm/pnpm์„ ํ†ตํ•ด ์„ค์น˜ํ•˜๋Š” ํŒจํ‚ค์ง€
  • ๊ฐœ๋ฐœ ์‹œ์—๋Š” Node.js ํ™˜๊ฒฝ์—์„œ ๋นŒ๋“œํ•˜๊ณ , ๊ฒฐ๊ณผ๋ฌผ์€ ๋ธŒ๋ผ์šฐ์ €์—์„œ ์‹คํ–‰
  • npx create-next-app โ†’ Next.js ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ โ†’ npm run dev โ†’ ๊ฐœ๋ฐœ ์„œ๋ฒ„ ์‹คํ–‰
  • ์ตœ์ข…์ ์œผ๋กœ ๋ธŒ๋ผ์šฐ์ €์— ์ „๋‹ฌ๋˜๋Š” ๊ฒƒ์€ ํ•ญ์ƒ HTML + CSS + JS

์ „์ฒด ํ๋ฆ„ ์š”์•ฝ

๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ดํ•ดํ•˜๋Š” ๊ฒƒ๊ฐœ๋ฐœํ•  ๋•Œ ์“ฐ๋Š” ๊ฒƒ๋นŒ๋“œ/ํŒจํ‚ค์ง€ ๊ด€๋ฆฌ
HTMLReact / Vue / Angularnpm / pnpm / yarn
CSSSass / Tailwind CSSwebpack / vite
JavaScriptTypeScriptNode.js
  • ๊ฐœ๋ฐœํ•  ๋•Œ๋Š” ํ”„๋ ˆ์ž„์›Œํฌ(React ๋“ฑ)์™€ TypeScript๋กœ ์ž‘์„ฑ
  • ๋นŒ๋“œ ๋„๊ตฌ(webpack, vite)๊ฐ€ ์ด๋ฅผ ๋ณ€ํ™˜
  • ์ตœ์ข…์ ์œผ๋กœ ๋ธŒ๋ผ์šฐ์ €์— ์ „๋‹ฌ๋˜๋Š” ๊ฒƒ์€ ํ•ญ์ƒ HTML + CSS + JavaScript