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의 차이만이라도 알고 있다면) 문법 오류를 최소한으로 줄일 수 있을것 같다.

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

댓글 17개:

  1. 평소에 헷갈리던 부분을 깔끔하게 정리해 주셨네요...

    좋은 정보 감사합니다. 잘 참고하겠습니다.

    답글삭제
  2. 무쟈게 공감가는 얘기네요 ^^

    개발들어가기 전에 공유해줘야하는 내용을 잘 정리해주셨네요~

    답글삭제
  3. 와우! 멋진 정리 감사합니다.

    도움이 많이 될 것 같아요 ;)

    답글삭제
  4. @Outsider - 2008/04/21 13:18
    아닙니다^^ 누구나 다 아는 내용을 재강조하고 싶었을 뿐인걸요.

    답글삭제
  5. @푸땡 - 2008/04/21 13:20
    개발자님들이 작지만 중요한 이런 사실들을 함께 공유하고 있다면 훨씬더 편하게 웹표준 작업을 진행할 수 있겠죠^^

    답글삭제
  6. @rootbox - 2008/04/21 16:30
    와우! 루트박스님~ 자주 와주셔서 감사해요~

    답글삭제
  7. 잘 봤습니다.

    하나, checked="checked" 는 checked="true" 라고 알고 있었는데요. ^^

    답글삭제
  8. @kenu - 2008/04/21 18:03
    checked의 값을 'true'로 해도 체크는 됩니다. 하지만 해당 dtd 문서를 보시면

    <!ATTLIST input

    %attrs;

    %focus;

    type %InputType; "text"

    name CDATA #IMPLIED

    value CDATA #IMPLIED

    checked (checked) #IMPLIED

    ...(중량)...

    이라고 되어 있습니다. 값이 'checked'입니다.



    이를 w3c validate로 돌려보면 'true'는 에러라고 표시됩니다^^ 'true'가 작동되더라도 'checked'로 설정하시는게 맞는것 같습니다.



    http://www.htmlpedia.org/wiki/Sp_131

    여기 가보시면 각각의 속성에 맞는 값을 확인하실 수 있습니다.



    짐작컨데 http://msdn2.microsoft.com/en-us/library/ms533556(VS.85).aspx 보시면 스크립트에서 처리를 할 때 true 값으로 체크 여부를 확인받을 수 있습니다. 이것 때문에 오해하고 계신게 아닌지 모르겠습니다^^

    답글삭제
  9. 웹 퍼블리셔라면 누구라도 이런 주제를 다루고자 마음만 앞섰을것인데 봄눈님께서 먼저 잘 정리해 주셨네요 ^^; 서버사이드 개발자분들이 낚이셔도 그리 기분나빠하시진 않으시겠죠 ^^ 저도 많이 배우고 갑니다~!

    답글삭제
  10. ㅎㅎㅎ 믹시에 올라온 글 제목을 보고 믹시 개발자에게 호소하는 글인 줄 알았어요. 확실한 정리 잘 보고 갑니다.

    답글삭제
  11. @봄눈☆ - 2008/04/21 22:40
    Line 11, Column 54: value of attribute "checked" cannot be "true"; must be one of "checked".

    <p><input type="radio" name="rcheck" checked="true"/></p>

    이렇게 나오는군요.

    덕분에 잘 배워갑니다. 링크도 감사합니다.

    행복기원!

    답글삭제
  12. 비밀 댓글 입니다.

    답글삭제
  13. @정찬명 - 2008/04/22 01:11
    아니 배우시다뇨^^;

    제가 오히려 더 많이 배우는걸요~

    항상 찾아와 주셔서 감사합니다.

    답글삭제
  14. @flexylog - 2008/04/22 13:00
    확실한 정리는 아닐겁니다^^



    많은 개발자분들에게 최대한 쉽게 설명드리고자 자세한 설명은 생략하고 그저 이렇게 해주세요! 라고 쓴 목적의 글이기 때문에 오히려 제대로 공부하신 분들이라면 제글의 부족함을 지적해 주실것이라고 생각합니다^^;

    답글삭제
  15. @Anonymous - 2008/04/23 10:29
    정확한 지적 감사합니다.



    지적해주신 부분중 대부분이 제가 알고 있어도 자세히 기록하지 않은 것들인데, 웹퍼블리셔 일을 하고 있는 사람이라면 꼼꼼이 알아야 해야 할 것이지만 사실 서버사이드개발자분들에게는 지나치게 상세한 설명은 오히려 귀찮은 정보가 되어버릴것 같아서 '이렇게만이라도 챙겨주십시요'라는 의미로 만든 포스트입니다.



    하지만 일부 내용은 지적을 받아들여 첨언해 두었습니다. 종종 wystan님의 블로그를 방문하곤 하는데 제 부족한 글에 댓글 남겨주셔서 정말 감사합니다^^

    답글삭제
  16. 야호~ 머쨍이 봄눈~~~

    나 이거 출력해서~ 개발자 분들께 전해 줄테얍~ ^ㅡ^



    하이킥 두대 정도는 맞을 각오를 하고...ㅋ;;

    답글삭제
  17. @hobread - 2008/04/29 10:25
    하하 고마워요~

    맞지 말고 잘 건네 주세요~

    답글삭제