레이블이 DOCTYPE인 게시물을 표시합니다. 모든 게시물 표시
레이블이 DOCTYPE인 게시물을 표시합니다. 모든 게시물 표시

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 읽기' 방법을 정리해 주셨습니다. 꼭 읽어보시길 바라겠습니다.

2008년 4월 21일 월요일

개발자님 제발 HTML을 깨트리지 말아주세요

이 글은 서버사이드 개발자님들께서 웹퍼블리셔로부터 받은 HTML문서를 작업하는데 있어서 최소한으로 알아주셨으면 하는 내용을 정리한 것입니다. 일부분 상세히 적지 않고(버전별 요소와 속성의 사용 유무 등) 최대한 쉽게 작성하는데 목적을 두었기 때문에 실 작업시에는 웹퍼블리셔와의 커뮤니케이션과 좀 더 정확한 스펙 문서를 참고해 주시기를 부탁드리겠습니다.

웹표준화와 관련하여 웹퍼블리셔는 정확한 Doctype 선언으로부터 마크업을 시작한다. 그리고 올바른 마크업(well-formed) 검증(validate)으로 작업을 마치게 된다. 하지만 많은 경우 사이트가 오픈했을 때 validate를 통과가 어렵다. 이는 서버사이드 개발자들이 웹퍼블리셔로부터 받은 (X)HTML 문서를 수정(개발을 입히는 작업)하면서 올바르지 않은 요소와 속성을 사용하기 때문인 경우가 많다.

서버사이드 언어인 ASP나 PHP, JSP 등은 문법오류에 대한 관용이 적기 때문에 즉각적으로 에러를 보여준다. 하지만 (X)HTML은 브라우저에 따라 관용적으로 처리되거나, 용납되는 경우가 많아 올바르지 않은 마크업을 하고도 화면이 정상적으로 보이는 경우가 많다. 하지만 이렇게 완성된 사이트는 결코 웹표준 사이트라고 볼 수 없거니와, 웹접근성 또한 보장받을 수 없게 된다.

XHTML 스펙을 살펴보면 잘못된 요소와 속성의 사용을 알 수 있지만 대부분의 경우 서버사이드 개발자들은 과거에 익혔던 HTML 문법만을 기억하고 있으며(그다마 올바르지 않은 문법) 새로운 XHTML에 대한 차이를 잘 알지 못한다.

다음은 W3C의 HTML / XHTML 스펙 문서 목록이다.

다음은 XHTML 기준으로 개발자 역시 함께 알아야 하는 내용들이다.

  • HTML 문서의 Doctype이 무엇인지 확인한다.

    HTML 4.01과 XHTML 1.0 에는 각각 'Strict(가장 엄격)', 'Transitional(전환형)', 'Frameset(프레임셋형)' 세가지 타입이 있다. XHTML 1.1은 'Strict'만을 지원하며, 표기는 XHTML 1.1로만 합니다.

    Doctype에 따라 사용 가능한 요소와 속성이 구분되며, CSS에도 영향을 미친다.

  • Doctype 선언 위에 출력되는 요소나 문자열이 없도록 한다.

    DTD는 HTML 문서의 최상단에 선언되어야 한다. 그렇지 않을 경우 일부 브라우저(IE 등)에서 비표준모드(Quirks mode)로 작동하게 된다. 일부 스타일이 제대로 적용되지 못하는 문제가 종종 발생한다.

  • XHTML일 경우 모든 요소와 속성은 소문자로 작성하며, alt와 title 속성을 제외하고 가능한 모든 속성에는 값을 넣어(대부분 넣지 않아도 에러가 나지는 않으나 alt와 title 속성을 제외하면 특별한 이유 없이 빈 값을 넣는 경우는 드믈다)준다. 또한, 모든 속성값은 반드시 인용부호로 둘러싼다.

    validate의 에러를 가장 많이 내는 주범이다.
  • XHTML일 경우 모든 요소는 반드시 닫아주어야 한다. 특히 <head>..</head>사이의 <meta> 요소 작성시 반드시 닫아주자! 또한, 요소의 위치관계를 정확하게 한다.
    <p>내용</p> , <br />, <img src="..." />, <meta ... />, <link rel=".." ... />

    (x) <a href="..."><span>링크</a></span>
    (o) <a href="..."><span>링크</span></a>

  • XHTML 1.1일 경우 <a>, <map>, <form>, <img> 요소에서 name 속성이 폐지되어 사용할 수 없다.

    id 속성만을 사용한다. 하지만 <form>내 <input> 등 요소에서는 name 속성을 사용할 수 있다.

  • MIME Type이 'application/xhtml+xml'일 경우 script와 style 요소는 '<!--'과 '-->'를 '<![CDATA['와 ']]>'로 대체한다. 단, 'text/html'일 경우는 과거처럼 주석 방식을 사용한다.

    CDATA는 script와 style 내 '<', '>', '&'와 같은 문자를 이스케이프 시키지 않고 그대로 사용할 수 있도록 한다. 또한, Doctype에 관계없이 script요소와 style요소를 </head>와 <body>사이에 삽입하는 경우는 없어야 한다. 되도록 script와 style은 외부 문서로 빼는 것이 좋다.

  • XHTML 1.1일 경우 다음의 요소들은 사용할 수 없다.

    <applet>, <basefont>, <center>, <dir>, <font>, <frame>, <frameset>, <iframe>, <isindex>, <menu>, <noframes>, <s>, <strike>, <u>

    특히 , <font>와 <center>, <iframe> 요소는 개발자들이 무분별하게 사용하는 대표 요소인데 Doctype에 따라 사용을 신중히 해야할 필요가 있다. <font>와 <center> 요소는 CSS로 정의할 수 있으며, <iframe>요소는 <object>요소로 대체된다.

  • XHTML 1.1일 경우 다음의 속성들은 사용할 수 없다. (일부 속성은 XHTML 1.0 Strict 에서도 지원되지 않기 때문에 주의 바랍니다.)

    <*> lnag
    <a> name, target
    <area> traget
    <body> background, bgcolor, text, link, vlink, alink
    <br> clear
    <caption> align
    <div> align
    <form> name, target
    <h1~h6> align
    <hr> align, noshade, size, width
    <img> align, border, hspace, vspace
    <input> align
    <legend>align
    <li> type, value
    <link> target
    <map> name
    <object> align, border, hsapce, vspace
    <ol> compact, start, type
    <p> align
    <pre> width
    <strict> language
    <table> align, bgcolor
    <td> bgcolor, height, nowrap, width
    <th> bgcolor, height, nowrap, width
    <tr> bgcolor
    <ul> compact, type

  • 가급적 요소에 직접 스타일(inline style)을 정의하지 않는다.

    <div style="...">
    단, <input>과 <img> 요소 등 개발시 변동이 잦은 요소들에 한해서 inline style로 width와 height를 지정하는 것은 괜찮다고 생각한다. 하지만 저속 인터넷 접속 환경에서는 느린 로딩으로 인해 이미지 요소들이 레이아웃을 잡지 못해 들쑥날쑥하게 전체레이아웃을 깨뜨리는 현상이 발생하기도 하므로 이에 대한 고려가 선행되어야 할 것이다.

  • 요소와 속성내 모든 문자열을 PCDATA(분석 처리된 문자데이터)로 작성한다.

    <p>LOVE & GHOST</p> ☞ <p>LOVE &amp;amp; GHOST</p>
    <a href="../../list.php?id=bomnun&val=2">링크</a> ☞ <a href="../../list.php?id=bomnun&amp;val=2">링크</a>

    * <style>과 <script>요소에서는 <![CDATA[ ... ]]>를 사용해서 문자열을 파싱하지 않고 그대로 사용할 수 있다.

  • XHTML일 경우 속성은 약술할 수 없다.

    <input type="radio" checked /> ☞ <input type="radio" checked="checked" />

  • Encoding Charset이 무엇인지 확인한다.

    HTML 문서는 utf-8인데, 파일 인코딩은 euc-kr인 경우가 종종 있고, 이 경우 한글이 깨져 보이는 가장 큰 이유가 된다. 또한, CSS나 JS 역시 인코딩이 다를 경우 제대로 작동되지 않기도 한다.

세세히 따지면 좀 더 있겠지만 대부분 위의 경우에 해당될 것 같다. 그리고 상위 4개 붉은색으로 표시한 것들이 validate를 통과하지 못하는 대부분의 이유가 된다. 서버사이드 개발자들이 위의 내용을 숙지만 하고 있다면(최소한 DTD의 차이만이라도 알고 있다면) 문법 오류를 최소한으로 줄일 수 있을것 같다.

이 글은 솔직히 서버사이드 개발자들을 '낚기' 위한 글입니다. 위의 내용은 이미 수차례 비슷한 주제의 블로그나 사이트를 통해서 널리 알려져 있는 내용입니다. 결국 복사된 내용의 재탕(웹표준교과서의 내용을 정리했음)이라는 것이지만 그럼에도 불구하고 서버사이드 개발자분들이 한번만이라도 관심 있게 읽어주기를 바라는 마음에 포스팅을 하게 되었습니다.