HTML/CSS 시작하기 | 웹 개발 첫걸음

이 글의 핵심

HTML은 문서의 뼈대와 의미를 표시하고 CSS는 그 위에 모양을 규칙으로 덧씌웁니다. 이 시리즈 첫 편은 두 언어의 역할을 구분하는 데서 출발해 index.html과 style.css로 첫 페이지를 완성하고, CSS를 고쳤는데 화면에 반영되지 않을 때 개발자 도구로 규칙이 적용됐는지부터 확인하는 요령까지 초보자 눈높이로 설명합니다.

시리즈 안내

#01 | 📋 전체 목차 | 다음: #02 HTML 기본 태그


들어가며

HTML과 CSS란?

HTML(HyperText Markup Language)은 문서의 뼈대와 의미를 표시하며, CSS(Cascading Style Sheets)는 보이는 모양을 규칙으로 덧씌웁니다.

HTML = 건물의 골조 (구조)
CSS = 인테리어 (디자인)
JavaScript = 전기/수도 (기능)

특징:

  • HTML: 제목, 문단, 이미지, 링크 등 콘텐츠 구조
  • CSS: 색상, 크기, 위치, 애니메이션 등 스타일
  • 브라우저: Chrome, Firefox, Safari 등에서 실행
  • 마크업 언어: HTML은 프로그래밍 언어가 아니라, 태그로 문서 구조·의미를 표시하는 언어입니다

역할을 나누는 이유는 같은 내용을 여러 방식으로 보여 줘야 하기 때문입니다. 한 페이지가 데스크톱 화면, 휴대폰, 인쇄물, 스크린 리더(시각 장애인이 쓰는 음성 낭독 프로그램), 검색 엔진 크롤러에게 동시에 읽힙니다. HTML이 “이것은 제목, 이것은 목록, 이것은 이 페이지의 핵심 내용”이라는 의미를 정확히 표시해 두면, CSS는 화면 크기에 맞게 모양만 바꾸고 스크린 리더와 검색 엔진은 모양과 상관없이 구조를 읽어 갑니다. 반대로 글자를 크게 보이게 하려고 <h1>을 쓰거나, 제목인데 <div>에 큰 글꼴만 주면 화면은 똑같아 보여도 기계가 읽는 구조는 망가집니다. 처음 배울 때 “보이는 모양은 CSS, 무엇인지는 HTML”이라는 기준을 세워 두면 이후의 태그 선택이 훨씬 쉬워집니다.


VS Code 설치와 첫 HTML 파일

VS Code 설치

  1. VS Code 공식 사이트 다운로드
  2. 추천 확장:
    • Live Server: 실시간 미리보기
    • HTML CSS Support: 자동완성
    • Prettier: 코드 포맷팅

첫 HTML 파일 만들기

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>내 첫 웹페이지</title>
</head>
<body>
    <h1>안녕하세요!</h1>
    <p>첫 번째 웹페이지입니다.</p>
</body>
</html>

문서 구조 설명: <!DOCTYPE html>은 HTML5 문서임을 브라우저에 알립니다. lang="ko"는 검색·접근성(스크린 리더)·폰트 렌더링에 힌트를 줍니다. meta charset과 viewport는 각각 문자 깨짐 방지와 모바일 레이아웃의 기준이 됩니다. 실행 방법:

  1. index.html 파일로 저장
  2. 더블클릭하거나 브라우저로 열기
  3. 또는 VS Code에서 Live Server 실행

파일을 더블클릭해서 열면 주소창에 file:///C:/... 같은 경로가 보이고, Live Server로 열면 http://127.0.0.1:5500/처럼 로컬 웹 서버 주소가 보입니다. 이 시리즈의 HTML/CSS 예제는 둘 다 잘 동작하지만, 나중에 JavaScript 모듈(type="module")이나 fetch로 파일을 불러오기 시작하면 file://에서는 브라우저 보안 정책 때문에 CORS 에러가 납니다. 처음부터 Live Server로 여는 습관을 들이면 저장할 때마다 자동으로 새로고침되는 편리함도 얻고, 실제 웹 서버와 같은 조건에서 확인할 수 있습니다.

한글이 안녕 같은 이상한 문자로 깨져 보인다면 두 가지를 확인합니다. <meta charset="UTF-8">이 <head> 맨 앞쪽에 있는지(브라우저는 문서 앞부분에서 인코딩 선언을 찾습니다), 그리고 파일 자체가 UTF-8로 저장되었는지입니다. VS Code는 기본이 UTF-8이지만 메모장이나 오래된 편집기로 저장한 파일은 다른 인코딩일 수 있고, VS Code 오른쪽 아래 상태 표시줄에서 현재 파일 인코딩을 확인할 수 있습니다.


HTML 문서의 기본 구조와 주요 태그

필수 요소

<!DOCTYPE html>          <!-- HTML5 문서 선언 -->
<html lang="ko">         <!-- 언어 설정 -->
<head>
    <!-- 메타데이터 -->
    <meta charset="UTF-8">
    <title>페이지 제목</title>
</head>
<body>
    <!-- 실제 콘텐츠 -->
</body>
</html>

역할 분리: head는 화면에 직접 보이지 않는 설정·메타데이터, body는 사용자가 보는 콘텐츠입니다. 스타일시트 링크(link rel="stylesheet")는 head에 두고, 스크립트는 body 끝에 두거나 head에 두되 defer 속성을 붙여 로딩 순서를 제어합니다.

스타일시트를 head에 두는 이유는 브라우저가 CSS를 모두 받기 전까지 화면 그리기를 미루기 때문입니다. body 끝에 두면 스타일 없는 맨 HTML이 잠깐 보였다가 갑자기 모양이 바뀌는 현상(FOUC)이 생깁니다. 반대로 일반 <script>는 만나는 순간 HTML 해석을 멈추고 실행하므로, head에 그냥 두면 아직 만들어지지 않은 body 요소를 찾다가 null 에러가 나거나 첫 화면 표시가 늦어집니다. <title>에 적은 내용은 브라우저 탭과 검색 결과 제목에 쓰이므로, “내 첫 웹페이지”처럼 페이지마다 다르게 적는 것이 좋습니다. 브라우저는 태그를 빠뜨려도 최대한 알아서 고쳐서 보여 주기 때문에 실수가 화면에 드러나지 않는 경우가 많은데, 그래서 더더욱 기본 구조를 정확히 지키는 습관이 중요합니다.

주요 태그

<!-- 제목 -->
<h1>가장 큰 제목</h1>
<h2>두 번째 제목</h2>
<h3>세 번째 제목</h3>
<!-- 문단 -->
<p>문단 내용입니다.</p>
<!-- 링크 -->
<a href="https://example.com">링크 텍스트</a>
<!-- 이미지 -->
<img src="image.jpg" alt="이미지 설명">
<!-- 목록 -->
<ul>
    <li>항목 1</li>
    <li>항목 2</li>
</ul>
<!-- 구분선 -->
<hr>
<!-- 줄바꿈 -->
<br>

<h1>~<h6>는 글자 크기가 아니라 문서의 목차 수준입니다. 한 페이지에서 <h1>은 보통 하나만 쓰고, <h2> 다음에 <h4>로 건너뛰지 않는 것이 스크린 리더 사용자에게 자연스러운 구조입니다. 크기만 바꾸고 싶다면 CSS로 조절하면 됩니다. <img>의 alt는 이미지를 불러오지 못했을 때와 스크린 리더가 읽을 때 대신 보여 줄 설명이므로 빠뜨리면 안 되고, 장식용 이미지라면 alt=""로 비워 “읽을 필요 없음”을 표시합니다.

<hr>, <br>, <img>처럼 내용을 감싸지 않는 태그는 닫는 태그가 없습니다(<br/>처럼 써도 동작합니다). 초보자가 자주 하는 실수는 문단 사이 간격을 만들려고 <br><br><br>를 여러 번 쓰는 것입니다. 간격은 CSS의 margin으로 조절하는 것이 맞고, <br>은 주소나 시처럼 줄바꿈 자체가 내용의 일부일 때만 씁니다.


CSS를 추가하는 방법과 기본 문법

CSS 추가 방법

방법 1: 인라인 스타일

<p style="color: red; font-size: 20px;">빨간 글씨</p>

방법 2: 내부 스타일

<head>
    <style>
        p {
            color: blue;
            font-size: 18px;
        }
    </style>
</head>

방법 3: 외부 스타일 (권장)

<!-- index.html -->
<head>
    <link rel="stylesheet" href="style.css">
</head>
/* style.css */
p {
    color: green;
    font-size: 16px;
}

세 방법 모두 결과는 같지만 관리 방식이 다릅니다. 인라인 스타일은 그 요소 하나에만 적용되어 같은 스타일을 여러 곳에 쓰려면 매번 반복해야 하고, 나중에 색 하나를 바꾸려면 모든 태그를 찾아 고쳐야 합니다. 내부 스타일은 한 페이지 안에서는 재사용되지만 페이지가 여러 개가 되면 페이지마다 복사해야 합니다. 외부 파일은 여러 페이지가 style.css 하나를 공유하고, 브라우저가 한 번 받은 CSS 파일을 캐시에 저장해 두었다가 다른 페이지에서 재사용하므로 속도 면에서도 유리합니다. 그래서 “외부 스타일 권장”입니다.

외부 파일이 적용되지 않을 때 가장 흔한 원인은 경로입니다. href="style.css"는 HTML 파일과 같은 폴더의 파일을 뜻하므로, CSS를 css/ 폴더에 넣었다면 href="css/style.css"로 바꿔야 합니다. 개발자 도구의 Network 탭에서 style.css 요청이 404로 빨갛게 표시된다면 경로 문제입니다. 또 Windows에서는 Style.css와 style.css를 같은 파일로 취급하지만 실제 웹 서버(대부분 Linux)는 대소문자를 구분하므로, 내 컴퓨터에서는 되는데 배포하면 스타일이 사라지는 일이 생깁니다. 파일 이름은 소문자로 통일하는 것이 안전합니다.

기본 CSS 문법

선택자 {
    속성: 값;
    속성: 값;
}

예제:

/* 태그 선택자 */
h1 {
    color: navy;
    font-size: 32px;
}
/* 클래스 선택자 */
.highlight {
    background-color: yellow;
}
/* ID 선택자 */
#header {
    background-color: #333;
    color: white;
}

태그 선택자 h1은 페이지의 모든 <h1>에, 클래스 선택자 .highlight는 class="highlight"가 붙은 모든 요소에, ID 선택자 #header는 id="header"인 요소 하나에 적용됩니다. 클래스는 한 요소에 class="highlight large"처럼 여러 개를 붙일 수 있고 여러 요소에 재사용할 수 있지만, ID는 페이지 안에서 하나뿐이어야 합니다. 선택자 앞의 점(.)과 샵(#)을 빠뜨리거나, HTML에는 class="high-light"로 쓰고 CSS에는 .highlight로 쓰는 식의 철자 불일치가 “CSS가 안 먹는다”는 문제의 대부분을 차지합니다. 속성 끝의 세미콜론을 빠뜨리면 그 줄과 다음 줄이 함께 무시되는 것도 흔한 실수입니다.

같은 요소에 여러 규칙이 겹치면 CSS는 명시도(specificity) 로 이기는 규칙을 정합니다. 대략 인라인 스타일 > ID 선택자 > 클래스 선택자 > 태그 선택자 순서이고, 명시도가 같으면 나중에 선언된 규칙이 이깁니다. 그래서 #header { color: white; }가 있는 요소에 .title { color: red; }를 추가해도 글자는 여전히 흰색입니다. 이런 충돌을 피하려고 스타일에는 ID보다 클래스를 주로 쓰는 것이 일반적인 관례이며, 명시도는 이 시리즈의 CSS 선택자 편에서 자세히 다룹니다.


index.html과 style.css로 첫 웹페이지 만들기

프로젝트 구조

my-website/
├── index.html
├── style.css
└── 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="style.css">
</head>
<body>
    <!-- 헤더 -->
    <header>
        <h1>홍길동</h1>
        <p>웹 개발자</p>
    </header>
    <!-- 메인 콘텐츠 -->
    <main>
        <section id="about">
            <h2>소개</h2>
            <p>안녕하세요! 웹 개발을 공부하고 있는 홍길동입니다.</p>
        </section>
        <section id="skills">
            <h2>기술</h2>
            <ul>
                <li>HTML</li>
                <li>CSS</li>
                <li>JavaScript</li>
            </ul>
        </section>
        <section id="contact">
            <h2>연락처</h2>
            <p>이메일: [email protected]</p>
        </section>
    </main>
    <!-- 푸터 -->
    <footer>
        <p>&copy; 2026 홍길동. All rights reserved.</p>
    </footer>
</body>
</html>

style.css

/* 전체 스타일 */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}
body {
    font-family: 'Malgun Gothic', sans-serif;
    line-height: 1.6;
    color: #333;
}
/* 헤더 */
header {
    background-color: #2c3e50;
    color: white;
    text-align: center;
    padding: 2rem;
}
header h1 {
    font-size: 2.5rem;
    margin-bottom: 0.5rem;
}
/* 메인 콘텐츠 */
main {
    max-width: 800px;
    margin: 2rem auto;
    padding: 0 1rem;
}
section {
    margin-bottom: 2rem;
}
h2 {
    color: #2c3e50;
    border-bottom: 2px solid #3498db;
    padding-bottom: 0.5rem;
    margin-bottom: 1rem;
}
ul {
    list-style-position: inside;
}
li {
    margin: 0.5rem 0;
}
/* 푸터 */
footer {
    background-color: #34495e;
    color: white;
    text-align: center;
    padding: 1rem;
    margin-top: 2rem;
}

index.html에서 <div> 대신 <header>, <main>, <section>, <footer>를 쓴 것은 앞에서 말한 “의미 표시”의 실제 예입니다. 화면 모양은 <div>로 만들어도 똑같지만, 스크린 리더 사용자는 “본문으로 건너뛰기” 같은 기능으로 <main>에 바로 이동할 수 있고, 검색 엔진도 어디가 핵심 내용인지 알 수 있습니다. <section id="about">의 id는 스타일용이 아니라 <a href="#about">처럼 페이지 안의 특정 위치로 이동하는 링크를 만들 때 쓸 수 있습니다.

CSS 첫 부분의 * { margin: 0; padding: 0; box-sizing: border-box; }는 브라우저마다 조금씩 다른 기본 여백을 없애고 크기 계산 방식을 통일하는 “리셋” 규칙입니다. 편리하지만 <ul>의 들여쓰기와 문단 사이 간격까지 모두 사라지므로, 그래서 아래에서 ul { list-style-position: inside; }와 section { margin-bottom: 2rem; }처럼 필요한 간격을 다시 지정하고 있습니다. box-sizing: border-box는 width에 padding과 border를 포함시켜, width: 300px; padding: 20px;인 상자가 340px이 아닌 300px로 보이게 합니다. 이 차이는 박스 모델 편에서 다시 다룹니다. font-family: 'Malgun Gothic', sans-serif는 Windows에만 있는 맑은 고딕을 지정한 것이라 Mac과 휴대폰에서는 뒤의 sans-serif 기본 글꼴로 바뀝니다. 여러 운영체제를 고려한다면 -apple-system, 'Apple SD Gothic Neo', 'Malgun Gothic', sans-serif처럼 후보를 여러 개 적어 두는 것이 좋습니다. main의 max-width: 800px; margin: 2rem auto;는 넓은 화면에서 본문 폭을 800px로 제한하고 좌우 여백을 자동으로 같게 나눠 가운데 정렬하는, 매우 자주 쓰는 패턴입니다.


명함 페이지와 블로그 글 페이지 만들어 보기

명함 웹페이지

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>명함</title>
    <style>
        body {
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            font-family: Arial, sans-serif;
        }
        .card {
            background: white;
            padding: 2rem;
            border-radius: 10px;
            box-shadow: 0 10px 30px rgba(0,0,0,0.3);
            text-align: center;
            max-width: 400px;
        }
        .card h1 {
            color: #333;
            margin-bottom: 0.5rem;
        }
        .card p {
            color: #666;
            margin: 0.5rem 0;
        }
        .card .email {
            color: #667eea;
            font-weight: bold;
        }
    </style>
</head>
<body>
    <div class="card">
        <h1>홍길동</h1>
        <p>프론트엔드 개발자</p>
        <p class="email">[email protected]</p>
        <p>서울, 대한민국</p>
    </div>
</body>
</html>

명함 예제의 핵심은 body에 준 세 줄입니다. display: flex로 body를 플렉스 컨테이너로 만들고, justify-content: center(가로)와 align-items: center(세로)로 카드를 화면 정중앙에 놓습니다. 여기서 min-height: 100vh가 빠지면 body의 높이가 카드 높이만큼밖에 안 되어 세로 가운데 정렬이 전혀 보이지 않는데, 가운데 정렬이 “안 된다”고 느낄 때 가장 흔한 원인이 이것입니다. 100vh는 화면 높이의 100%이며, 모바일 브라우저에서는 주소창 때문에 실제 보이는 영역보다 조금 커질 수 있어 최신 브라우저에서는 100dvh도 함께 쓰입니다.

linear-gradient(135deg, ...)는 이미지 파일 없이 대각선 그라데이션 배경을 만들고, box-shadow의 rgba(0,0,0,0.3)은 30% 불투명도의 검정 그림자입니다. max-width: 400px는 넓은 화면에서 카드가 너무 커지지 않게 하면서 좁은 화면에서는 알아서 줄어들게 합니다. 이 예제 파일에는 첫 예제에 있던 <meta name="viewport">가 빠져 있는데, 이 줄이 없으면 휴대폰 브라우저가 페이지를 데스크톱 폭(보통 980px)으로 그린 뒤 축소해서 글자가 아주 작게 보입니다. 실제로 만들 때는 모든 페이지에 넣어 두세요.

간단한 블로그 글

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>블로그 글</title>
    <style>
        body {
            max-width: 700px;
            margin: 0 auto;
            padding: 2rem;
            font-family: 'Malgun Gothic', sans-serif;
            line-height: 1.8;
        }
        article {
            background: white;
            padding: 2rem;
            border-radius: 8px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
        }
        h1 {
            color: #2c3e50;
            margin-bottom: 0.5rem;
        }
        .meta {
            color: #7f8c8d;
            font-size: 0.9rem;
            margin-bottom: 1.5rem;
        }
        p {
            margin-bottom: 1rem;
        }
        .highlight {
            background-color: #fff3cd;
            padding: 0.2rem 0.4rem;
            border-radius: 3px;
        }
    </style>
</head>
<body>
    <article>
        <h1>HTML과 CSS 시작하기</h1>
        <div class="meta">2026년 3월 29일 | 홍길동</div>
        
        <p>
            <span class="highlight">HTML</span>과 
            <span class="highlight">CSS</span>는 
            웹 개발의 기초입니다.
        </p>
        
        <p>
            HTML로 구조를 만들고, CSS로 스타일을 입히면 
            멋진 웹페이지를 만들 수 있습니다.
        </p>
        
        <p>
            이 두 기술만 잘 익혀도 정적 웹사이트는 
            충분히 만들 수 있습니다!
        </p>
    </article>
</body>
</html>

블로그 글 예제는 읽기 좋은 본문의 기본값을 보여 줍니다. max-width: 700px은 한 줄이 너무 길어져 다음 줄을 찾기 어려워지는 것을 막고(한국어 기준 한 줄 40~50자 안팎이 읽기 편하다고 알려져 있습니다), line-height: 1.8은 줄 간격을 넉넉히 줍니다. line-height에 단위 없이 숫자만 쓰면 글자 크기에 비례해서 계산되므로, 제목처럼 글자 크기가 다른 요소에도 알맞은 간격이 자동으로 적용됩니다.

<article>은 “독립적으로 떼어 내도 의미가 통하는 콘텐츠”(블로그 글, 뉴스 기사, 댓글 하나)를 감싸는 태그이고, <span class="highlight">는 문장 흐름을 끊지 않고 일부 단어에만 스타일을 입힐 때 씁니다. <span>과 <div>는 둘 다 의미가 없는 범용 태그라는 점은 같지만, <span>은 문장 안에 들어가는 인라인 요소이고 <div>는 새 줄에서 시작하는 블록 요소라는 차이가 있습니다. 날짜를 담은 .meta는 <time datetime="2026-03-29">로 감싸면 기계가 읽을 수 있는 날짜 정보가 되어 조금 더 의미 있는 마크업이 됩니다.


Chrome DevTools로 HTML·CSS 살펴보기

Chrome DevTools

열기: F12 또는 Ctrl+Shift+I (Mac: Cmd+Option+I) 주요 기능:

  • Elements: HTML/CSS 실시간 수정
  • Console: JavaScript 실행
  • Network: 네트워크 요청 확인
  • Sources: 소스 코드 디버깅 활용법:
  1. 요소 검사: 원하는 요소에 우클릭 → “검사”
  2. 스타일 수정: Elements 탭에서 CSS 실시간 변경
  3. 색상 선택: 색상 값 클릭 → 컬러 피커 사용

개발자 도구에서 고친 CSS는 새로고침하면 사라진다는 점을 꼭 기억하세요. 처음에는 DevTools에서 원하는 모양을 찾느라 한참 값을 바꿔 놓고, 그 값을 style.css에 옮기지 않은 채 새로고침해서 작업을 날리는 일이 누구에게나 한 번쯤 생깁니다. 마음에 드는 값을 찾으면 바로 파일에 옮겨 적는 습관을 들이는 것이 좋습니다.

Elements 탭 오른쪽의 Styles 패널은 선택한 요소에 적용된 모든 규칙을 우선순위 순으로 보여 주고, 다른 규칙에 밀려 적용되지 않은 속성에는 취소선을 긋습니다. 속성 이름 옆에 노란 경고 아이콘이 있다면 colr: red처럼 철자가 틀렸거나 값이 잘못된 것입니다. 바로 옆의 Computed 탭은 여러 규칙이 합쳐진 최종 값과 박스 모델(margin, border, padding, 내용 크기)을 그림으로 보여 주므로, “왜 여기에 여백이 생겼지?” 같은 질문의 답을 찾을 때 가장 먼저 열어 볼 곳입니다.


첫 편 요약

핵심 요약

  1. HTML: 웹 페이지 구조 (태그)
  2. CSS: 웹 페이지 디자인 (스타일)
  3. 개발 환경: VS Code + 브라우저
  4. 기본 구조: <!DOCTYPE html> → <html> → <head> + <body>
  5. CSS 추가: 인라인, 내부, 외부 (외부 권장)

다음 단계


관련 글


자주 묻는 질문 (FAQ)

Q. CSS를 고쳤는데 화면에 반영되지 않으면 무엇부터 확인하나요?

A. 먼저 개발자 도구(F12)의 Elements 탭에서 해당 요소를 선택해, 내가 쓴 규칙이 목록에 보이는지와 취소선이 그어져 있는지를 봅니다. 규칙 자체가 없다면 <link>의 파일 경로나 선택자 오타를, 취소선이 있다면 더 우선하는 다른 규칙이 있다는 뜻입니다. 둘 다 아니라면 브라우저 캐시 때문일 수 있으니 강력 새로고침(Ctrl+Shift+R)으로 다시 불러옵니다.