6강 일반 게시판 스킨 (skin/board) > 퍼블리싱강좌

퍼블리싱강좌

6강 일반 게시판 스킨 (skin/board) 정보

표준화 6강 일반 게시판 스킨 (skin/board)

본문

6강 일반 게시판 스킨 (skin/board)

  1. 게시판은 무엇으로 이루어지는가?
    1. 공통
    2. 목록
    3. 글쓰기
    4. 읽기
  2. 레이아웃 계획
    1. 목록
    2. 글쓰기
    3. 읽기
  3. 문서구조를 세워보자
    1. 목록
    2. 글쓰기
    3. 글읽기

게시판은 무엇으로 이루어지는가?

각 화면에서 보여지는 순서대로 (위에서 아래로), 현재 그누보드의 각 요소를 알아보겠습니다. 중복되는 내용은 기능과 목적에 큰 차이가 없는 한 생략합니다. 다음 설명에서 '선택기능'은 사용자가 기능의 사용여부를 지정할 수 있는 기능을 일컫습니다.

공통

상단파일
게시판의 상단에 불러온 파일입니다. 일반적으로 게시판이 시작되기 전 레이아웃을 담당하는 파일을 불러옵니다.
상단이미지
게시판의 상단에 불러온 이미지입니다. 게시판관리자에서 파일첨부로 입력할 수 있습니다.
상단내용
사이트 관리자가 게시판 상단에 직접 입력한 문구 혹은 HTML 을 보여줍니다.
하단내용
사이트 관리자가 게시판 하단에 직접 입력한 문구 혹은 HTML 을 보여줍니다.
하단이미지
게시판의 하단에 불러온 이미지입니다. 게시판관리자에서 파일첨부로 입력할 수 있습니다.
하단파일
게시판의 하단에 불러온 파일입니다. 일반적으로 게시판이 끝나고 난 이후의 레이아웃을 담당하는 파일을 불러옵니다.

목록

분류
게시판의 글을 종류에 따라서 나눠놓은 목록입니다. 분류는 선택기능입니다.
전체글수
게시판에 등록된 전체글수 중 댓글을 제외한 원글수를 보여줍니다.
RSS
구독한 사용자에게 자동으로 최신 게시물을 전송합니다.
관리자
게시판의 관리자 모드로 접속합니다.
번호
게시물의 번호입니다. 정렬기준에 따라 원글의 순서를 번호로 표시하며, 게시판관리자에서 정렬기준을 변경할 수 있습니다.
게시물 선택하기 (체크박스)
여러 게시물을 한번에 삭제, 복사, 이동하고자 할 때, 대상을 선택합니다.
제목
게시물의 제목을 표시합니다.
글쓴이
게시물의 작성자를 표시합니다. 실명과 별명 중 선택할 수 있습니다.
날짜
게시물이 작성된 날짜를 표시합니다.
조회
게시물의 열람횟수를 표시합니다.
추천
게시물이 얻은 추천횟수를 표시합니다.
비추천
게시물이 얻은 비추천횟수를 표시합니다.
선택삭제
선택한 게시물(혹은 게시물들을) 한번에 삭제합니다.
선택복사
선택한 게시물(혹은 게시물들을) 한번에 다른 게시판으로 복사합니다.
선택이동
선택한 게시물(혹은 게시물들을) 한번에 다른 게시판으로 이동합니다.
글쓰기
해당 게시판에 글을 작성합니다.
페이지 나눔
페이지당 목록 출력 갯수에 따라 전체 원글수를 나눠 페이지로 표시합니다.
검색
해당 게시판의 원글과 댓글을 대상으로, 여러가지 옵션으로 글을 찾습니다.

글쓰기

이름
작성자의 이름을 입력합니다. (비회원)
패스워드
게시물의 수정 혹은 삭제 등에 쓰이는 패스워드를 지정할 수 있습니다. (비회원)
이메일
작성자의 이메일을 입력합니다. (비회원)
홈페이지
작성자의 홈페이지를 입력합니다. (선택기능)
옵션
공지사항, 비밀글 설정 혹은 HTML 사용 등을 설정할 수 있으며, 사이트 관리자가 각각의 설정에 대해 이용권한을 제한할 수 있습니다. 특히 공지사항 설정은 일반적으로 게시판관리자 이상만 지정할 수 있습니다.
분류
게시물이 속할 분류를 선택합니다.
제목
게시물의 제목을 입력합니다.
내용
게시물의 내용을 입력합니다. 일반 입력상자 혹은 DHTM 에디터 중 선택할 수 있습니다.
링크
게시물과 연관된 링크를 입력합니다. 이 링크는 일반적으로 새창으로 뜨며, 몇명의 독자나 사용자가 해당 링크를 통해 접속했는지도 알려줍니다.
파일첨부
게시물과 연관된 파일을 업로드합니다. 몇명의 독자나 사용자가 해당 파일을 다운로드 받았는지 알려줍니다.
트랙백주소
설명하기가 어렵네요. 차후에 설명하겠습니다.
CAPTCHA, 자동등록방지
자동등록프로그램으로 광고나 악의적인 목적의 게시물을 자동 혹은 연속으로 등록하는 것을 방지합니다. 웹 접근성에서 주요하게 다뤄질 항목이기도 합니다.
글쓰기
지금까지 입력한 내용을 서버로 전송합니다.
목록
지금까지 입력한 내용을 서버로 전송하지 않고 목록으로 돌아가는 기능입니다. 취소와 같습니다.

읽기

작성일
해당 게시물이 작성된 일시를 표시합니다.
복사
해당 게시물을 다른 게시판으로 복사합니다. 일반적으로 게시판관리자 이상만 가능한 기능입니다.
이동
해당 게시물을 다른 게시판으로 이동합니다. 일반적으로 게시판관리자 이상만 가능한 기능입니다.
목록
해당 게시물이 속한 게시판의 목록으로 돌아갑니다.
수정
해당 게시물을 수정합니다. 작성자 본인 혹은 게시판관리자 이상만 가능한 기능입니다.
삭제
해당 게시물을 삭제합니다. 작성자 본인 혹은 게시판관리자 이상만 가능한 기능입니다.
답변
해당 게시물에 답글을 작성합니다.
글쓰기
현재 게시물 열람을 중단하고 새로운 글을 작성합니다.
제목
해당 게시물의 제목입니다.
스크랩
해당 게시물을 스크랩 목록에 추가합니다. 사이트의 어떤 위치에서라도 스크랩 기능을 이용할 수 있다면 해당 게시물로 한번에 이동할 수 있습니다.
트랙백
설명하기가 어렵네요. 차후에 설명하겠습니다.
글쓴이
해당 게시물을 작성한 사람의 이름을 표시합니다.
아이피
해당 게시물의 작성자 아이피 정보입니다. 일반적으로 게시판관리자 이상에게만 온전한 아이피 주소가 노출됩니다.
조회
해당 게시물을 몇명의 독자 혹은 사용자가 열람했는지 표시합니다.
추천
해당 게시물이 얻은 추천수입니다.
비추천
해당 게시물이 얻은 비추천수입니다.
본문
해당 게시물의 본문입니다.
댓글쓰기
해당 게시물에 남길 댓글을 입력합니다.
댓글보기
해당 게시물에 남겨진 댓글을 표시합니다.

레이아웃 계획

목록

목록 레이아웃은 크게 5개 영역으로 구분할 수 있습니다.
  1. 관리자
  2. 전체글수, 카테고리, 검색, 글쓰기
  3. 목록
  4. 선택삭제, 선택복사, 선택이동, 관리자, 글쓰기
  5. 페이지 나눔

글쓰기

글쓰기는 입력서식 외 특별한 구성을 추가적으로 제공하지 않습니다.

글읽기

글읽기 레이아웃은 크게 7개 영역으로 구분할 수 있습니다.
  1. 수정, 삭제, 복사, 이동, 목록, 답변, 글쓰기
  2. 게시물 헤더 (작성자 정보 등 포함)
  3. 첨부파일, 링크
  4. 본문
  5. 댓글
  6. 댓글쓰기
  7. 복사, 이동, 목록, 답변, 글쓰기

문서구조를 세워보자

목록

영역1. 관리자 바로가기

관리자 바로가기는 게시판의 최상단에 위치시킬 계획입니다. 일반 회원들에게는 노출되지 않기 때문에 디자인적으로 전체 미관을 해치지 않으면서도, 사이트 관리자에게는 편리함을 제공할 것입니다.
활용은 다음과 같이 할 수 있습니다.


영역2. TOTAL / 카테고리 / 검색, 글쓰기
// TOTAL / 카테고리 / 검색
<div>
    <? if ($is_category) { ?>
    <form name="fcategory" method="get">
        <select name="sca" onchange="location='<?=$category_location?>'+<?=strtolower($g4['charset'])=='utf-8' ? "encodeURIComponent(this.value)" : "this.value"?>;">
            <option value=''>전체</option>
            <?=$category_option?>
        </select>
    </form>
    <? } ?>

    <form name="fsearch" method="get">
    <input type="hidden" name="bo_table" value="<?=$bo_table?>">
    <input type="hidden" name="sca" value="<?=$sca?>">
    <fieldset>
        <legend>게시물 검색</legend>
        <span>전체 <?=number_format($total_count)?>건 중</span>
        <label for="sfl">검색대상</label>
        <select id="sfl" name="sfl">
            <option value="wr_subject">제목</option>
            <option value="wr_content">내용</option>
            <option value="wr_subject||wr_content">제목+내용</option>
            <option value="mb_id,1">회원아이디</option>
            <option value="mb_id,0">회원아이디(코)</option>
            <option value="wr_name,1">글쓴이</option>
            <option value="wr_name,0">글쓴이(코)</option>
        </select>
        <label for="stx">검색어</label>
        <input id="stx" name="stx" maxlength="15" required value="<?=stripslashes($stx)?>">
        <input type="radio" id="sop_and" name="sop" value="and">
        <label for="sop_and">and</label>
        <input type="radio" id="sop_or" name="sop" value="or">
        <label for="sop_or">or</label>
        <input type="submit" value="검색">
    </fieldset>
    </form>
</div>

각 상단과 하단에 나뉘어져 있던 내용을 하나의 그룹으로 묶었습니다. 특히 검색으로 연결되는 부분은 ' 전체 n건 중 검색대상 제목 ' 으로 읽을 수 있어 자연스럽고 논리적인 구조가 만들어졌습니다.

// RSS, 글쓰기 버튼
<div>
    <? if ($rss_href) { ?><a href="<?=$rss_href?>">RSS</a><? } ?>
    <? if ($write_href) { ?><a href="<?=$write_href?>">글쓰기</a><? } ?>
</div>
영역3. 게시글 목록
// 테이블 캡션
<caption><?=$board['bo_subject']?> 목록</caption>

게시판 제목 목록으로 caption 을 표시합니다. 예를들어 자유게시판에 접속 중이라면, '자유게시판 목록' 이 자유게시판 글 목록의 caption 입니다.

// 테이블 헤더
<thead>
<tr>
    <th scope="col">번호</th>
    <? if ($is_checkbox) { ?><th scope="col"><input type="checkbox" onclick="if (this.checked) all_checked(true); else all_checked(false);"></th><?}?>
    <th scope="col">제목</th>
    <th scope="col">글쓴이</th>
    <th scope="col"><?=subject_sort_link('wr_datetime', $qstr2, 1)?>날짜</a></th>
    <th scope="col"><?=subject_sort_link('wr_hit', $qstr2, 1)?>조회</a></th>
    <? if ($is_good) { ?><th scope="col"><?=subject_sort_link('wr_good', $qstr2, 1)?>추천</a></th><?}?>
    <? if ($is_nogood) { ?><th scope="col"><?=subject_sort_link('wr_nogood', $qstr2, 1)?>비추천</a></th><?}?>
</tr>
</thead>

이 소스에서 관심을 가지고 살펴볼 속성은 scope 입니다. scope 속성은 제목셀과 내용셀을 연결해주는 역할을 합니다. 웹 접근성에서는 거의 필수적인 요소라고 보시면 됩니다.
HTML5 에서는 scopeheaders 속성으로 scope 만으로 지정하기 어려운 복잡한 테이블을 표현할 수 있습니다. 하지만 가능한 scope 만으로도 의미전달이 충분한 테이블을 작성하는 것이 생산적입니다.

th scope
scope 는 테이블 헤더가 같은 행 혹은 열에 있는 그 다음 셀들 중 일부에 적용되는 것을 의미합니다.
  • scope="row" : 동일한 행에 있는 셀들 중 일부
  • scope="col" : 동일한 열에 있는 셀들 중 일부
  • scope="rowgroup" : 동일한 행에 있는 다른 모든 셀
  • scope="colgroup" : 동일한 열에 있는 다른 모든 셀
  • scope="auto" : 브라우저가 자동으로 선택
더 자세한 설명은 scope 명세(번역)을 참고하세요.
td headers (HTML5)
headers 속성 값으로 지정한 id 를 가진 th 를 가리킵니다.
            <table>
            <thead>
            <tr>
                <th id="name">이름</th>
                <th id="age">나이</th>
            </tr>
            </thead>
            <tbody>
            <tr>
                <td headers="name">지운아빠</td>
                <td>9살</td>
            </tr>
            </tbody>
            </table>
        
위 소스에서 지운아빠(heaers="name")은 이름(id="name")을 가리킵니다. 화면낭독기는 이 테이블을 이름:지운아빠 라고 읽을 것입니다.
// 테이블 내용
<?
for ($i=0; $i<count($list); $i++) {
?>
<tr>
    <td>
    <?
    if ($list[$i]['is_notice']) // 공지사항
        echo '공지';
    else if ($wr_id == $list[$i]['wr_id']) // 현재위치
        echo $list[$i]['num'];
    else
        echo $list[$i]['num'];
    ?>
    </td>
    <? if ($is_checkbox) { ?><td><input type="checkbox" name="chk_wr_id[]" value="<?=$list[$i]['wr_id']?>" title="이 게시물 선택"></td><? } ?>
    <td>
        <?
        echo $list[$i]['reply'];
        echo $list[$i]['icon_reply'];
        if ($is_category && $list[$i]['ca_name']) {
            echo '<a href="'.$list[$i]['ca_name_href'].'">'.$list[$i]['ca_name'].'</a>';
        }

        if ($list[$i]['is_notice'])
            echo '<a href="'.$list[$i]['href'].'">'.$list[$i]['subject'].'</a>';
        else
            echo '<a href="'.$list[$i]['href'].'">'.$list[$i]['subject'].'</a>';

        if ($list[$i]['comment_cnt'])
            echo '<a href="'.$list[$i]['comment_href'].'">'.$list[$i]['comment_cnt'].'</a>';

        // if ($list[$i]['link']['count']) { echo '['.$list[$i]['link']['count']}.']'; }
        // if ($list[$i]['file']['count']) { echo '<'.$list[$i]['file']['count'].'>'; }

        echo $list[$i]['icon_new'];
        echo $list[$i]['icon_file'];
        echo $list[$i]['icon_link'];
        echo $list[$i]['icon_hot'];
        echo $list[$i]['icon_secret'];
        ?>
    </td>
    <td><?=$list[$i]['name']?></td>
    <td><?=$list[$i]['datetime2']?></td>
    <td><?=$list[$i]['wr_hit']?></td>
    <? if ($is_good) { ?><td><?=$list[$i]['wr_good']?></td><? } ?>
    <? if ($is_nogood) { ?><td><?=$list[$i]['wr_nogood']?></td><? } ?>
</tr>
<?}?>
<? if (count($list) == 0) { echo '<tr><td colspan="'.$colspan.'" class="empty_table">게시물이 없습니다.</td></tr>'; } ?>

게시물이 없을 때 나타내는 셀의 클래스는 empty_table 입니다.

영역4. 게시글 선택삭제/선택복사/선택이동/관리자, 글쓰기 버튼
<div>
    <div>
    <? if ($list_href) { ?>
    <a href="<?=$list_href?>">목록</a>
    <? } ?>
    <? if ($is_checkbox) { ?>
    <a href="javascript:select_delete();">선택삭제</a>
    <a href="javascript:select_copy('copy');">선택복사</a>
    <a href="javascript:select_copy('move');">선택이동</a>
    <? } ?>
    </div>

    <div>
        <? if ($write_href) { ?><a href="<?=$write_href?>">글쓰기</a><? } ?>
    </div>
</div>
영역5. 페이지 나눔
// common.lib.php 수정
// 현재페이지, 총페이지수, 한페이지에 보여줄 행, URL
function get_paging($write_pages, $cur_page, $total_page, $url, $add="")
{
    $str = '';
    if ($cur_page > 1) {
        $str .= '처음'.PHP_EOL;
    }

    $start_page = ( ( (int)( ($cur_page - 1 ) / $write_pages ) ) * $write_pages ) + 1;
    $end_page = $start_page + $write_pages - 1;

    if ($end_page >= $total_page) $end_page = $total_page;

    if ($start_page > 1) $str .= '이전';

    if ($total_page > 1) {
        for ($k=$start_page;$k<=$end_page;$k++) {
            if ($cur_page != $k)
                $str .= ''.$k.''.PHP_EOL;
            else
                $str .= ''.$k.''.PHP_EOL;
        }
    }

    if ($total_page > $end_page) $str .= '다음';

    if ($cur_page < $total_page) {
        $str .= '맨끝'.PHP_EOL;
    }
    $str .= "";

    return $str;
}

// list.skin.php

<div>
    <? if ($prev_part_href) { echo '<a href="'.$prev_part_href.'">이전검색</a>'; } ?>
    <?=$write_pages?>
    <? if ($next_part_href) { echo '<a href="'.$next_part_href.'">다음검색</a>'; } ?>
</div>

지금까지 작성한 코드를 조합하면 아래와 같은 페이지가 나옵니다. (CSS가 없는 상태)

게시판 문서구조

글쓰기

글쓰기(온라인 서식)은 이번 g4s 강좌에서 손이 가장 많이 가는 부분 중 하나입니다. 개인적으로 마크업도 어렵게 느껴지지만 디자인하기도 어렵게 느껴지는 부분이 많기 때문입니다.
특히, 웹 접근성과 관련하여 에디터와 캡챠, 보안 이슈가 대두되고 있습니다. 이러한 점들을 자세히 살펴보면 좋겠지만 퍼블리싱보다는 프로그래밍의 측면이 더 크기 때문에, 에디터를 textarea 로만 사용하고, 캡챠는 별도로 다루지 않도록 하겠습니다.
캡챠에 관해 관심 있으신 분들은 개별적으로 아래 사이트를 참조하시면 도움이 될 것 같습니다.

글쓰기 서식에서 유의할 점

그누보드를 표준화하는 과정에서 글쓰기 서식은 다음을 유의해야 합니다.

  • 유효성검사용 예약어 email, alphanumeric, itemname 등의 비표준 속성
  • thtd의 적절한 분리 및 label 설정
  • 파일첨부 추가 시 자바스크립트 사용 부분
선행작업
  • 중첩되어 사용된 table 을 제거합니다.
            //원본
            <table width="<?=$width?>" align=center cellpadding=0 cellspacing=0><tr><td>
    
            <div style="border:1px solid #ddd; height:34px; background:url(<?=$board_skin_path?>/img/title_bg.gif) repeat-x;">
            <div style="font-weight:bold; font-size:14px; margin:7px 0 0 10px;">:: <?=$title_msg?> ::</div>
            </div>
            <div style="height:3px; background:url(<?=$board_skin_path?>/img/title_shadow.gif) repeat-x; line-height:1px; font-size:1px;"></div>
    
            <table width="100%" border="0" cellspacing="0" cellpadding="0">
            <colgroup width=90>
            <colgroup width=''>
    
            //수정본
            <table>
            <caption><?=$board['bo_subject']?> 글쓰기</caption>
            
  • 표현태그, 인라인스타일, 클래스명을 제거하고 제목셀과 내용셀을 구분합니다.
            //원본 : 표현을 위해 사용된 내용없는 셀 (삭제)
            <tr><td colspan="2" style="background:url(<?=$board_skin_path?>/img/title_bg.gif) repeat-x; height:3px;"></td></tr>
    
            //원본
            <table width="100%" border="0" cellspacing="0" cellpadding="0">
            //수정본
            <table>
    
            //원본
            <td class=write_head>이 름</td>
            //수정본
            <th scope="row"><label for="wr_name">이름</label></th>
            
  • itemname, email 등 비표준 속성을 제거합니다.
            //원본
            <input class='ed' maxlength=20 size=15 name=wr_name itemname="이름" required value="<?=$name?>">
            //수정본
            <input name="wr_name" size="15" value="<?=$name?>" maxlength="20" required>
            

    size 속성은 브라우저별로 랜더링 결과가 다르게 나타납니다.
    만약 input이 모든 브라우저에서 일정한 크기로 표현돼야 한다면 id 나 class 를 이용하세요.
    다음은 input 의 브라우저별 랜더링 결과를 캡쳐한 것입니다.

                    <input type="text" size="15">
                
    input의 size 값이 15일때 브라우저별 랜더링 결과
    익스플로러9
    125px
    파이어폭스
    122px
    사파리
    118px
    크롬
    125px
    오페라
    125px
    익스플로러6
    125px
    익스플로러6의 경우 ietester 로 테스트를 진행하여 실제 결과와는 오차가 있을 수 있습니다.
  • 입력폼의 name 속성 앞에 동일한 값의 id 속성을 부여합니다.
            <input id="wr_name" name="wr_name" value="<?=$name?>" maxlength="20" required>
            
  • 파일첨부칸을 증가 혹은 감소시키는 부분을 스크립트로 처리하는 것 이외의 대안을 찾습니다.

    우선적으로 고려해 볼 수 있는 방법은 파일첨부 증가/감소 기능을 제외시키고, 3칸이나 5칸처럼 지정된 만큼 파일첨부 칸을 출력시키는 것입니다.

글쓰기 전체 마크업은 양도 많지만, 캡챠/파일첨부 등을 처리 중이어서 생략하겠습니다. 더 자세하게 살펴보고 싶으신 분은 강좌홈페이지의 테스트게시판을 참조하세요.

글읽기

글읽기 표준화 과정에서 유의할 점

글 읽기 페이지를 작업할 때 중점적으로 다뤄야 할 부분은 자바스크립트로만 동작되는 기능들입니다.
'웹 접근성 향상을 위한 국가표준 기술 가이드라인'에서는 자바스크립트 없이도 주요 기능을 사용할 수 있도록 제공해야 한다고 명시하고 있습니다.
g4s 강좌는 표준화 뿐만 아니라 접근성도 고려하고 있기 때문에 이 부분에 대해 중점적으로 다루겠습니다. 글읽기에서 자바스크립트로만 동작하고 있는 기능은 다음과 같습니다.

  • 첨부파일 다운로드
  • 스크랩
  • 트랙백
  • 댓글 수정
  • 댓글 답변
  • 댓글 삭제

위의 기능들은 내부적으로도 검토 중에 있는 기능들이며, 아직 강좌에서 다룰 수 있을만큼 진척되지는 않았습니다.
예를 들어, 첨부파일 다운로드의 경우 경고메세지 출력을 위해 자바스크립트를 이용하고 있는데, 첨부파일 버튼을 놓는 곳에 관련 경고문구를 미리 보여주는 방식 등을 고려 중입니다.
작업의 진척상황은 역시 강좌홈페이지의 테스트게시판을 참조하세요.

글읽기 마크업 간략
// 구조에 대한 제안을 받습니다.
// 댓글이나 whitedot@네이버.com 으로 제안해주세요.
<ul>수정 삭제</ul>
<ul>복사 이동 검색 목록 답변 글쓰기</ul>
<article>
    <header>
        <h1>분류와 글제목</h1>
        <dl>작성자 작성일 조회 댓글 추천 비추천</dl>
    </header>
    <section>
    첨부파일
    </section>
    <section>
    관련링크
    </section>
    <div>
    첨부이미지 출력
    </div>
    <p>
    내용출력
    </p>
    <ul>스크랩 트랙백 추천 비추천</ul>
    <section>
    댓글목록
        <article>
            댓글내용
        </article>
        <div>
            댓글작성
        </div>
    </section>
</article>

위 구조를 보시면 article 밑에 h1이 나옵니다. 강좌홈페이지(http://g4s.chin.so)의 구조를 확인해보시면 아시겠지만, g4s 에는 이미 h1이 상단에 존재합니다.
한 문서에는 하나의 h1만 갖는 것이 기본인데, 어떻게 h1을 여러개 갖을 수 있는 걸까요?

HTML4에서 문서 구조를 나타내는 유일한 방법은 <h1>~<h6> 엘리먼트를 사용하는 것이었다. 만일 작성한 문서 구조가 한 개의 루트 노트를 갖게 하고 싶다면 마크업에 <h1>을 한 개만 사용해야 했다. 하지만 HTML5 명세는 새로운 시맨틱 엘리먼트를 포함한 문서 구조 생성 알고리즘을 정의한다. HTML5 알고리즘은 <article> 엘리먼트를 새 섹션으로 간주하고 문서 구조에 이를 위한 새 노드를 만든다. 그리고 각 섹션은 자신만의 <h1> 엘리먼트를 가질 수 있다.

이 점이 HTML4와 큰 차이점 중 하나인데, 왜 좋은지 생각해보자. 많은 웹 페이지가 템플릿을 사용해 만들어진다. 내용의 일부를 한 소스에서 읽어와 페이지 상단에 붙이고, 다른 내용을 다른 소스에서 가져와 페이지 하단에 넣는다. 대부분의 튜토리얼도 같은 식으로 "여기 HTML 마크업이 있으니 복사해서 페이지에 붙여보세요"라고 한다. 작은 컨텐트에 대해서는 괜찮지만 복사해서 붙이려는 마크업이 전체 섹션이라면 어떨까? 튜토리얼 같은 데에서는 "여기 HTML 마크업이 있으니 문서 편집기에 복사해놓고 붙이려는 페이지에서 헤더를 표시할 때 사용하는 태그와 같은 레벨로 태그를 수정하세요"라고 친절하게 설명해준다.

여기서 잠깐 생각해보자. HTML4에는 그냥 '헤더'임을 나타내는 엘리먼트가 없고 <h1>~<h6> 처럼 숫자로 정해진 레벨을 가진 엘리먼트만 있다. 때문에 엘리먼트 간에 포함관계를 이 레벨에 맞춰야 하는 단점이 있다. 페이지를 여기 저기서 가져와야 하는 경우 레벨에 맞게 <h1>~<h6>를 고쳐줘야 하므로 매우 불편하고 짜증스럽다. HTML5에서는 이 문제를 해결하기 위해 헤더 엘리먼트를 새로 도입했고 기존 엘리먼트에 새 규칙을 적용했다.

구글 개발자가 들려주는 HTML5 활용, 마크 필그림 지음, 현동석 강유훈 옮김, 오라일리, 에이콘

section으로 구성된 첨부파일과 관련링크는 ul로도 마크업할 수 있을 것입니다.
마찬가지로 본문을 p로만 감싼 부분도 sectionh2를 이용해 감싸줄 수도 있겠죠.
수정이나 복사, 스크랩 같은 버튼은 특별히 section으로 감싸지 않았습니다. 기능적인 면으로 내용과 크게 연관된 부분은 아니라는 생각이며, 디자인 적용 시, 필요하다면 div로 한번 더 감싸줄 수 있을 것입니다.
댓글목록은 section으로 감싸고 각 댓글 하나하나를 article로 지정을 했습니다. 본문에 대한 댓글의 묶음이라는 거죠.

지금까지 일반게시판 스킨 작업 요소들을 대략적으로 살펴봤습니다. 원래 계획은 전체 소스를 열어놓고 하나씩 뜯어나가는 것이었는데, 시간이 부족하고 제가 설명할 수 있는 범위에서도 크게 벗어나는 것 같아 겉핥기만 했습니다. 궁금하신 내용은 댓글로 남겨주세요.
6강을 마칩니다.

추천
6

댓글 19개

좋아요~ 꾹! 강좌 잘보고 있어요~
퍼블리셔분들이 어느 정도 계신지는 잘모르겠지만
전 이런 강의에 너무 행복하네요~
지운아빠님 전진님 화이팅~
위 테스트 게시판의 페이징 부분중, 맨끝의 링크가 제대로 나오지 않는 것 같은데.. 저만 그런가요? ^^;
page=7 으로 나오지 않고, page= 로 끝나서요..
테스트게시판은 말 그대로 테스트게시판이어서 불안정한 면이 있습니다. ^^;;

확인해보니 변수처리를 하나 잘못 해놨었네요. 감사합니다.
수고하셨습니다.
저도 다다음 강 쯤의 그누보드 적용이 있는데, (형식등이) 많은 도움이 될것 같습니다. ^^

질문. 글읽기 마크업 구조에 대해서
물론 현재보다 훨씬 표준화? 된 구조이겠지만,
기존의 리더들 ( 구글 RSS 리더, 사파리 Reader, readability 등)이 이미 지금의 그누보드 게시판 글 마크업 구조에 익숙해져 있을텐데 (예: readability 로 본 글 - http://www.readability.com/articles/9qhfrxoy )
바뀌는 마크업에도 빨리 적응하겠죠? ^^

참, 중간에 vs_class_name, vs_property_name, vc_tag_name 등의 span class가 있던데,
저는 그때그때마다 글 안에 style 정의해서 사용하는데 미리 정의된 것이 있으면 그냥 쓰는게 나을것 같아서요..
제 글에서 사용해도 적용이 되는 건가요? 혹시 다른 것들이 또 있나요? ^^;
readability 는 처음 접했습니다. 시간을 들여 살펴봐야 할 것 같습니다.

http://sir.co.kr/bbs/board.php?bo_table=g4_lecture&wr_id=1
vc_class_name 등은 오늘 추가된 내용이고, 이런 내용은 서식안내에 꾸준히 업데이트하고 있습니다만 따로 알려드린다는게 깜박하고 있었네요. ^^;;
아, 시간을 들이실 만한 내용은 아닙니다.
그냥 원칙적으로 맞는 것과, 현실의 차이? 그런 정도가 궁금했습니다. ^^

넵, 그 포멧관련 글은, 강좌 글 쓸때 항상 참조하고 있습니다.
포함시켜주신 내용도 가끔 사용할 것 같네요.. ^^
제가 포함했으면 하는 내용은 그 글에 댓글하겠습니다. ^^
잘은 모르겠지만, 예를 들어,
현재의 본문은 div class=view_content 로 되어있는데,
위처럼 바뀔 구조는 article>p 로 접근하게 되잖아요?
그런 경우, 기존 리더들이 이를 잘 반영할까 하는 거죠.. ^^;

갑자기 든 생각이, 스크린 리더들은 어떻게 본문인지를 알게되는 걸까요?
sir 구조를 말씀하신 거군요.
위의 구조는 sir 에 적용할 구조는 아니에요. 따라서 바꾸면 좋겠지만 기본 그누보드 외에 추가된 기능들도 있고 해서 작업량이... ^^;;
본문이 div 로 되어있는 건 cheditor 로 글을 쓸때 p 나 br 이 아니라 div 로 줄바꿈을 처리해서 그렇게 했던 건데, 정확한 이유가 기억이 안 나네요. 리자님하고 섞여서 작업한 부분도 있어서요.
꼭 sir만 말씀드린것은 아니고요 ^^;
다른 예로는 그누보드 dtd의 경우 div class="content"로 본문을 표시했고
readability도 적절히 판단한 것 같고요.. http://www.readability.com/articles/qdlcqydo
기본 그누보드는 span id="writeContents" ??
그래서, 제 생각에 대부분의 리더들이 id나 class에서 판단할것 같아서 드린 말씀입니다. ^^
리더가 작동하는 방식을 이해해야 할 것 같은데, 기본적으로는 아이디나 클래스보다 마크업을 기준으로 구분해야 할것 같단 생각이 듭니다.
살펴보고 저도 다시 의견 드릴께요. ㅠㅠ
안녕하세요, 지운아빠님.
왕초보 주제에 겁도 없이 지운아빠님 강의에 도전하고 있습니다.
"//테이블 내용"에서 좀 궁금한 코드부분인데요,

        if ($list[$i]['is_notice'])
            echo '<a href="'.$list[$i]['href'].'">'.$list[$i]['subject'].'</a>';
        else
            echo '<a href="'.$list[$i]['href'].'">'.$list[$i]['subject'].'</a>';

아무리 봐도 두개의 실행문이 동일한 것 같은데 이렇게 해야되는 이유가 있나요?
If 없이 무조건 실행하게 만드는 것과 뭐가 다른지 잘 이해가 안가서 질문드립니다.

너무 초보질문이면 정말 죄송합니다.
PASKRAN님 질문 감사합니다.

해당 부분은 게시물이 공지사항인지 일반 게시물인지 여부를 판별하는 부분입니다.
강좌를 쉽게 쓴다고 하면서도 아무래도 그누보드를 어느 정도 만져본 분들을 머리 속에 그리며 쓰다 보니, 설명이 미흡했습니다.

해당 부분을 다음과 같이 바꾸시면

if ($list[$i]['is_notice'])
    echo '<a href="'.$list[$i]['href'].'"><b>'.$list[$i]['subject'].'</b></a>';
else
    echo '<a href="'.$list[$i]['href'].'">'.$list[$i]['subject'].'</a>';

공지사항인 게시물의 제목은 목록에서 두껍게 표시가 됩니다.
이 방법보다는

css
.notice {font-weight:bold}

php
if ($list[$i]['is_notice'])
    echo '<a href="'.$list[$i]['href'].'" class="notice">'.$list[$i]['subject'].'</a>';
else
    echo '<a href="'.$list[$i]['href'].'">'.$list[$i]['subject'].'</a>';

이렇게 공지사항용 클래스를 미리 정의해두고, CSS 로 스타일을 부여하는 것이 더 좋은 방법입니다.

시맨틱 마크업으로 중요하단 의미를 부여하고 싶다면,

if ($list[$i]['is_notice'])
    echo '<a href="'.$list[$i]['href'].'" class="notice"><strong>'.$list[$i]['subject'].'</strong></a>';
else
    echo '<a href="'.$list[$i]['href'].'">'.$list[$i]['subject'].'</a>';

이와 같이도 하실 수 있습니다.

강좌 내용을 갱신해야 하는 부분이 있는데 여의치가 않습니다. 이 점은 너른 아량으로 양해 부탁드립니다.
질문 감사드리고, 제 답변이 조금이나마 도움이 되었길 바랍니다. :)
예, 공지사항인지 확인하는 부분인건 이해했는데, 공지사항일 경우와 아닐경우 실행되는 명령문이 똑 같아서 고개를 좀 갸웃 거렸습니다.
공지사항일 경우 굵은 글씨로 표현되게 하기위한 부분이었군요.
답변 감사합니다. [꾸뻑]
열심히 공부하겠습니다. ^^
여기부터 다시본다. 엥? 졸다가 썼나?
왜 스크랩에 메모를 했는데.. 여기에. ㅡㅡ

이궁..
슬그머니 삭제하는 것도 참 민망스럽지?
그렇지..

<strong> 이거 필요한가? 삭제.. 하고 작업한 놈.. 저요!
전체 13
퍼블리싱강좌 내용 검색

회원로그인

(주)에스아이알소프트 / 대표:홍석명 / (06211) 서울특별시 강남구 역삼동 707-34 한신인터밸리24 서관 1404호 / E-Mail: admin@sir.kr
사업자등록번호: 217-81-36347 / 통신판매업신고번호:2014-서울강남-02098호 / 개인정보보호책임자:김민섭(minsup@sir.kr)
© SIRSOFT