5부 · 화장과 동작: CSS와 JavaScript

← 4부 | 목차 | 다음: 6부 · 브라우저 렌더링 →

지금 다루는 단계: ⑥ 렌더링 — 같은 뼈대(HTML)에 모양(CSS)과 동작(JS)을 입히는 두 동반자.

4부에서 만든 페이지는 뼈대만 있어 투박했습니다. 1부의 집 비유를 다시 꺼내면, 이제 인테리어(CSS)를 하고 전기·배관(JavaScript)을 깔 차례입니다.

1부 · CSS: 모양을 입히다

CSS(Cascading Style Sheets, 캐스케이딩 스타일 시트)는 HTML 요소가 어떻게 보일지를 정합니다. 색, 글꼴, 크기, 여백, 배치 등 '디자인'에 해당하는 모든 것이죠.

CSS의 기본 문법

CSS는 "무엇을(선택자) 어떻게(속성)" 꾸밀지 적는 규칙들의 모음입니다.

CSS
h1 {
  color: navy;
  text-align: center;
}

읽는 법:

  • h1 : 선택자(selector) — "어떤 요소를 꾸밀까?" (여기선 모든 <h1>)
  • { ... } : 그 요소에 적용할 규칙 묶음
  • color: navy; : 속성: 값; — "글자색을 남색으로"
  • text-align: center; : "가운데 정렬로"

규칙 하나는 속성: 값; 형태이고, 세미콜론(;)으로 끝맺습니다.

선택자 세 가지만

선택자무엇을 고르나
p (태그 이름)그 종류의 모든 요소모든 문단
.box (점 + 이름)특정 class를 가진 요소class="box"인 것들
#main (샵 + 이름)특정 id를 가진 요소 하나id="main"인 것

class는 여러 요소에 같은 옷을 입힐 때, id는 페이지에서 딱 하나뿐인 요소를 콕 집을 때 씁니다.

HTML
<p class="highlight">이 문단과</p>
<p class="highlight">이 문단은 같은 스타일</p>
CSS
.highlight {
  background-color: yellow;
}

CSS를 HTML에 연결하는 법

CSS는 보통 <head> 안의 <style> 태그에 적거나, 별도 .css 파일로 분리해 연결합니다. 실습에서는 간단히 <style>을 쓰겠습니다.

박스 모델 한 줄 상식: 모든 요소는 내용 → 안쪽 여백(padding) → 테두리(border) → 바깥 여백(margin)으로 이뤄진 상자입니다. 여백이 헷갈릴 때 이 순서를 떠올리세요.
flowchart TD
    M["margin (바깥 여백) — 다른 요소와의 거리"]:::m
    subgraph M2[" "]
        B["border (테두리)"]:::b
        subgraph B2[" "]
            P["padding (안쪽 여백)"]:::p
            subgraph P2[" "]
                C["content (실제 내용: 글·이미지)"]:::c
            end
        end
    end

    classDef m fill:#fff3b0,stroke:#d4a017,color:#000
    classDef b fill:#cfe8ff,stroke:#2b6cb0,color:#000
    classDef p fill:#c6f6d5,stroke:#276749,color:#000
    classDef c fill:#e9d8fd,stroke:#6b46c1,color:#000

안에서 바깥으로: 내용padding이 감싸고, 그 바깥을 border가 두르고, 다시 margin이 이웃과 거리를 둡니다. 5부 실습에서 paddingmargin을 바꿔 보며 차이를 느껴 보세요.

배치: 요소를 나란히 놓기 (가볍게)

기본적으로 <div><p> 같은 요소는 세로로 쌓입니다(한 줄에 하나씩). 이를 가로로 나란히 배치하고 싶을 때 쓰는 현대적 도구가 Flexbox입니다.

CSS
.row {
  display: flex;      /* 자식들을 가로로 나란히 */
  gap: 10px;          /* 사이 간격 */
  justify-content: center;  /* 가운데로 모으기 */
}

지금은 "한 줄짜리 마법으로 가로 배치가 된다" 정도만 기억하세요. Flexbox와 그 형제인 Grid는 7부에서 더 배울 거리로 안내합니다.

2부 · JavaScript: 살아 움직이게 하다

JavaScript(자바스크립트, 줄여서 JS)는 웹페이지에 동작을 더하는 프로그래밍 언어입니다. HTML·CSS와 달리 JS는 판단하고 계산하고 반응합니다. 버튼 클릭에 반응하고, 내용을 바꾸고, 서버와 추가로 통신하는 일이 모두 JS의 몫입니다.

이름이 'Java'와 비슷하지만 자바(Java)와 자바스크립트는 완전히 다른 언어입니다. 헷갈리지 마세요. (이름은 마케팅 때문에 붙은 역사적 우연입니다.)

가장 단순한 JS

HTML
<button onclick="alert('안녕하세요!')">눌러보세요</button>

버튼을 누르면 alert(경고창)이 "안녕하세요!"를 띄웁니다. onclick은 "클릭하면 이걸 실행해"라는 뜻이죠.

조금 더 제대로: 요소를 찾아 바꾸기

실전에서는 JS가 HTML 요소를 찾아서(select) 내용이나 모양을 바꿉니다.

HTML
<p id="greeting">아직 인사 전</p>
<button onclick="greet()">인사하기</button>

<script>
  function greet() {
    // id가 greeting인 요소를 찾아서
    const el = document.getElementById('greeting');
    // 그 안의 글자를 바꾼다
    el.textContent = '반갑습니다! 버튼이 동작했어요 🎉';
  }
</script>
  • function greet() { ... } : "greet라는 동작을 이렇게 정의한다"
  • document.getElementById('greeting') : 페이지(document)에서 id="greeting"인 요소를 찾아온다
  • .textContent = '...' : 그 요소의 글자를 새 값으로 바꾼다

document는 "지금 이 페이지 전체"를 가리키는 JS의 손잡이입니다. JS는 이 손잡이로 페이지의 어느 요소든 찾아 바꿀 수 있어요. 이 '페이지를 객체로 다루는 통로'를 DOM이라 하는데, 6부에서 정식으로 다룹니다.

JavaScript의 재료 두 가지: 변수와 이벤트

JS를 조금 더 이해하려면 두 개념만 알면 충분합니다.

변수(variable) — 값을 담아 두는 이름표 붙은 상자입니다.

JS
const name = "김초보";      // 바뀌지 않을 값
let count = 0;              // 바뀔 수 있는 값
count = count + 1;         // 이제 count는 1
  • const : 한 번 정하면 바꾸지 않을 값 (상수).
  • let : 나중에 바뀔 수 있는 값.

이벤트(event) — 사용자의 행동(클릭, 입력, 스크롤 등)이 일어나는 '사건'입니다. JS의 핵심은 "어떤 이벤트가 일어나면 → 이 동작을 해라"를 연결하는 것입니다.

JS
const button = document.getElementById('myButton');
button.addEventListener('click', function() {
  alert('버튼이 클릭됐습니다!');
});

addEventListener('click', ...)는 "이 버튼에 클릭 사건이 생기면 이 함수를 실행하라"는 뜻입니다. 앞서 본 onclick보다 이 방식이 더 권장됩니다(HTML과 동작을 분리할 수 있어서요). 웹페이지의 거의 모든 상호작용이 이 "이벤트 → 동작" 짝으로 이루어집니다.

flowchart LR
    E["이벤트 발생<br/>(클릭·입력·스크롤)"]:::user --> H["연결된 함수 실행<br/>(이벤트 핸들러)"]:::model --> R["페이지 변화<br/>(DOM 수정)"]:::good

    classDef user fill:#fff3b0,stroke:#d4a017,color:#000
    classDef model fill:#b2f5ea,stroke:#2c7a7b,color:#000
    classDef good fill:#c6f6d5,stroke:#276749,color:#000

🛠 실습: 소개 페이지에 스타일과 동작 더하기

4부의 index.html을 아래 내용으로 통째로 교체해 저장하고 새로고침하세요. HTML 뼈대는 같고, <style>(CSS)과 <script>(JS)가 추가됐습니다.

HTML
<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <title>나를 소개합니다</title>
  <style>
    body {
      font-family: sans-serif;
      max-width: 600px;
      margin: 40px auto;
      padding: 0 20px;
      color: #333;
      line-height: 1.6;
    }
    h1 {
      color: navy;
      text-align: center;
    }
    img {
      display: block;
      margin: 0 auto;
      border-radius: 50%;   /* 동그란 프로필 */
    }
    .highlight {
      background-color: #fff3b0;
      padding: 2px 6px;
      border-radius: 4px;
    }
    button {
      background-color: navy;
      color: white;
      border: none;
      padding: 10px 20px;
      border-radius: 6px;
      cursor: pointer;
      font-size: 16px;
    }
  </style>
</head>
<body>
  <h1>김초보의 소개 페이지</h1>

  <img src="https://placehold.co/150x150" alt="내 프로필 사진">

  <p>안녕하세요! 저는 웹을 배우는 <span class="highlight">김초보</span>입니다.</p>

  <h2>제가 좋아하는 것</h2>
  <ul>
    <li>커피 ☕</li>
    <li>산책</li>
    <li>새로운 것 배우기</li>
  </ul>

  <p id="greeting">아래 버튼을 눌러보세요.</p>
  <button onclick="greet()">인사하기</button>

  <script>
    function greet() {
      const el = document.getElementById('greeting');
      el.textContent = '반갑습니다! JavaScript가 동작했어요 🎉';
    }
  </script>
</body>
</html>

예상 결과:

  • 글이 가운데로 모이고 읽기 좋은 폭으로 정리됩니다.
  • 프로필 이미지가 동그랗게 바뀝니다.
  • 이름에 노란 형광펜이 칠해집니다.
  • 남색 버튼이 생기고, 누르면 위 문장이 바뀝니다.
세 언어의 역할이 한 화면에 다 모였습니다. HTML은 무엇이 있는지(구조), CSS는 어떻게 보이는지(모양), JavaScript는 무슨 일이 일어나는지(동작). 색·여백을 마음대로 바꿔 보며 어느 줄이 무엇을 담당하는지 확인해 보세요.

🛠 보너스 실습: 입력을 받아 화면에 반영하기

4부에서 폼을 배웠으니, 사용자가 친 이름을 화면에 즉시 띄워 봅시다. </body> 바로 위(버튼 아래)에 다음을 추가하고 새로고침하세요.

HTML
  <h2>방명록</h2>
  <p>
    <input type="text" id="nameInput" placeholder="이름을 입력하세요">
    <button onclick="addGreeting()">인사 남기기</button>
  </p>
  <ul id="guestbook"></ul>

  <script>
    function addGreeting() {
      const input = document.getElementById('nameInput');
      const name = input.value.trim();      // 입력칸의 값 읽기
      if (name === '') {                    // 비었으면 무시
        alert('이름을 입력해 주세요!');
        return;
      }
      const list = document.getElementById('guestbook');
      const item = document.createElement('li');   // 새 <li> 만들기
      item.textContent = name + '님, 환영합니다! 👋';
      list.appendChild(item);               // 목록에 추가
      input.value = '';                     // 입력칸 비우기
    }
  </script>

예상 결과: 입력칸에 이름을 치고 버튼을 누르면, 아래 목록에 "○○님, 환영합니다!"가 한 줄씩 쌓입니다. 빈 칸으로 누르면 경고가 뜨고요.

여기서 새로 등장한 것들을 짚어 보면: input.value(입력칸의 현재 값 읽기), if(조건 판단 — "비었으면"), document.createElement(없던 요소를 새로 만들기), appendChild(만든 요소를 DOM 나무에 붙이기). 5부 첫 예제는 있던 글자를 바꿨고, 이번엔 없던 요소를 새로 만들어 추가했습니다. JS가 DOM 나무를 어떻게 키우는지 보이시나요? (이 '나무'는 6부의 주제입니다.)

세 언어의 분업 정리

flowchart TD
    HTML["HTML<br/>구조 · 내용<br/>(무엇이 있나)"]:::doc
    CSS["CSS<br/>스타일 · 배치<br/>(어떻게 보이나)"]:::render
    JS["JavaScript<br/>동작 · 반응<br/>(무슨 일이 일어나나)"]:::model
    PAGE["완성된<br/>살아있는 페이지"]:::good

    HTML --> PAGE
    CSS --> PAGE
    JS --> PAGE

    classDef doc fill:#e9d8fd,stroke:#6b46c1,color:#000
    classDef render fill:#cfe8ff,stroke:#2b6cb0,color:#000
    classDef model fill:#b2f5ea,stroke:#2c7a7b,color:#000
    classDef good fill:#c6f6d5,stroke:#276749,color:#000

이 부에서 기억할 것

  • CSS선택자 { 속성: 값; } 문법으로 요소의 모양을 정한다. class(여럿)·id(하나)로 대상을 고른다.
  • JavaScript는 페이지에 동작을 더하는 프로그래밍 언어다. document를 통해 요소를 찾아 내용·모양을 바꾼다.
  • JS의 핵심 재료는 변수(값을 담는 상자)와 이벤트("어떤 사건이 일어나면 → 이 동작")다.
  • 자바(Java)와 자바스크립트는 다른 언어다.
  • 실습 프로젝트 2단계 — 정적인 뼈대에 스타일·상호작용·입력 처리를 입혔다.

다음 부에서는 한 걸음 물러나, 브라우저가 이 HTML·CSS·JS를 받아 실제 픽셀로 그려내는 내부 과정을 들여다봅니다.

6부 · 브라우저는 어떻게 화면을 그리나