icon
2장 : HTML 기초와 심화

리스트, 테이블, 폼 요소


앞서 우리는 웹 페이지의 기본 뼈대를 만드는 HTML의 역할과 텍스트, 링크, 이미지를 다루는 방법을 학습했습니다. 이제는 웹 페이지에서 정보를 더욱 구조적이고 체계적으로 표현하거나, 사용자로부터 데이터를 입력받는 데 사용되는 핵심적인 HTML 요소들에 대해 깊이 있게 다룰 차례입니다.

이 장에서는 리스트(목록) 요소를 사용하여 정보를 효과적으로 나열하고, 테이블(표) 요소를 통해 데이터를 행과 열의 형태로 정리하는 방법을 배울 것입니다. 또한, 웹 애플리케이션의 핵심 기능 중 하나인 폼(Form) 요소를 통해 사용자의 입력을 받고 이를 처리하는 기본적인 방법을 알아볼 것입니다. 이 요소들은 웹 페이지의 기능성과 정보 전달력을 높이는 데 매우 중요한 역할을 합니다.


리스트 요소: 정보를 체계적으로 나열하기

2장에서도 간략하게 다루었지만, 리스트 요소는 웹 페이지에서 관련 있는 항목들을 그룹화하여 보여줄 때 매우 유용합니다. 목록은 크게 세 가지 유형으로 나눌 수 있습니다.

순서 없는 목록 (Unordered List)

<ul> 태그는 항목의 순서가 중요하지 않을 때 사용하며, 각 항목은 <li> (list item) 태그로 정의됩니다. 웹 브라우저는 일반적으로 각 <li> 앞에 글머리 기호(•)를 표시합니다. 내비게이션 메뉴, 카테고리 목록, 중요하지 않은 정보 나열 등에 사용됩니다.

<h3>제가 좋아하는 과일들</h3>
<ul>
    <li>사과</li>
    <li>바나나</li>
    <li>딸기</li>
</ul>

순서 있는 목록 (Ordered List)

<ol> 태그는 항목의 순서가 중요할 때 사용하며, 각 항목은 역시 <li> 태그로 정의됩니다. 웹 브라우저는 기본적으로 각 <li> 앞에 숫자를 표시합니다. 레시피의 단계, 순위, 지시 사항 등 순서가 중요한 정보에 적합합니다.

<h3>커피 만드는 법</h3>
<ol>
    <li>원두를 갈아 준비합니다.</li>
    <li>뜨거운 물을 준비합니다.</li>
    <li>천천히 물을 부어 커피를 추출합니다.</li>
    <li>맛있게 드세요!</li>
</ol>
  • type 속성 ( <ol>에 사용): 순서의 종류를 변경할 수 있습니다.

    • type="1" (기본값): 숫자 (1, 2, 3...)
    • type="a": 소문자 알파벳 (a, b, c...)
    • type="A": 대문자 알파벳 (A, B, C...)
    • type="i": 소문자 로마 숫자 (i, ii, iii...)
    • type="I": 대문자 로마 숫자 (I, II, III...)
    <h3>시험 점수 등급</h3>
    <ol type="A">
        <li>A 학점</li>
        <li>B 학점</li>
        <li>C 학점</li>
    </ol>
  • start 속성 ( <ol>에 사용): 목록 시작 번호를 변경할 수 있습니다.

    <h3>재개되는 작업 목록</h3>
    <ol start="5">
        <li>이전 작업 마무리</li>
        <li>새로운 기능 개발 시작</li>
        <li>테스트 및 배포</li>
    </ol>

정의 목록 (Description List)

정의 목록은 용어와 그 용어에 대한 설명을 나열할 때 사용합니다. 용어 사전, 질문과 답변(FAQ) 등에 유용합니다.

  • <dl> (Description List): 정의 목록 전체를 감싸는 태그입니다.
  • <dt> (Definition Term): 정의할 용어를 나타냅니다.
  • <dd> (Definition Description): 용어에 대한 설명을 나타냅니다.
<h3>용어 사전</h3>
<dl>
    <dt>HTML</dt>
    <dd>웹 페이지의 구조를 정의하는 마크업 언어입니다.</dd>

    <dt>CSS</dt>
    <dd>웹 페이지의 스타일과 디자인을 담당하는 스타일 시트 언어입니다.</dd>

    <dt>JavaScript</dt>
    <dd>웹 페이지에 동적인 기능과 상호작용을 부여하는 프로그래밍 언어입니다.</dd>
</dl>

테이블 요소: 데이터를 행과 열로 정리하기

테이블(Table)은 데이터를 행(row)과 열(column)의 형태로 정리하여 보여줄 때 사용합니다. 통계 데이터, 제품 비교, 시간표 등 구조화된 데이터를 표시하는 데 매우 유용합니다. 테이블은 여러 태그들의 조합으로 이루어집니다.

  • <table>: 테이블 전체를 감싸는 태그
  • <caption>: 테이블의 제목이나 설명을 제공 (선택 사항)
  • <thead>: 테이블의 헤더(제목) 행들을 그룹화
  • <tbody>: 테이블의 본문(데이터) 행들을 그룹화
  • <tfoot>: 테이블의 푸터(요약) 행들을 그룹화 (선택 사항)
  • <tr> (Table Row): 테이블의 한 행을 나타냅니다.
  • <th> (Table Header): 테이블 헤더 셀(열의 제목)을 나타냅니다. (기본적으로 굵고 가운데 정렬됨)
  • <td> (Table Data): 테이블 데이터 셀(실제 데이터)을 나타냅니다.
<h3>월별 웹사이트 방문자 수</h3>
<table>
    <caption>2024년 월별 방문자 통계</caption>
    <thead>
        <tr>
            <th></th>
            <th>방문자 수</th>
            <th>신규 방문자</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>1월</td>
            <td>10,500</td>
            <td>3,200</td>
        </tr>
        <tr>
            <td>2월</td>
            <td>12,300</td>
            <td>4,100</td>
        </tr>
        <tr>
            <td>3월</td>
            <td>15,800</td>
            <td>5,500</td>
        </tr>
    </tbody>
    <tfoot>
        <tr>
            <td>총계</td>
            <td>38,600</td>
            <td>12,800</td>
        </tr>
    </tfoot>
</table>
  • 셀 병합 (rowspan, colspan 속성):

    • colspan: 여러 개의 열을 하나의 셀로 병합할 때 사용합니다.
    • rowspan: 여러 개의 행을 하나의 셀로 병합할 때 사용합니다.
    <h3>시간표 (예시)</h3>
    <table>
        <thead>
            <tr>
                <th>시간</th>
                <th>월요일</th>
                <th>화요일</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>9:00 - 10:00</td>
                <td>HTML 기초</td>
                <td rowspan="2">CSS 심화</td> </tr>
            <tr>
                <td>10:00 - 11:00</td>
                <td>JavaScript 기초</td>
            </tr>
            <tr>
                <td colspan="3">점심 시간</td> </tr>
        </tbody>
    </table>

💡 Tip: 테이블은 데이터 표시를 위한 용도로만 사용해야 합니다. 웹 페이지의 레이아웃을 잡기 위해 테이블을 사용하는 것은 권장되지 않습니다. (이는 '테이블 레이아웃'이라고 불리며, 오래된 방식이고 웹 표준과 웹 접근성에 좋지 않습니다. 현대 웹에서는 CSS Flexbox나 Grid를 사용합니다.)


폼 요소: 사용자로부터 입력받기 (<form>)

웹 페이지에서 사용자로부터 정보를 입력받는 것은 매우 중요합니다. 로그인, 회원가입, 검색, 게시글 작성 등 거의 모든 웹 서비스는 사용자로부터의 입력을 필요로 합니다. 이러한 입력 양식을 폼(Form) 이라고 하며, <form> 태그를 사용하여 만듭니다.

<form> 태그 안에는 다양한 종류의 입력 필드(input field)와 컨트롤 요소들이 포함됩니다.

  • <form> 태그의 주요 속성
    • action: 폼 데이터가 제출될 서버의 URL을 지정합니다.
    • method: 폼 데이터를 서버로 전송하는 HTTP 메서드를 지정합니다.
      • GET: URL에 폼 데이터를 쿼리 문자열로 추가하여 전송합니다. (주로 검색이나 간단한 데이터 요청 시 사용)
      • POST: 폼 데이터를 HTTP 요청 본문에 담아 전송합니다. (주로 회원가입, 로그인, 파일 업로드 등 민감하거나 많은 데이터를 전송 시 사용)
<form action="/submit-form" method="POST">
    </form>

입력 필드 (Input Fields): <input>

<input> 태그는 폼에서 가장 많이 사용되는 요소입니다. type 속성을 변경하여 다양한 종류의 입력 필드를 만들 수 있습니다. <input>은 닫는 태그가 없는 빈 태그입니다.

  • type="text": 한 줄 텍스트 입력 필드

    <label for="username">사용자 이름:</label>
    <input type="text" id="username" name="username" placeholder="이름을 입력하세요">
    • id: 각 입력 필드를 고유하게 식별하는 이름 (JavaScript나 <label>과 연결)
    • name: 서버로 전송될 때 이 입력 필드의 데이터를 식별하는 이름 (필수)
    • placeholder: 입력 필드에 아무것도 없을 때 표시되는 힌트 텍스트
    • value: 입력 필드의 초기값
    • required: 필수로 입력해야 하는 필드임을 명시
  • type="password": 비밀번호 입력 필드 (입력 시 문자 대신 • 또는 * 표시)

    <label for="password">비밀번호:</label>
    <input type="password" id="password" name="password" required>
  • type="email": 이메일 주소 입력 필드 (유효성 검사 지원)

    <label for="email">이메일:</label>
    <input type="email" id="email" name="email">
  • type="number": 숫자 입력 필드 (화살표 버튼으로 숫자 증감 가능)

    <label for="quantity">수량:</label>
    <input type="number" id="quantity" name="quantity" min="1" max="10" value="1">
  • type="radio": 여러 옵션 중 하나만 선택할 수 있는 라디오 버튼

    • 같은 name 속성을 가진 라디오 버튼들은 하나의 그룹으로 묶여 하나만 선택 가능합니다.
    <p>성별:</p>
    <input type="radio" id="male" name="gender" value="male">
    <label for="male">남성</label><br>
    <input type="radio" id="female" name="gender" value="female">
    <label for="female">여성</label>
  • type="checkbox": 여러 옵션을 동시에 선택할 수 있는 체크박스

    <p>좋아하는 취미 (다중 선택 가능):</p>
    <input type="checkbox" id="reading" name="hobby" value="reading">
    <label for="reading">독서</label><br>
    <input type="checkbox" id="travel" name="hobby" value="travel">
    <label for="travel">여행</label>
  • type="file": 파일 업로드 필드

    <label for="upload_file">파일 업로드:</label>
    <input type="file" id="upload_file" name="uploaded_file" accept=".pdf,.doc">
    • accept: 업로드 가능한 파일 유형을 제한합니다.
  • type="submit": 폼을 제출하는 버튼

    <input type="submit" value="제출하기">
    • value 속성으로 버튼에 표시될 텍스트를 지정합니다.
  • <label>: 입력 필드의 레이블을 정의합니다. for 속성을 사용하여 해당 레이블이 어떤 input 요소와 연결되는지 id 값으로 명시하는 것이 좋습니다. 이는 웹 접근성을 높여줍니다. (레이블을 클릭하면 해당 입력 필드가 활성화됩니다.)

여러 줄 텍스트 입력: <textarea>

여러 줄의 텍스트를 입력받을 때 사용합니다. rowscols 속성으로 초기 크기를 지정할 수 있습니다.

<label for="message">메시지:</label><br>
<textarea id="message" name="message" rows="5" cols="30" placeholder="메시지를 입력하세요."></textarea>

드롭다운 목록: <select><option>

미리 정의된 여러 옵션 중에서 하나를 선택하도록 할 때 사용합니다.

  • <select>: 드롭다운 목록 전체를 감싸는 태그
  • <option>: 드롭다운 목록의 각 항목을 나타냅니다.
    • value: 서버로 전송될 실제 값
    • selected: 기본적으로 선택되어 있을 옵션에 사용
<label for="country">국가 선택:</label>
<select id="country" name="country">
    <option value="">-- 국가를 선택하세요 --</option>
    <option value="kr">대한민국</option>
    <option value="us" selected>미국</option>
    <option value="jp">일본</option>
</select>

버튼: <button>

클릭할 수 있는 버튼을 만듭니다. <input type="button">과 유사하지만, <button> 태그는 텍스트뿐만 아니라 이미지와 같은 HTML 콘텐츠를 포함할 수 있어 더 유연합니다.

<button type="submit">회원가입</button>
<button type="reset">초기화</button>
<button type="button">클릭 미!</button>
  • type 속성:
    • submit (기본값): 폼을 제출합니다.
    • reset: 폼의 모든 입력 필드를 초기화합니다.
    • button: 일반적인 버튼으로, 주로 자바스크립트와 함께 사용되어 특정 동작을 수행합니다.

폼 요소 그룹화

관련된 폼 요소들을 시각적, 의미적으로 그룹화할 때 사용합니다.

  • <fieldset>: 폼 요소들을 그룹화하는 박스
  • <legend>: <fieldset> 박스의 제목
<fieldset>
    <legend>개인 정보</legend>
    <label for="first_name">이름:</label>
    <input type="text" id="first_name" name="first_name"><br><br>
    <label for="last_name">성:</label>
    <input type="text" id="last_name" name="last_name">
</fieldset>

실습: 간단한 회원가입 폼 만들기

배운 폼 요소들을 조합하여 간단한 회원가입 폼을 만들어 봅시다. web-dev-practice 폴더에 signup.html 파일을 만들고 아래 코드를 작성해 보세요.

signup.html
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>회원가입 페이지</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            background-color: #f2f2f2;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            margin: 0;
        }
        .signup-container {
            background-color: white;
            padding: 30px 40px;
            border-radius: 8px;
            box-shadow: 0 4px 15px rgba(0,0,0,0.1);
            width: 100%;
            max-width: 450px;
        }
        h1 {
            text-align: center;
            color: #333;
            margin-bottom: 30px;
        }
        .form-group {
            margin-bottom: 20px;
        }
        label {
            display: block;
            margin-bottom: 8px;
            color: #555;
            font-weight: bold;
        }
        input[type="text"],
        input[type="email"],
        input[type="password"],
        input[type="number"],
        textarea,
        select {
            width: calc(100% - 20px); /* 패딩 고려 */
            padding: 10px;
            border: 1px solid #ddd;
            border-radius: 5px;
            font-size: 1em;
            box-sizing: border-box; /* 패딩이 너비에 포함되도록 */
        }
        input[type="radio"],
        input[type="checkbox"] {
            margin-right: 8px;
        }
        button[type="submit"] {
            width: 100%;
            padding: 12px;
            background-color: #007bff;
            color: white;
            border: none;
            border-radius: 5px;
            font-size: 1.1em;
            cursor: pointer;
            transition: background-color 0.3s ease;
        }
        button[type="submit"]:hover {
            background-color: #0056b3;
        }
        .radio-group label, .checkbox-group label {
            display: inline-block;
            margin-right: 15px;
            font-weight: normal;
        }
    </style>
</head>
<body>
    <div class="signup-container">
        <h1>회원가입</h1>
        <form action="/register" method="POST">
            <div class="form-group">
                <label for="user_id">아이디:</label>
                <input type="text" id="user_id" name="user_id" placeholder="5~12자 영문/숫자" required minlength="5" maxlength="12">
            </div>

            <div class="form-group">
                <label for="user_email">이메일:</label>
                <input type="email" id="user_email" name="user_email" placeholder="email@example.com" required>
            </div>

            <div class="form-group">
                <label for="user_password">비밀번호:</label>
                <input type="password" id="user_password" name="user_password" placeholder="비밀번호 입력" required minlength="8">
            </div>

            <div class="form-group">
                <label for="password_confirm">비밀번호 확인:</label>
                <input type="password" id="password_confirm" name="password_confirm" placeholder="비밀번호 다시 입력" required>
            </div>

            <div class="form-group radio-group">
                <label>성별:</label>
                <input type="radio" id="gender_male" name="gender" value="male" checked>
                <label for="gender_male">남성</label>
                <input type="radio" id="gender_female" name="gender" value="female">
                <label for="gender_female">여성</label>
                <input type="radio" id="gender_other" name="gender" value="other">
                <label for="gender_other">기타</label>
            </div>

            <div class="form-group">
                <label for="birth_year">출생 연도:</label>
                <select id="birth_year" name="birth_year">
                    <option value="">-- 선택 --</option>
                    <script>
                        const currentYear = new Date().getFullYear();
                        for (let i = currentYear; i >= 1900; i--) {
                            document.write(`<option value="${i}">${i}</option>`);
                        }
                    </script>
                </select>
            </div>

            <div class="form-group">
                <label for="self_intro">자기소개 (선택 사항):</label>
                <textarea id="self_intro" name="self_intro" rows="5" placeholder="간단히 자신을 소개해 주세요."></textarea>
            </div>

            <div class="form-group checkbox-group">
                <input type="checkbox" id="terms_agree" name="terms_agree" required>
                <label for="terms_agree">서비스 이용 약관에 동의합니다.</label>
            </div>

            <button type="submit">회원가입</button>
        </form>
    </div>
</body>
</html>
  • 위 코드에서는 CSS를 <style> 태그 내부에 직접 작성하여 예시의 간결성을 높였습니다. 실제 프로젝트에서는 별도의 .css 파일로 분리하는 것이 유지보수에 더 좋습니다.
  • birth_year <select> 옵션을 자바스크립트로 동적으로 생성하여 <script> 태그의 위치를 확인할 수 있도록 했습니다.

이번 장에서는 웹 페이지의 정보 전달력과 사용자 상호작용을 크게 향상시키는 리스트, 테이블, 그리고 폼 요소들에 대해 자세히 알아보았습니다. 이 요소들을 적절히 활용하면 데이터를 체계적으로 보여주고, 사용자로부터 필요한 정보를 효과적으로 수집할 수 있습니다.