2008년 4월 29일 화요일

DTD 어떻게 읽는지 아세요?

웹표준과 관련된 글들을 올리면서 가장 많이 언급하는 것이 HTML 문서의 DTD이다. 기본적으로 HTML에는 3.2, 4.0, 4.01이 나와 있고, XHTML 1.0과 1.1이 발표되었다. 그런데 HTML 4.01이라고 다 같은 HTML 4.01이 아니고, XHTML 1.0이라고 해서 똑같은 XHTML 1.0이 아니라는데 애로가 있다. 각 버전에는 문법에 대한 엄격성에 따른 DTD가 존재하는데 다음과 같다.

more..


현재 가장 많이 사용되고 있다고 볼 수 있는 DTD를 열거했는데, 크게 보면 HTML 4.01과 XHTML 1.0에 가장 엄격한 문법 준수를 요구하는 Strict, 하위 버전과의 호환성을 보장해주는 Transitional, 프레임셋을 위한 Frameset 타입 세가지로 구성되어 있다. XHTML 1.1에 와서는 의미적으로 Strict 타입만을 지원하며 표기는 위와 같이 한다. 아울러 가까운 미래에 나오게 될 HTML 5 에서는 단순히 <!DOCTYPE html> 라고만 정의하면 그만이게 된다.

DTD는 HTML 문서가 어떠한 구조로 작성되어야 하는지를 명시적으로 정의하는 스펙으로 표준화된 방법을 제안하고 있다. 따라서 우리가 위의 7가지 DTD중 하나를 선택해서 HTML 문서를 작성했다면 해당 DTD가 명시하고 있는 문법 규칙을 올바르게 따라야 오류가 없는 무결한 HTML 문서를 만들수 있게 된다. HTML 문법과 관련된 웹사이트 강좌나 서적이 이미 많이 나와 있고, 완성된 HTML 문서의 유효성 검증(Validation)을 실시해 주는 서비스도 여럿 존재기 때문에 작업에 어려움은 없지만 기왕에 HTML을 다루는 직업을 가졌다면 자신이 사용하는 DTD의 내용을 읽고 이해할 수는 있어야 하지 않을까 하는 생각이 든다. (많은 사람들이 위 DTD를 입맛 따라 골라서 복사해서 붙여놓고 쓸 줄만 알지 어떤 내용인지는 신경쓰지 않는것 같다) 그래서 이 글은 DTD를 읽고 이해하는 방법을 설명하고자 한다.

W3C HTML 4.01 Specification3.3 How to read the HTML DTD 에서 HTML DTD를 어떻게 읽을 것인지를 간단히 설명하고 있다.

사용자 삽입 이미지

  1. 주석(Comment)
    주석은 한 줄 또는 여러 줄이 될 수 있고, 선언문 내에서 연속된 하이픈(-) 두개를 주석내용의 앞과 뒤에 위치시켜서 쓸 수 있다.
    ※ XHTML DTD는 선언부 내 하이픈(-) 주석을 사용하고 있지 않다.

  2. 파라메터 엔티티(Parameter Entity)
    어려운 용어로 정의되어 있는데 파라메터는 매개변수를 말하고, 엔티티는 대체문자를 말한다. 간단히 설명하면 미리 정의된 변수를 대체문자로써 사용하겠다라는 뜻이다. 다시 말해 %attrs;이라는 엔티티에는 이미 style, class, alt, title과 같이 거의 모든 엘리먼트에 포함되는 속성명들을 정의해 놓고 있어서 이후에 정의하는 엘리먼트에서는 단순히 %attrs;이라고만 정의하면 된다라는 의미다. 프로그래밍을 해보신 분이라면 쉽게 이해하실수 있을것 같다. x라는 변수에 숫자 '3'을 미리 기억시켜 놓고, y = x + 2 라는 프로그래밍을 하게 되면 y의 값은 미리 기억된 x의 값 '3'을 불러와 합산을 해서 '5'라는 결과를 보여주는 것과 같다.

  3. 엘리먼트(Element)
    엘리먼트는 이름과 태그, 컨텐츠 모델(Content Model)로 구성되어 있다. 엘리먼트 이름은 HTML 문서에서 실제로 사용되는 태그의 명칭이 되고, 두번째 나오는 '- O'은 시작태그와 종료태그의 형태를 기술한 것이다. 하이픈(-)일 경우에 태그는 사용되어야 하고, 'O(Omitted)'일 경우에는 생략이 가능하다. 위의 경우에는 시작태그는 필요하고, 종료태그는 생략할 수 있다고 기술한 것이다. 세번째 컨텐츠 모델은 어떤 내용을 갖을 것인가? 하는 것을 기술한다. 위에서는 파라메터 엔티티로 정의된 %inline;과 %flow;가 DT 엘리먼트와 DD 엘리먼트에 각각 기술되어 있고, 괄혹 속에 들어가 있는 것을 볼 수 있다. 또, 애스테리스크(*, 별표)가 붙어 있는 것을 볼 수 있다. 좀 더 쉬운 예를 보자.

    <!ELEMENT DL - - (DT | DD)+>

    DL 엘리먼트를 정의한 것인데 괄호안에 'DT'와 'DD'가 있고, 플러스(+)표시가 붙어 있다. 당연히 알고 있겠지만 DL 엘리먼트에는 DT 요소와 DD 요소를 자식요소로 가질 수 있고,  한 번 이상 쓰일 수 있는데 그것을 위와 같이 기술한 것이다. 정의된 엘리먼트의 괄호는 내용의 그룹이 되며, 산술 기호는 등장 횟수가 된다. 다음과 같은 기호들이 사용된다.

    ( ... ) : 그룹 제한
    A : 오직 A 하나만 나타날 경우
    A+ : A 가 무조건 한 번 이상 나타나는 경우
    A? : A 가 생략되거나 한 번 나타나는 경우
    A* : A 가 생략되거나 한 번 이상 나타나는 경우
    +(A) : A 를 포함할 수 있는 경우
    -(A) : A 를 포함할 수 없는 경우
    A | B : A 또는 B, 둘 다는 아닐 경우
    A , B : A 와 B가 순서대로 나타나는 경우
    A & B : A 와 B가 순서없이 모두 나타나는 경우


    IMG 요소나 BR 요소와 같이 내용을 포함하지 않는 요소의 경우에는 'EMPTY'라고 정의하고, 문자열 이외의 자식 요소를 포함하지 않는 경우(OPTION 요소)에는 '(#PCDATA)'와 같이 정의한다. 또한, A 엘리먼트와 같이 자식요소에 자신을 포함하지 못하는 경우는

    <!ELEMENT A - - (%inline;)* -(A)>

    와 같이 정의한다.

  4. 애트리뷰트(Attribute)
    애트리뷰트를 설명하기 위해서 IMG 요소의 정의 부분을 보겠다.
    <!ATTLIST IMG
      %attrs;                              -- %coreattrs, %i18n, %events --
      src         %URI;          #REQUIRED -- URI of image to embed --
      alt         %Text;         #REQUIRED -- short description --
      longdesc    %URI;          #IMPLIED  -- link to long description
                                              (complements alt) --
      name        CDATA          #IMPLIED  -- name of image for scripting --
      height      %Length;       #IMPLIED  -- override height --
      width       %Length;       #IMPLIED  -- override width --
      usemap      %URI;          #IMPLIED  -- use client-side image map --
      ismap       (ismap)        #IMPLIED  -- use server-side image map --
      >

    애트리뷰트의 이름과 타입, 디폴트 값을 정의한 것을 볼 수 있다. src 애트리뷰트와 longdesc 애트리뷰트는 미리 정의된 URI 타입으로 되어 있고, alt 애트리뷰트 역시 Text 엔티티로 되어 있음을 볼 수 있다. 애트리뷰트에서 중요한 것은 디폴트 값으로 지정되는 네가지 값인데 다음과 같다.

    #REQUIRED : 반드시 정의해야 하는 애트리뷰트이다.
    #IMPLIED : 디폴드 값을 사용도구(웹 브라우저 등)가 지정하며, 경우에 따라 부모 엘리먼트로부터 상속 받는다. 반드시 정의하지 않아도 된다.
    #FIXED : 값이 일정하여 변경이 없는 애트리뷰트이다. HTML 4.01 의 경우에는 없으나 XHTML의 경우에는 xmlns 애트리뷰트와 xml:space 애트리뷰트가 'http://www.w3.org/1999/xhtml' 값으로 #FIXED 되어 있다.

    애트리뷰트 가운데에는 '참'과 '거짓'의 형태로 구분되는 불린(Boolean) 애트리뷰트가 존재하는데 'selected' ,'checked' 와 같은 것들이다.

    <!ATTLIST option
      %attrs;
      selected    (selected)     #IMPLIED
      disabled    (disabled)     #IMPLIED
      label       %Text;         #IMPLIED
      value       CDATA          #IMPLIED
      >


    위와 같이 이러한 불린 애트리뷰트는 자신의 이름을 값으로 가질 수 있도록 정의되어 있다. HTML 4.01에서는 불린 애트리뷰트의 약술을 허용하고 있기는 하지만 XHTML 에서는 옮은 표현이 아니기 때문에 가급적 사용하지 않은 것을 추천한다.

나는 예전에 DL 요소의 자식요소인 DT와 DD가 순서대로 나와야 하는가? 에 대한 의문을 가진 적이 있었다. 의미적으로 DT 요소가 나온 후 DD 요소가 나타나는 것이 맞겠지만 실제로는 둘을 바꿔도 오류를 내지 않았기 때문이었고, 레이아웃을 잡기 위해서 임의적으로 포지셔닝을 하다보니 DT 요소와 DD 요소를 서로 바꾸는 것이 더 편할 때가 있었다. 그런데 잘 기억이 나지는 않지만 어떤 서적인가 사이트에서 DT 요소와 DD 요소는 순서대로 나타나야 한다고 되어 있었던 것을 본 적이 있어 혼자 고민했던 적이 있었다. 그리고는 우연히 해당 DTD 문서를 열어보게 되었는데 다음과 같다.

HTML 4.01 : <!ELEMENT DL - - (DT|DD)+ -- definition list -->

XHTML 1.0 : <!ELEMENT dl (dt|dd)+>

위에서 설명했던 내용을 토대로 이해를 해보자. DL 이라는 이름으로 엘리먼트가 정의 되었고, 시작태그와 종료태그를 모두 가져야 하며, DT 요소 또는 DD 요소가 순서에 상관 없이 한 번 이상 나타날 수 있다고 되어 있다. 순서는 문제가 되지 않았다는 것이다.

이렇게 DTD는 불확실한 정보에 대한 확신을 심어줄 수 있는 최고의 레퍼런스이다. 온전하게는 아닐지라도 대략적으로 DTD를 읽고 이해할 수 있는 능력을 키운다면 새로운 마크업 언어를 익히는 일이 두렵지만은 않을 수 있지 않을까- 그런 생각을 끝으로 DTD를 읽는 방법을 정리해 보았다.


덧붙임.

정찬명님께서 제 글을 보신 후 보다 더 자세하고 친절하게 'HTML DTD 읽기' 방법을 정리해 주셨습니다. 꼭 읽어보시길 바라겠습니다.

댓글 6개:

  1. @정찬명 - 2010/01/22 17:04
    ㅎㅎㅎㅎ 저도 잊고 있었던 글에다가 댓글을!

    감사합니다~

    답글삭제
  2. 태그의 시작과 끝 선언에 대한 설명 중 '- 0' 부분을 숫자 '0'으로 작성하셨는데 이 부분은 숫자가 아니라 알파벳 'O' 입니다.



    보통 숫자 '0'과 알파벳 'O'는 똑같이 보이지만 코딩 전용 글꼴로 보면 다르게 보이기 때문에 발견하게 되었습니다.



    누가 복사해서 퍼갈일은 없겠지만 혹시나 하는 마음에 코멘트 남겨요. 'O'는 'Omitted'의 약자인것 같네요.

    답글삭제
  3. @정찬명 - 2010/01/26 01:02
    아... 전혀 눈치채지 못했었는데 감사합니다^^ 찬명님 역시 꼼꼼하세요~

    답글삭제
  4. 오호 이런구조였군요!

    DTD파일 다시 구경하러 ㄱㄱ ㅋㅋ

    답글삭제
  5. trackback from: HTML DTD 명세서 읽기.
    목차 명세의 시작과 끝 명세의 주석 연산 기호들 등장하는 용어들 본체와 변수 요소와 속성 요소 명세 읽기 속성 명세 읽기 참고 DTD에 표시된 URI(예: loose.dtd 또는 xhtml1-transitional.dtd)를 내려받아서 명세를 한 번이라도 열어보신 분들이라면 알 수 없는 낯선 문자들에 대한 당혹스러움을 감출 수 없었을 것입니다. HTML/XHTML의 문법 규칙들이 포함되어 있고 브라우저가 이것을 어떻게 해석해야 하는지에 대한 단서가...

    답글삭제