작성자 : 김문규
최초 작성일 : 2009.6.17

이렇게 완벽한 가이드 문서는 못 보았습니다.
굳이 다시 정리할 이유를 못 느껴서 그대로 옮겨 담습니다. 와우~ 짱!

원본 출처
http://jsguide.net/ver2/articles/frame.php?artnum=006

개 요

웹 환경에서 게시판 류의 프로그램을 만들 때 프로그래머를 가장 괴롭히는 문제는 아마도 게시판 목록을 보여줄 때 사용자가 입력한 길고 긴 제목을 적절히 잘라서 한 라인에 표시하는 문제일 것이다. 이러한 문제를 전통적인 방법이 아닌 스타일시트 기능을 이용하여 깔끔하고 간편하게 처리하는 방법에 대해서 알아본다.

왜 이런 기능이 필요한가?

아마도 게시판이나 방명록 등의 프로그램을 직접 만들어 본 사람들은 누구나 비슷한 경험을 가지고 있으리라 본다. 다음의 게시판 예시를 보자. 별다른 점이 보이지 않는가? 그렇다. 사실, 초창기 게시판들은 대개 이런 식이었다. 게시판에 글 제목을 아무리 길게 적더라도 몇라인에 걸치든지 무조건 다 보여주는 방식이다. 다음의 테이블에는 제목이 길어서 두 라인에 걸쳐서 표시된 게시물이 3건이 보인다. (참고로 소스도 함께 표시했으니 같이 비교해보면서 확인하기 바란다.)

<style type="text/css">
th,td { font-size: 9pt; line-height: 160%; }
</style>
<table width=500 border=1 cellspacing=0 cellpadding=2>
  <tr><th>No</th><th>Subject</th><th>Name</th><th>Date</th><th>Hit</th></tr>
  <tr>
    <td>5</td>
    <td>제목 길게 쓰면 누가 알아나 주나? 제발 좀 제목은 간단하게 쓰라구! 누가 본다고.. 쯧쯧</td>
    <td>짜증남</td>
    <td>2001.10.17</td>
    <td>2</td>
  </tr>
  <tr>
    <td>4</td>
    <td>짧게 좀 씁시다. 잘 안보이자나여.</td>
    <td>딴지남</td>
    <td>2001.10.17</td>
    <td>8</td>
  </tr>
  <tr>
    <td>3</td>
    <td>나도 길게 쓸래. 짧게 쓰면 뭔가 허전해서 말이쥐, 왜냐구? 내맘이지 모야!</td>
    <td>졸라맨</td>
    <td>2001.10.17</td>
    <td>19</td>
  </tr>
  <tr>
    <td>2</td>
    <td>이렇게 짧게 써도 되는데</td>
    <td>낙천맨</td>
    <td>2001.10.17</td>
    <td>7</td>
  </tr>
  <tr>
    <td>1</td>
    <td>꼭 이렇게 제목을 길게 써야지만 직성이 풀리는 유별난 사람들이 많은 모양이예요.</td>
    <td>순진녀</td>
    <td>2001.10.17</td>
    <td>26</td>
  </tr>
</table>

사실 본인 개인적인 입장으로서는, 이렇게 표시하는 것 또한 한가지 훌륭한 표시방식이라 생각하며, 이렇게 보인다 하더라도 하등의 문제가 없다고 생각한다. 그러나, 문제는 그렇게 생각하는 사람들이 그리 많지 않다는데 있다. 최근의 게시판 동향을 보면, 정해진 레이아웃에서 한 픽셀이라도 벗어나거나 글 내용에 따라 레이아웃이 깨지는 것을 몸서리 칠 정도로 거부하고 있다. 현재 많이 사용되는 유명 오픈소스 게시판과, 상용 커뮤니티 서비스에서의 게시판에서는 위와 같은 제목의 Word-Wrap을 허용하지 않는다. 긴 제목을 잘라버리는 한이 있더라도, 정해진 영역 이외에 표시되는 것을 두고 볼 수 없다는 입장이라는 얘기다.

전통적인 해결방법

그렇다면, 기존의 각종 게시판에서는 이러한 문제들을 어떻게 극복하고 있는가? 가장 쉽게 머리 속에 떠오르는 방법은 바로, 긴 문자열 자체를 일정 글자수 만큼 잘라내서, 이러한 현상이 발생하지 않도록 적당한 길이의 제목 만을 표시하는 방법일 것이다. 실제로 유명 게시판 소스에서는 이러한 방식을 사용하고 있다.

그러나, 이러한 방법을 구현하는 데에는 심각한 문제점이 몇가지 있다. 몇가지 나열해 보면 다음과 같다.

  • 가변폭 글꼴을 사용하는 경우, 정해진 너비에 해당하는 문자열 길이를 정확히 유추할 수 없다.
  • 한글이 포함된 제목의 경우, 단순한 바이트 단위의 잘라내기는 적합하지 않다.
  • 해당 기능을 위한 추가적인 프로그램 코딩과 서버 수행이 필요하다.

가변폭 글꼴

글꼴에는 크게 두가지 종류가 있다. 하나는 글자마다 그 폭이 달라지는 가변폭 글꼴과 모든 글자가 같은 폭을 갖는 고정폭 글꼴이다. 대부분의 트루타입 영문글꼴은 가변폭 글꼴이며, 시스템에서 사용하는 기본 글꼴(System, Terminal, FixedSys 등)과 한글글꼴 중 굴림체, 돋움체 등과 같이 "체" 자가 붙는 글꼴은 고정폭 글꼴이다. 아래의 예시는 가변폭과 고정폭 글꼴이 전체 문장의 너비에 어떠한 영향을 미치는지 가시적으로 보여주는 예시이다. 위의 문장은 가변폭 글꼴인 영문전용 글꼴(Arial)을 사용한 문장이고, 아래쪽은 고정폭 글꼴(돋움체)을 사용하여 표시한 것이다. 보이는 것과 같이, 똑같은 문자열이라도 사용된 글꼴과, 어떠한 내용이냐에 따라서 그 전체 너비가 달라질 수 있다.

Welcome to JavaScript Guide

Welcome to JavaScript Guide

이를 다르게 표현하자면, 정해진 너비에 몇글자가 들어갈 것인지를 미리 유추한다는 것은 매우 힘들다는 얘기가 되겠다. 따라서, 눈대중으로 이정도면 몇글자 정도 들어갈테니 대충 20글자 까지만 쓰도록 문자열을 잘라낸다고 하더라도, 가변폭 글꼴을 사용할 경우, 사용자가 꽤 넓은 폭을 가진 W 글자만으로 제목을 채운다면 자칫 넘어가 버릴 수도 있다는 뜻이다.

한글 제목

한글은 영문과는 달리, 한 글자를 나타내는데 2 Byte를 필요로 한다. 불행스럽게도 일반적인 프로그래밍 언어에서 기본적으로 제공하는 문자열 잘라내는 함수들은 이러한 한글의 특성을 배려해 주지 않는다. 따라서 무작정 이러한 함수들을 사용하여 정해진 바이트 단위로 잘라버리게 되면, 한글이 중간에 잘려서 엉뚱한 글자로 깨지는 현상을 접할 수 있다.

이러한 문제를 극복하기 위해서는, 잘라내는 처리를 할 대상 문자열 중에 한글이 포함된 경우, 한글의 경계를 파악하기 위해 일일히 문자열을 바이트 단위로 검사하여, 잘라낼 위치가 한글의 경계가 아닌 중간에 위치한 경우 그 경계를 피하여 잘라내도록 별도의 알고리즘을 적용하여 처리해야 한다. 이러한 처리과정이 뭐 그리 복잡한건 아니겠지만, 그렇다 하더라도 프로그래머 입장에서는 번거로운건 사실이다.

추가적인 프로그램 코딩과 서버 수행

어찌보면 "별것도 아닌" 효과를 위해 숱한 사람들이 지속적으로 들락날락 하는 게시판 같은 프로그램에서 이러한 처리과정을 일일히 적용하여 수행한다는 것은 추가적인 코드를 작성해서 기능연결을 해야 하는 프로그래머의 수고 뿐만 아니라 이러한 처리를 사용자가 게시판을 조회할 때마다 일일히 수행해야 하는 서버의 자원낭비도 무시할 순 없다. 사실, 조그만 개인 홈페이지나 기껏해야 동시 접속자 100명 안쪽의 소규모 게시판에서는 이러한 요소가 고려할 필요조차 없을지도 모른다. 하지만 대규모 사용자를 서비스하는 게시판의 경우에는 작은 성능 향상이 엄청난 효과를 발휘할 수도 있다.

스타일시트를 이용한 레이아웃 정의

스타일의 속성 중에는 overflow라는 속성이 있다. 이 속성은 정해진 영역 이상으로 포함된 내용이 많을 경우 그 내용 표시를 어떻게 처리할 것인지를 정하는 스타일 속성이다. 기본값은 auto이며, scroll, hidden 등으로 지정할 수 있다. scroll로 정의하면 내용이 많을 경우 스크롤바를 표시하여 처리한다는 의미이고, hidden으로 지정하면 영역을 벗어난 내용을 표시하지 않는다는 뜻이다. 이 기사에서는 바로 이 overflow라는 스타일을 이용하여 위에서 열거한 문제들을 해결하는 또다른 해법을 제시하고자 한다.

맨 처음에 봤던 그 테이블에서 제목란을 이제 너비 320 픽셀과 높이 18 픽셀로 고정시키려고 한다. 그리고 지정된 영역 이상으로 넘어가는 내용(Word-Wrap에 의해)을 화면 상에 표시하지 않기 위해서는 overflow:hidden 이라는 스타일 지정을 사용하여 처리하도록 한다. 그리고, Netscape에서는 display 속성을 block 또는 inline-block 으로 지정하지 않으면 이 효과를 확인할 수 없으므로 함께 추가한다.

<style type="text/css">
th,td { font-size: 9pt; line-height: 160%; }
.shorttitle { width: 320; height: 18; display: block; overflow: hidden; }
</style>
<table width=500 border=1 cellspacing=0 cellpadding=2>
  <tr><th>No</th><th width=320>Subject</th><th>Name</th><th>Date</th><th>Hit</th></tr>
  <tr>
    <td>5</td>
    <td>
      <span class=shorttitle>
        제목 길게 쓰면 누가 알아나 주나? 제발 좀 제목은 간단하게 쓰라구! 누가 본다고.. 쯧쯧
      </span>
    </td>
    <td>짜증남</td>
    <td>2001.10.17</td>
    <td>2</td>
  </tr>
  <tr>
    <td>4</td>
    <td>
      <span class=shorttitle>
        짧게 좀 씁시다. 잘 안보이자나여.
      </span>
    </td>
    <td>딴지남</td>
    <td>2001.10.17</td>
    <td>8</td>
  </tr>
  <tr>
    <td>3</td>
    <td>
      <span class=shorttitle>
        나도 길게 쓸래. 짧게 쓰면 뭔가 허전해서 말이쥐, 왜냐구? 내맘이지 모야!
      </span>
    </td>
    <td>졸라맨</td>
    <td>2001.10.17</td>
    <td>19</td>
  </tr>
  <tr>
    <td>2</td>
    <td>
      <span class=shorttitle>
        이렇게 짧게 써도 되는데
      </span>
    </td>
    <td>낙천맨</td>
    <td>2001.10.17</td>
    <td>7</td>
  </tr>
  <tr>
    <td>1</td>
    <td>
      <span class=shorttitle>
        꼭 이렇게 제목을 길게 써야지만 직성이 풀리는 유별난 사람들이 많은 모양이예요.
      </span>
    </td>
    <td>순진녀</td>
    <td>2001.10.17</td>
    <td>26</td>
  </tr>
</table>

생략 표기 (IE 전용)

제목의 표시는 원하는 만큼의 분량만 표시한다고 하더라도, 이것이 제목 전체가 아닌, 잘라진 문자열일 경우 원래 내용이 더 있다는 표시를 해야 할 필요가 있을 수 있다. 보통 이런 경우에는 해당 문자열 뒤에 "..." 을 표기하여 생략되었다는 의미를 나타낸다.

이러한 생략 표시를 위의 해법에 적용하기 위해서는 각각의 문자열이 원래 2라인인지 아닌지를 판단해야 한다. 그것을 알아내려면 해당 태그의 scrollHeight를 조사하면 판단할 수 있다. 이러한 내용을 적용하여 생략된 제목 뒤에 생략 표시를 나타내는 테이블은 다음과 같다.

<style type="text/css">
th,td { font-size: 9pt; line-height: 160%; }
.shorttitle { width: 300; height: 18; display: inline-block; overflow: hidden; }
</style>
<table width=500 border=1 cellspacing=0 cellpadding=2>
  <tr><th>No</th><th width=320>Subject</th><th>Name</th><th>Date</th><th>Hit</th></tr>
  <tr>
    <td>5</td>
    <td>
      <span id=line1 class=shorttitle>
        제목 길게 쓰면 누가 알아나 주나? 제발 좀 제목은 간단하게 쓰라구! 누가 본다고.. 쯧쯧
      </span>
      <span id=line1ellipsis style="height:18;display:none">...</span>
    </td>
    <td>짜증남</td>
    <td>2001.10.17</td>
    <td>2</td>
  </tr>
  <tr>
    <td>4</td>
    <td>
      <span id=line2 class=shorttitle>
        짧게 좀 씁시다. 잘 안보이자나여.
      </span>
      <span id=line2ellipsis style="height:18;display:none">...</span>
    </td>
    <td>딴지남</td>
    <td>2001.10.17</td>
    <td>8</td>
  </tr>
  <tr>
    <td>3</td>
    <td>
      <span id=line3 class=shorttitle>
        나도 길게 쓸래. 짧게 쓰면 뭔가 허전해서 말이쥐, 왜냐구? 내맘이지 모야!
      </span>
      <span id=line3ellipsis style="height:18;display:none">...</span>
    </td>
    <td>졸라맨</td>
    <td>2001.10.17</td>
    <td>19</td>
  </tr>
  <tr>
    <td>2</td>
    <td>
      <span id=line4 class=shorttitle>
        이렇게 짧게 써도 되는데
      </span>
      <span id=line4ellipsis style="height:18;display:none">...</span>
    </td>
    <td>낙천맨</td>
    <td>2001.10.17</td>
    <td>7</td>
  </tr>
  <tr>
    <td>1</td>
    <td>
      <span id=line5 class=shorttitle>
        꼭 이렇게 제목을 길게 써야지만 직성이 풀리는 유별난 사람들이 많은 모양이예요.
      </span>
      <span id=line5ellipsis style="height:18;display:none">...</span>
    </td>
    <td>순진녀</td>
    <td>2001.10.17</td>
    <td>26</td>
  </tr>
</table>
<script language="JavaScript">
function showEllipsis() {
  for (i = 1; i <= 5; i++) {
    if (eval("line"+i+".scrollHeight") >= 24) {
      ellipsis = eval("line" + i + "ellipsis");
      ellipsis.style.display = "inline-block";
    }
  }
}
showEllipsis();
</script>

간혹, 레이아웃이 로딩 중에 달라지도록 구성된 웹 페이지에서는 각 제목의 스타일 속성이 로딩이 완료되기 이전까지는 결정되지 않아서 생략표시를 처리하는 자바스크립트 함수가 제대로 동작하지 않을 수 있다. 이런 경우에는 이 함수의 실행을 BODY 태그의 onLoad에 이벤트 핸들러로 연결하거나, 적절한 실행 지연시간(setTimeout() 이용)을 지정하여 호출하면 해결할 수 있다.