22. 범용적 컨테이너 – div와 span 요소

소개

이 글에서는 내용을 “설명하지 않는” 두가지 HTML 요소에 대해, 언제 어떻게 쓸 것인지 설명하고자 합니다. span 요소와 div 요소는 사실 자신이 감싸고 있는 내용에 대해 아무런 의미도 전달하지 않습니다. 대신 커스텀한 구조를 만들거나, 또는 정말로 다른 어떤 적절한 요소가 없는 내용들을 하나로 묶어서 CSS로 스타일을 부여할, 혹은 자바스크립트로 조작할 수 있도록 합니다. div 요소들이 아무런 의미를 더하지 않기는 하지만, 의미있게 부여된 클래스명이나 id를 통해 마크업의 구조적 측면을 표현한다고 생각할 수 있습니다.

이러한 것들은 “최후의 보루” 여야 하며, 정말로 적당한 다른 것이 전혀 없을 경우에만 사용해야 합니다. 보조 기술이나 검색엔진 등에 아무런 의미도 없는 것이기 때문입니다.

이 글의 구조는 다음과 같습니다:

  • 의미적으로 중립인
  • 인라인 vs 블럭
  • 컨텐츠 그룹화에 대해 좀 더…
  • 자바스크립트와 CSS를 위한 훅
  • div-itis
  • 적절치 않은 사용
    • 무의미한 문단
  • 표현적 요소
  • 요약
  • 연습문제

의미적으로 중립인

HTML 요소의 대부분은 그 내용을 설명하거나, 문서의 틀을 짜는데 일조합니다. 전자의 예로는 img, ul/ol, h1~h6 같은 것이 있으며 후자의 예로는 head, body, link, meta 같은 것이 있습니다. 그런데, 아무런 의미도 부여되지 않은 요소가 2개 있습니다. HTML 명세에 따르면:

div와 span 요소는 id, class 속성과 함께 사용하여 문서에 구조를 더하는 포괄적인 메커니즘을 제공합니다.

이 두 요소는 HTML의 비계1)라고 생각해도 될 것입니다. 컨텐츠를 묶고, 추가적인 정보를 제공하며, 스타일과 동작을 더하기 위한 고리 구실을 합니다. 하지만 문서에 아무런 의미적인 것도 추가하지 않습니다.

인라인 vs 블럭

앞에서 배운 바와 같이, 블럭 요소들은 문서의 구조를 표현하는데에 도움이 됩니다. div 요소는 분할division의 약자인데, 포괄적인 블럭 레벨 컨테이너입니다. 이것은 보통 다른 블럭 레벨 요소들을 감싸서 하나로 묶는데 사용합니다(다음 섹션에서 더 자세히 볼 것입니다). 또한 이것은 다른 블럭 레벨 요소에는 논리적으로 맞지 않는 인라인 요소들과 텍스트를 하나로 묶는데 사용할수도 있긴 하지만, 어디까지나 최후의 보루입니다.

span 요소는 인라인 레벨의 포괄적 컨테이너입니다. 이것 역시 문서의 구조를 표현하는데에 도움이 되지만, 블럭 레벨 요소가 아니라 인라인 요소와 텍스트를 묶거나 감싸는 용도로 사용합니다.

처음에는, 이 둘 사이의 차이점이 무척 인위적이라고 느껴질 수 있습니다. 기억해야 할 것은 내용의 타입이며, 스타일을 적용하지 않고 표시하였을때 어떻게 보일지 입니다. div 는 블럭 레벨 요소를 감쌉니다 – 예를 들어, 제목에 링크의 목록을 더해서 내비게이션을 만드는 것입니다. span 요소는 인라인 요소들 또는 (대부분의 경우) 평범한 텍스트들을 감쌉니다.

키워드는 “그룹” 입니다: 만약 div 요소가 단 하나의 블럭 레벨 요소만을 감싸고 있거나, span 요소가 단 하나의 인라인 요소만을 감싸고 있다면, 그것은 필요없는 것입니다. 예를 들어서, 다음의 단순한 마크업에서 div와 span 요소가 사용된 방법을 눈여겨 보기 바랍니다:

<body>
  <div id="mainContent">
    <h1>Title of the page</h1>
    <p>예제 페이지의 첫번째 문단입니다.</p>
    <img src="example.gif" alt="이 이미지는 단순한 예제입니다.">
    <p>예제 페이지의 두번째 문단입니다. 첫번째 것과 매우 흡사하지만,
    <span id="specialAlert">CSS를 이용해서 색을 지정하고 크기를 키울
    부분이 있습니다.</span>.
    이것은 일반적인 강조가 아닙니다 - 강조에는 단순한 스타일링 이상의 목적이
    있습니다. 따라서 <em> 이나 <strong> 은 여기 적합하지 않습니다.</p>
  </div>
</body>

이제 div와 span 의 id 속성을 이용해서 그 내부의 내용을 선택할 수 있고, CSS를 사용해서 특별한 스타일과 위치 지정을 할 수 있습니다.

컨텐츠 그룹화에 대해 좀 더…

인터넷에서 여러 페이지들의 소스를 살펴보다 보면, 많은 div 요소들의 클래스와 id 에 공통적인 것 – header, footer, content, sidebar 등 – 이 있음을 보게 될 것입니다.

 

항상 “의미 있는” id와 class명을 사용하도록 해야 합니다. 이 말의 의미는, 단순히 외관을 요약하도록 그 이름을 짓는 것이 아니라, 내용이 갖는 의미와 역할을 나타낼 수 있도록 하라는 것입니다. 예를 들어, sidebar 라든가 alertMessage 같은 것은 클래스명으로 적합합니다만, “왼쪽의빨간색컬럼”redLeftHandColumn 이라든가 “파란색으로반짝이는텍스트”blueFlashingText 같은 것은 적합하지 않은 것입니다. 나중에 사이드바의 색을 빨간색에서 파란색으로 바꾸면 어떻게 됩니까? 경고 메세지가 파란색으로 반짝이던 것을 녹색으로 표시하고 반짝임은 없앤다면 어떻게 되겠습니까?

 

이러한 분류는 페이지의 구조를 만들면서 예상할 수 있도록 하며, 아마도 그보다 더 중요하게는, 나중에 HTML을 다시 살펴 볼 일이 있을때 이것이 페이지의 어떤 부분인지 단서를 제공한다는 것입니다. 잘 분할된 페이지는 그 내용을 스스로 문서화할 수 있습니다.

실제 사이트 – dev.opera.com의 홈페이지 에서 div 들의 구조를 보면서 이것을 좀 더 명확하게 알 수 있기를 바랍니다. 염두에 둘 것은, 아래의 예제 코드에는 실제 내용이 전혀 포함되어 있지 않으며, 사이트의 구조에 중요한 부분을 차지하기 때문에 내가 임의로 추가한 몇가지 요소가 있다는 것입니다. 아래의 예제를 만들면서 주력한 것은 div 요소들을 사용해서 사이트의 구조를 정의된 그대로 다시 만든다는 것입니다. 아래의 코드를 보면서 HTML 주석들을 신경써서 읽어야 합니다 – 이것들은 사이트의 구조를 설명하기 위해 추가한 것입니다. 아래의 코드를 살펴보면서, 동시에 dev.opera.com의 홈페이지를 열어서 구조와 모양을 동시에 보길 바랍니다.

<body>
<!-- 먼저 페이지 전체를 감싸는 div 입니다. 이렇게 하면 페이지 전체를 좀 더 세밀하게 조절할 수 있습니다 -->
  <div id="wrap">
  <!-- 이 목록은 오페라의 모든 사이트들에 대한 링크이며, 페이지의 맨 위에서 볼 수 있습니다 -->
    <ul id="sitenav" class="hidemobile">
      ...
    </ul>
      ...
    <!-- 검색 폼입니다 - 사이트의 오른쪽 위에서 볼 수 있습니다 -->
    <form action="/search/" method="get" id="search">
      <div>
        ...
      </div>
    </form>
    <!-- 이 목록은 사이트의 메인 내비게이션을 담고 있습니다 - 로고 그래픽의 바로 아래에 보이는 가로로 정렬된 탭 입니다 -->
    <ul id="menu">
      ...
    </ul>
    <!-- 이 중첩된 div 는 로그인 박스의 구조를 형성합니다. 로그인 박스에는 사용자 이름과 비밀번호를 넣어서 로그인하는 용도인데, 로그아웃된 상태에서만 보일 것입니다 -->
    <div id="loginbox">
      <div id="login">
        ...
      </div>
    </div>
    <!-- 여기에서 중첩된 div 들은 페이지가 담고 있는 주된 컨텐츠들입니다. 각각의 글들은 페이지의 메인 컨텐츠를 요약하고 있습니다. -->
    <div id="content2">
      <div id="main">
        ...
        <div class="major">
          ...
        </div>
        <div class="major">
          ...
        </div>
        ...
      </div>
    </div>
    <!-- 이 div는 페이지의 사이드바를 담당합니다. 각각의 글의 분류, 가장 최근의 코멘트 같은 것이 포함됩니다 -->
    <div id="side">
      ...
    </div>
    <!-- 이 div는 페이지의 푸터를 포함합니다. 여기에는 저작권 노트, 그리고 페이지 하단에 있는 다양한 링크들이 담길 것입니다 -->
    <div id="footer">
      ...
    </div>
  <!-- 페이지의 끝 - wrap div가 끝나는 곳입니다 -->
  </div>
</body>

추가적인 정보

일부 컨텐츠는 사용자 에이전트나 기타 파서에서 사용할 수 있는 정보를 가지고 있을 수 있습니다. 이러한 정보는 속성을 통해서 전달되어야 합니다. span 요소는 그러한 정보를 전달하는데에 유용하며, 다음에서 살펴보겠습니다.

문서에서 다른 언어로 표현된 부분이 이에 적합한 예가 될 것입니다.

<p><q>Plus ça change, plus c'est la même chose</q> she said.</p>

문서의 주된 언어는 영어이지만, 인용구는 프랑스어로 되어 있습니다. 이러한 것은 lang 속성을 다음과 같이 사용하여 나타낼 수 있습니다.

<p><q lang='fr'>Plus ça change, plus c'est la même chose</q> she said.</p>

위의 예제에서는 언어의 변화가 일어난 모든 부분이 인용구 내에 있었으므로, q 요소를 이용해서 내용을 감쌌다면 더욱 좋았을 것입니다. 하지만 의미 있는 요소들 중에서 적합한 것을 찾을 수 없어서 별 수 없이 span 이나 div 를 사용해야 할 경우도 있을 수 있습니다. 예를 들어:

<p>스크린 리더는 프랑스어 단어 chat(고양이) 이 올바르게
마크업되어 있지 않다면 그것을 chat (격의 없이 대화하는것. 채팅)
으로 읽을 것입니다.</p>

이 예제에서는, “chat” 이라는 단어가 처음 나타난 것에서는 영어 문서에서 나타난 프랑스어의 예를 드는 것이므로, 영단어 chat 으로 인식되지 않도록 다르게 나타내어야 합니다. 이 경우에는, chat 이란 단어를 span 요소로 감싸는 것이 적합할 것입니다 – 프랑스어 단어를 나타내는데 적합한 HTML 요소가 없기 때문입니다(그 단어를 강조하는 것도 아니고, 그 단어는 인용구도 아니며, 코드도 아닙니다). 또한 이것은 문장 중의 한 단어이고 인라인 레벨입니다. 따라서 위의 것을 더 잘 쓴다면 아래와 같을 것입니다:

<p>스크린 리더는 프랑스어 단어
<span lang='fr'>chat</span>(고양이) 이 올바르게
마크업되어 있지 않다면 그것을 chat (격의 없이 대화하는것. 채팅)
으로 읽을 것입니다.</p>

이러한 것은 웹 페이지에서 공통적인 데이터 포맷을 마크업하기 위해 마이크로포맷 을 사용했었던 것과 같은 테크닉입니다. dev.opera.com의 더 진보된 HTML 기사들 에서 마이크로포맷에 관해 훨씬 많이 배울 수 있을 것입니다.

자바스크립트와 CSS를 위한 훅

div 와 span 요소에 id, class 속성을 사용하고, CSS에서 그것을 이용해서 특정 부분에 스타일을 적용하고 위치를 지정하는 것에 관해서는 이미 살펴보았습니다. 같은 것을 자바스크립트에도 적용할 수 있습니다.

문서의 특정한 요소를 자바스크립트로 찾아내고 조작하려면, id 속성을 적용한 후 getElementById 함수를 이용해서 그것을 찾아내는 것이 일반적입니다. 같은 일을 당신의 문서에서도 할 수 있습니다.

“div-itis”

한가지 유의할 것은, 웹 개발 업계에서 흔히 “div-itis” 이라 말하는 효과입니다.

div와 span을 많이 중첩시키고, 그것을 통해서 스타일을 적용하는 것이 편해 보일 수 있지만, 이러한 것은 가능한 한 피해야만 합니다. 대부분의 경우에는 문서에 이미 있는 요소들만을 사용해서 스타일이나 자바스크립트 기능을 결합할 수 있습니다. 범용적인 컨테이너는 항상 마지막까지 피해야 합니다. 처음부터 의미 있는 요소들로만 웹 페이지를 만들도록 시도해 보고, 꼭 필요한 경우에만 컨테이너를 추가하는 것이 좋습니다.

적절치 않은 사용

이 섹션에서는 HTML을 이용해서 컨텐츠를 마크업하면서 종종 벌어지는 실수들을 다루려고 합니다. 물론 이러한 것은 가능한한 피해야 합니다.

무의미한 문단

이따금씩, 텍스트 덩어리들을 별 생각 없이 p(문단) 요소로 감싸고 싶을 수 있겠지만, 그렇게 하는 것은 잘못된 것입니다. 내가 이전에 컨텐츠 마크업에 관한 글 에 적었듯이:

몇 개의 단어일 뿐이고 올바른 문장이 아니라면, 그러한 것을 문장으로 마크업해서는 안됩니다.

끊어져 있는 텍스트 내용들을 감쌀 수 있는 적합한 HTML 요소가 없는 경우에는 div 또는 span (상황에 따라) 을 사용해야 합니다.

표현적 요소

이따금씩 인터넷에서 볼 수 있는, b 요소나 i 요소와 같은 범용적인 컨테이너를 span 요소 대신 쓰라는 충고 역시 매우 잘못된 것입니다. 그러한 이유로 제시되는 것은 보통 다음 두가지 중 하나인데:

  • 이 요소들은 3바이트 만큼 짧으니까, HTML과 CSS를 전송할때 대역폭을 절감할 수 있다.
  • 여기에서 필요한 스타일은 외형만을 위한 것이므로, “표현적인” 요소를 사용하는 것이 이 경우에는 적당하다.

첫번째 이유는 맞습니다. 하지만 이러한 것으로 아낄 수 있는 양은 무시할 정도이며(믿을 수 없을 정도로 많은 양의 표현적 효과를 만들고 있다면 예외일수도 있습니다만..), 게다가 최근의 웹 서버들이 문서를 인터넷으로 전송하기 전에 압축을 적용하고 있음을 고려한다면 더욱 더 그렇습니다. 이러한 압축 기술은 사람이 하는 것 보다 훨씬 더 많이 문서의 양을 축소하고 있습니다.

두번째 이유는 “표현” 이라는 것이 HTML 의 문맥에서 실제로 무엇을 의미하는지를 잘 모르기 때문에 할 수 있는 말입니다. 표현적인 요소란 자신이 감싸고 있는 것이 “어떻게 보일 지” 설명하는 것입니다. b 요소는 단순히 “이 안의 텍스트는 볼드체다” 라는 것을 의미합니다. b나 i 같은 요소들은 내부에 있는 것에 스타일을 적용하기 위한 범용적인 훅을 나타내는 것이 아닙니다.

문단 내부의 약간의 텍스트에 스타일을 적용하거나 자바스크립트에서 선택해야 하지만 의미에 맞는 요소가 없을 경우, 정확한 요소는 오직 span 뿐입니다.2)

요약

span 과 div 요소에 대해 자세히 살펴보았습니다. 이제 이 요소들의 용도에 대해 훨씬 더 잘 이해하고, 자신있게 사용할 수 있을 것입니다. 이후 CSS에 관한 글에서 이러한 것을 이용해서 페이지 레이아웃을 만들고 또 다른 방법으로 활용할 수 있는 것을 더 많이 살펴볼 것입니다.

연습문제

  • div와 span의 차이는 무엇입니까?
  • 이 요소를 웹 페이지에서 사용하는 2가지 주된 용도를 들어 보십시오.
  • 즐겨 사용하는 웹 사이트의 페이지과 그 구조를 살펴보십시오. div와 span을 많이 사용하고 있습니까? 뭔가 잘못되었거나 부적절하게 사용된 부분이 있는지, 있다면 어떻게 수정할 수 있을지 생각해보기 바랍니다.

저자에 대해서

Mark Norman Francis는 웹이 발명되기 전부터 인터넷에서 일을 했었다. 그가 마지막으로 일했던 Yahoo!에서 세상에서 가장 큰 웹사이트를 위한 Front End Architect로, 최상의 방법을 정의하고, 국제적인 웹개발의 표준과 품질을 만들(Coding)었다. 

Yahoo! 이전에 그는 Formula One Management에서 일했다, Purple Interactive와 City University에서 웹 개발에 포함되는 각종 규칙을 만들고, CGI 프로그래밍과 시스템 설계를 했다. 그는 블로그를 운영중이다.

이 글과 비슷한 종류의 글은 'HTML' 카테고리에서 더 찾아볼 수 있습니다. 또한, , , , 태그로도 검색해 보실 수 있습니다. 북마크를 하시려면 퍼머 링크로 기억해 주세요.
이 글을 다 읽어주셨다면, 댓글을 남겨주세요. 좋았다라는 격려도 좋고, 잘못된 부분을 지적해 주시는 것도 좋습니다. 마음에 드셨다면 아래 Like 버튼을 눌러서 페이스북과 트위터로 소개해 주시면 더욱 좋겠습니다.