HTML의 콘텐츠 구획 태그

목차

1. 섹션 루트

<head>에 들어가는 요소들을 제외하고 다른 요소들은 모두 섹션 루트 즉 <body>태그 내에 포함된다.

섹션 루트는 문서의 내용 섹션을 나타내며 <body>태그로 나타내고 이 태그는 문서에 하나만 존재 가능하다.

onblur, onerror, onfocus, onload, onresize, onpopstate 등의 이벤트 핸들러를 가질 수 있다. 이들은 문서에서 특정 이벤트가 생겼을 때 실행되는 함수를 지정한다. 더 많은 이벤트 핸들러는 body 태그의 MDN 문서에서 볼 수 있다.

2. 페이지를 구성하는 영역

HTML에는 페이지의 각 구역을 정의할 수 있는 블록 요소들도 있다. 가령 메인 컨텐츠가 위치하는 구역이라든지. 이 요소들을 이용하면 기본적인 페이지 구조를 HTML로 표현할 수 있다.

일반적인 문서는 다음과 같은 영역으로 구성된다.

header : 큰 제목과 로고 등이 있는 띠. 주요 정보가 정리되어 있다. 보통 다른 페이지들에서도 똑같이 나타난다.

nav : 페이지 내에서 다른 페이지로 이동할 수 있는 링크들이 있는 영역. 주로 메뉴, 링크, 탭이 들어가고 다른 페이지들에서도 일관적으로 나타난다. 보통 header 영역에 들어가지만 필수 사항은 아니다.

main : 페이지의 가장 주요 내용이 들어가는 영역. 이야기나 페이지의 중요한 비디오 등이 들어간다.

sidebar : 주변의 정보, 링크, 인용부호 등이 들어가는데 메인 컨텐츠에 따라 내용이 다르다. 기사 페이지라면 sidebar에는 작성자나 관련 기사 링크를 포함할 것이다. 보통 main 영역의 옆에 위치한다.

footer : 페이지 바닥의 줄로 페이지에 관한 작은 정보나 연락처를 적는다. 사이트맵이나 인기 컨텐츠 바로가기 링크가 있을 수도 있다.

이 각각의 페이지 요소들에 대해서 적절한 태그들을 사용해야 한다. 그리고 HTML에서는 정말로 이들에 대한 적절한 태그를 제공한다.

header를 나타내는 header, nav bar를 나타내는 nav, 문서의 주요 컨텐츠에 쓰일 main, article, section, div 등등, sidebar는 aside, footer는 footer를 제공한다.

전체를 이야기하자면, <address>, <article>, <aside>, <footer>, <header>, <h1>, <h2>, <h3>, <h4>, <h5>, <h6>, <main>, <nav>, <section> 태그를 포함한다.

제목 태그들을 묶을 때 사용하는 <hgroup>태그도 있었으나 W3C HTML 명세에서는 제거되었다. 아무튼 이런 태그들을 하나씩 알아보자.

2.1. 태그 구분의 필요성

CSS나 폰트 크기를 통해서 사이트의 각 파트를 구분하고 표시할 수도 있다. 하지만 아예 스크린 리더를 사용하거나 혹은 색을 통해서 구분할 수 없는 정도의 사용자도 많다.

약 8%의 남자와 0.5%의 여자가 색맹(colorblind)이다. 세계의 약 4~5%가 색맹인 것이다. 이는 우리가 그렇게 지원하려고 노력하는 레거시 브라우저 사용자들보다도 많은 수치이지만 많은 경우 색맹 이용자들은 레거시 브라우저 사용자들에 비해 간과된다.

이럴 때 콘텐츠를 기능에 따라 구획할 수 있는 HTML 마크업을 사용하는 것은 사이트 구조를 명백하게 드러내는 데 도움이 된다. 이는 스크린 리더 사용자들이 페이지를 명확히 이용하는 데에도 도움이 된다. 이런 데에 쓰이는 태그들을 알아보자.

3. 콘텐츠 구획 태그

3.1. 간단한 페이지 예시

먼저 간단한 페이지를 한번 구성해 보고, 쓰인 태그들의 의미를 하나하나 짚어보자.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="author" content="Kim Sung Hyun" />
    <title>My Sementic Page</title>
  </head>
  <body>
    <header>
      <h1>My Sementic Page</h1>
    </header>
    <nav>
      <ul>
        <li><a href="#">Home</a></li>
        <li><a href="#">About</a></li>
        <li><a href="#">Contact</a></li>
      </ul>
      <label for="search-input">Search</label>
      <input id="search-input" type="search" placeholder="Search" />
      <input type="submit" value="Search" />
    </nav>
    <main>
      <article>
        <h2>Home</h2>
        <p>Home page 내용</p>
      </article>
      <aside>
        <h2>About</h2>
        <ul>
          <li><a href="#">About 1</a></li>
          <li><a href="#">About 2</a></li>
          <li><a href="#">About 3</a></li>
        </ul>
      </aside>
    </main>
    <footer>
      <p>My Sementic Page</p>
      <p>Contact : <address>[email protected]</address></p>
    </footer>
  </body>
</html>
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="author" content="Kim Sung Hyun" />
    <title>My Sementic Page</title>
  </head>
  <body>
    <header>
      <h1>My Sementic Page</h1>
    </header>
    <nav>
      <ul>
        <li><a href="#">Home</a></li>
        <li><a href="#">About</a></li>
        <li><a href="#">Contact</a></li>
      </ul>
      <label for="search-input">Search</label>
      <input id="search-input" type="search" placeholder="Search" />
      <input type="submit" value="Search" />
    </nav>
    <main>
      <article>
        <h2>Home</h2>
        <p>Home page 내용</p>
      </article>
      <aside>
        <h2>About</h2>
        <ul>
          <li><a href="#">About 1</a></li>
          <li><a href="#">About 2</a></li>
          <li><a href="#">About 3</a></li>
        </ul>
      </aside>
    </main>
    <footer>
      <p>My Sementic Page</p>
      <p>Contact : <address>[email protected]</address></p>
    </footer>
  </body>
</html>
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="author" content="Kim Sung Hyun" />
    <title>My Sementic Page</title>
  </head>
  <body>
    <header>
      <h1>My Sementic Page</h1>
    </header>
    <nav>
      <ul>
        <li><a href="#">Home</a></li>
        <li><a href="#">About</a></li>
        <li><a href="#">Contact</a></li>
      </ul>
      <label for="search-input">Search</label>
      <input id="search-input" type="search" placeholder="Search" />
      <input type="submit" value="Search" />
    </nav>
    <main>
      <article>
        <h2>Home</h2>
        <p>Home page 내용</p>
      </article>
      <aside>
        <h2>About</h2>
        <ul>
          <li><a href="#">About 1</a></li>
          <li><a href="#">About 2</a></li>
          <li><a href="#">About 3</a></li>
        </ul>
      </aside>
    </main>
    <footer>
      <p>My Sementic Page</p>
      <p>Contact : <address>[email protected]</address></p>
    </footer>
  </body>
</html>
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="author" content="Kim Sung Hyun" />
    <title>My Sementic Page</title>
  </head>
  <body>
    <header>
      <h1>My Sementic Page</h1>
    </header>
    <nav>
      <ul>
        <li><a href="#">Home</a></li>
        <li><a href="#">About</a></li>
        <li><a href="#">Contact</a></li>
      </ul>
      <label for="search-input">Search</label>
      <input id="search-input" type="search" placeholder="Search" />
      <input type="submit" value="Search" />
    </nav>
    <main>
      <article>
        <h2>Home</h2>
        <p>Home page 내용</p>
      </article>
      <aside>
        <h2>About</h2>
        <ul>
          <li><a href="#">About 1</a></li>
          <li><a href="#">About 2</a></li>
          <li><a href="#">About 3</a></li>
        </ul>
      </aside>
    </main>
    <footer>
      <p>My Sementic Page</p>
      <p>Contact : <address>[email protected]</address></p>
    </footer>
  </body>
</html>

이걸 실행해 보면 끔찍하다. 왜냐하면 아무런 스타일이 없기 때문이다. 후에 CSS를 정리할 때 스타일을 적용해 볼 수 있을 것이다. 하지만 지금은 시맨틱한 페이지를 만든 것에 만족하고 태그들을 살피자.

3.2. header

header 태그는 구획을 요약하고 소개, 탐색에 도움을 주는 컨텐츠 그룹을 나타낸다. 만약에 body에 바로 포함되어 있다면 문서 전체의 헤더를 나타낸다.

section, article, nav, aside 등의 요소 안에 포함되어 있다면 해당 요소의 헤더를 나타낸다. 즉 영역의 제목과 간단한 설명 등을 감싸는 데에 사용할 수 있다.

단 address, footer나 다른 header 태그의 자손으로는 사용될 수 없다.

<!-- 이런 식으로 중첩된 헤더를 만들면 안 된다. -->
<header>
  Parent header
  <header>
    Child header
  </header>
</header>
<!-- 이런 식으로 중첩된 헤더를 만들면 안 된다. -->
<header>
  Parent header
  <header>
    Child header
  </header>
</header>
<!-- 이런 식으로 중첩된 헤더를 만들면 안 된다. -->
<header>
  Parent header
  <header>
    Child header
  </header>
</header>
<!-- 이런 식으로 중첩된 헤더를 만들면 안 된다. -->
<header>
  Parent header
  <header>
    Child header
  </header>
</header>

header는 h1~h6, nav, form, section, article, aside, header, footer, address 등의 요소를 포함할 수 있다.

footer 태그는 가장 가까운 구획의 footer를 나타낸다. 일반적으로 작성자, 저작권 정보, 관련 문서 바로가기 등을 담는다. 예를 들어 address 요소를 포함하는 게 일반적이다. 단 구획 콘텐츠는 아니라서 개요에 새로운 구획을 생성하지는 않는다.

footer가 body 요소의 자식이면 footer는 전체 페이지에 적용된다.

3.4. main

main은 페이지의 주요 컨텐츠이다. 문서의 핵심 주제나 핵심 기능에 직접적으로 연결된 컨텐츠를 말한다.

주요 컨텐츠인 만큼 hidden 속성이 없는 한 문서에 하나만 존재해야 한다. main은 article, section, div 등의 태그들을 포함할 수 있으며 요소 개요에 영향을 주지 않는다. 또한 이상적으로는 body에 바로 포함되어야 하며 다른 요소 안에 포함되어서는 안 된다.

3.5. article

article은 페이지의 나머지 요소와 상관없이 독립적으로 구분되고 재사용할 수 있는 컨텐츠 블록을 나타낸다. 뉴스 기사나 블로그 포스트 같은 것.

하나의 문서가 여러 개의 article을 포함할 수 있는데, 사용자가 스크롤하면 계속 다음 글을 보여주는 블로그의 경우 각 글이 article 태그가 될 것이다.

사용할 때 의미론적으로 생각해야 할 건 다음과 같다.

  • 각 article은 독립적으로 구분되어야 한다.
  • article을 식별할 수단이 필요하다. 제목 요소를 article에 포함시키는 방법이 일반적이다.
  • article이 중첩되어 있을 경우 안쪽 article은 바깥쪽 article에 관련된 글이다.
  • address 태그를 이용해서 작성자 정보를 제공할 수 있다.
  • article의 작성요소와 시간은 time의 datetime을 이용해서 표시할 수 있다.

3.6. aside

aside 태그는 페이지의 메인 컨텐츠와 직접 관련이 있지는 않지만 페이지의 주제와 간접적인 관련이 있는 컨텐츠를 나타낸다. 주로 사이드바로 표현되며 작성자의 정보, 용어 사전, 관련 링크 등이다.

3.7. nav

nav 태그는 페이지의 주요 링크를 모아놓은 구획을 나타낸다. 주로 메뉴나 목차를 만들 때 사용한다. 단 문서의 모든 링크를 포함할 필요는 없고, 주요 링크만 있으면 된다. 나머지 링크들은 footer에 포함될 때가 많다.

또한 페이지 내에 목적에 따라 nav 여러 개를 가질 수 있는데 접근성 향상을 하려면 nav에 aria-labelledby을 추가해야 한다. 스크린리더도 nav를 참고하기 때문에 접근성에 영향을 미칠 수 있다.

3.8. address

가까운 HTML 요소의 사람, 단체, 조직 등에 대한 연락처 정보를 나타낸다. 주소, 이메일, 전화번호, SNS 등 어떤 정보라도 포함할 수 있다.

헤더에 제작자의 연락처를 적는 데 사용할 수도 있고 article 내에 배치해서 해당 글의 작성자를 나타내는 데 쓸 수도 있다. footer 안에 흔히 쓰인다.

<address>
  <p>Written by <a href="mailto:[email protected]">soakdma37</a>.</p>
</address>
<address>
  <p>Written by <a href="mailto:[email protected]">soakdma37</a>.</p>
</address>
<address>
  <p>Written by <a href="mailto:[email protected]">soakdma37</a>.</p>
</address>
<address>
  <p>Written by <a href="mailto:[email protected]">soakdma37</a>.</p>
</address>

<address>내부에 더 복잡한 형태의 마크업을 포함시켜 여러 연락처 정보를 담을 수도 있다.

<address>
  <ul>
    <li>Tel: 01234 567 890</li>
    <li>Email: [email protected]</li>
  </ul>
</address>
<address>
  <ul>
    <li>Tel: 01234 567 890</li>
    <li>Email: [email protected]</li>
  </ul>
</address>
<address>
  <ul>
    <li>Tel: 01234 567 890</li>
    <li>Email: [email protected]</li>
  </ul>
</address>
<address>
  <ul>
    <li>Tel: 01234 567 890</li>
    <li>Email: [email protected]</li>
  </ul>
</address>

<address>태그의 내용에 연락처 외의 정보를 담아서는 안된다. 가령 날짜 같은 것을 담으면 안된다.

3.9. section

section은 HTML 문서에서 하나의 기능을 수행하는 독립적인 구획을 나타낸다. 더 적합한 의미 요소가 없을 때 사용한다. 제목을 포함할 수도 있고 아닐 수도 있는데 제목이 아니라도 각 section을 식별할 수단이 필요하다.

단 콘텐츠가 외부와 구분되어 단독으로 존재할 수 있다면 article 태그를 쓰는 것이 나을 수 있다. 그리고 section은 일반 컨테이너로 사용하는 게 아니라 문서에 해당 구획이 논리적으로 구분되어야 할 때 사용한다. 스타일링만이 목적이라면 div를 쓰자.

section은 article과 비슷하다. 차이라고 한다면 article은 독립적으로 구분되어야 하지만 section은 그렇지는 않다. 그리고 맥락에 따라 article을 여러 개의 section으로 구성하거나 하나의 section을 여러 article로 구성할 수 있다.

<section>
  <h2>Heading</h2>
  <img src="./my-image.png" alt="페이지 예시 이미지" />
</section>
<section>
  <h2>Heading</h2>
  <img src="./my-image.png" alt="페이지 예시 이미지" />
</section>
<section>
  <h2>Heading</h2>
  <img src="./my-image.png" alt="페이지 예시 이미지" />
</section>
<section>
  <h2>Heading</h2>
  <img src="./my-image.png" alt="페이지 예시 이미지" />
</section>

3.10. heading

<h1>에서 <h6>까지의 요소는 6단계의 구획 제목을 나타낸다. <h1>이 제일 큰 제목이다.

<h1>태그는 페이지당 1개만 있는 것이 좋으며, 제목 태그 자체를 한 페이지에 3개 이상 사용하는 것은 좋지 않다. 많은 단계의 목차를 가진 경우 다루기 쉽지 않기 때문이다. 이런 상황에서는 컨텐츠를 여러 페이지로 나누는 것이 좋다.

그리고 <h1>을 쓴 구획 내에서는 <h2>를 다음으로 사용하는 등 제목 단계를 순차적으로 쓰는 것이 좋다. 그것이 스크린 리더 사용자의 접근성에 좋다.

h1~h6태그에는 기본 스타일링이 있지만, 이는 의미와는 상관이 없다.

예를 들어서 span 태그의 텍스트에 css를 적용하여 h1 태그의 기본 스타일링처럼 보이게 했다고 해도 두 태그의 근본적인 의미 차이는 바꿀 수 없다.

제목 텍스트에 이 태그들을 쓰고, 폰트 사이즈 스타일링 등이 필요하다면 font-size CSS를 사용하자.

3.11. non-semantic wrapper div, span

어떤 내용을 넣을 특정한 시맨틱 태그가 마땅하지 않을 때 div나 span 태그를 딱히 태그 자체의 의미는 없는 래퍼 태그로 사용한다.

div는 블록 레벨 요소로 묶을 때 쓰이고 span은 인라인 요소로 요소들을 묶을 때 쓰인다. 이렇게 묶어서 class등으로 스타일링을 할 수 있다.

단 div 요소는 너무 편리하기 때문에 지나치게 많이 쓰일 때가 있는데, 어떤 시맨틱 태그도 어울리지 않을 때만 생각해서 써야 한다. 그렇지 않으면 의미없는 div 태그들로 코드가 어수선해지게 될 것이다.

3.12. br

텍스트 안에서 끊고 싶은 지점에 삽입하여 줄바꿈을 강제로 지정한다. 이는 짧은 줄들로 문장을 쓰고 싶을 때 줄바꿈을 강제하는 유일한 방법이다. 시를 HTML 내에서 표현할 때 등에 쓸 수 있다.

단 줄바꿈을 삽입하는 요소일 뿐이므로 문단 구분을 <br>요소로 하지는 말자. 문단 구분에는 <p>태그를 사용하는 게 좋고 여백을 두는 데에는 margin CSS를 쓰는 게 좋다.

3.13 hr

hr 태그는 문단의 분리나 테마의 전환 등 문단 레벨 요소들의 주제 구분을 위해 사용된다. 브라우저에서는 수평선으로 그려진다.

단 주제의 분리라는 의미를 가진 요소이므로 단순한 수평선을 그리려는 목적이라면 CSS를 사용하자.

빈 요소이므로 닫는 태그가 있으면 안 된다.