재미있는 자바스크립트 01, TABLE 태그와 HTCs의 활용
본문은 사이트가 ASP 기반으로 운영되던 시기에 테스트 및 작성된 글로, 현재 본 사이트는 ASP.NET 기반으로 리뉴얼 된 상태다. 그에 따라, DTD 선언을 비롯한 대부분의 사이트 구조가 변경되었으며, 보편적으로 사용되는 인터넷 익스플로러의 버전이나 클라이언트 측 기술의 주요 흐름도 당시와는 많이 달라졌다. 그 결과 본문에서 다루고 있는 내용들 중 일부가 오동작을 일으키는데, 인터넷 익스플로러가 CSS를 렌더링하는 방식이 변한 것이 그 가장 큰 이유다. 결론적으로 본문에서는 오동작을 일으키는 일부 요소들의 문제만 해결하고, 원문 자체는 가급적 그대로 유지하고자 한다.
특히, 본문의 후반부에서 소개하고 있는 HTCs는 IE 10에서 지원이 중단되었으므로 참고하기 바란다.
많은 경우에, 조금 과장하면 거의 모든 종류의 웹 프로그래밍에 빠지지 않고 사용되는 것 중 하나가 바로 TABLE 태그로 구성된 표일 것이다. 지금 이 순간에도 전 세계의 웹 프로그래머들 중 상당수가 TABLE 태그를 사용해서 뭔가 만들어내고 있는 중이라고 얘기해도 큰 허풍은 아닐 것이다. 본문에서는 자바스크립트로 바로 이 TABLE 태그를 다뤄 볼텐데 필자도 본문에서 살펴보고자 하는 내용들이 실무에 얼마나 도움이 될런지는 모르겠다. 고백하건데 본문은 순전히 필자 자신의 프로그래머적인, 그리고 개인적인 재미를 위해서 작성된 글로 적용 대상 자체도 인터넷 익스플로러만을 감안한 글이다. 즉, 본문에서 논의되는 모든 자바스크립트 코드들은 파이어폭스로 대표되는 다른 웹 브라우저들에서는 동작을 보장하지 않는다.
다음은 TABLE 태그를 사용해서 작성한 평범한 형태의 표다. 웹 프로그래머라면 태그 사용법에 관한 취향 차이는 있을지언정 이런 TABLE 태그 구성에 어려움을 겪거나 곤란을 느끼시는 분들은 많지 않을 것이다. 아무튼 본문에서 표의 세부적인 형태는 그리 중요하게 다뤄지지 않으므로 그저 표가 하나 존재한다는 정도로만 생각하기 바란다.
Column 1 | Column 2 | Column 3 | Column 4 | Column 5 |
A1 | B1 | C1 | D1 | E1 |
A2 | B2 | C2 | D2 | E2 |
A3 | B3 | C3 | D3 | E3 |
A4 | B4 | C4 | D4 | E4 |
A5 | B5 | C5 | D5 | E5 |
A6 | B6 | C6 | D6 | E6 |
A7 | B7 | C7 | D7 | E7 |
실무에서 작업을 하다보면 종종 난감한 경우를 접하게 된다. 가령, 화면에 출력하고자 하는 데이터의 수량이 애매모호한 경우가 대표적인 경우인데, 페이징 처리를 구현하기에는 데이터가 너무 적어서 민망하고, 그렇다고 그대로 아무런 처리 없이 출력하자니 그러기에는 데이터가 조금 부담스러운 분량인 경우다. 이런 경우, 몇 년 전까지만 해도 IFRAME 태그를 하나 삽입하고 별도의 페이지에 TABLE 태그를 출력한 다음, 페이지를 IFRAME 태그에 연결해서 IFRAME 태그 자체의 스크롤바를 이용해서 처리하기도 했지만, 물리적으로 페이지를 하나 더 만들어야 된다는 번거러움과 부모 페이지와의 연동 불편 등을 이유로 최근에는 거의 사용되지 않고 있다. 대신 근래에는 케스케이딩 스타일시트(Cascading Sytle Sheet)로 비교적 간단히 처리하는 방식이 보편적으로 사용되고 있다. 이 방법을 사용하면 TABLE 태그의 출력 결과가 다음과 같이 렌더링된다.
Column 1 | Column 2 | Column 3 | Column 4 | Column 5 |
A1 | B1 | C1 | D1 | E1 |
A2 | B2 | C2 | D2 | E2 |
A3 | B3 | C3 | D3 | E3 |
A4 | B4 | C4 | D4 | E4 |
A5 | B5 | C5 | D5 | E5 |
A6 | B6 | C6 | D6 | E6 |
A7 | B7 | C7 | D7 | E7 |
무엇보다 렌더링 결과 자체가 매우 세련되었으며 개발자의 입장에서는 결과를 얻기 위해 필요한 노력이 다른 방법에 비해 매우 적다. 꽤나 매력적인 방법이라고 볼 수 있는데, 이런 결과를 얻기 위해서 개발자가 해줘야 할 일은 단지 DIV 태그를 하나 추가하고 style 속성에 적당한 값들을 채워넣는 것 뿐이다. 다음은 실제로 위와 같은 결과를 얻어내기 위해서 사용된 HTML 태그 코드 블럭의 전부다. (사이트 리뉴얼로 인해 일부 내용이 변경됐다.)
<div style="width: 400px; height: 89px; overflow-y: auto;">
... 여기에 기존의 TABLE 태그가 위치한다. ...
</div>
그러나, 상당히 만족스럽게 느껴지는 이 방법으로도 까다로운 고객들의 취향을 완벽하게 만족시켜주지는 못한다. 수 많은 고객들이 다양한 인터넷 경험을 바탕으로 요구사항의 수준을 높혀가고 있는 것이다. 불만의 구체적인 이유는 스크롤바를 위, 아래로 움직여보면 그리 어렵지 않게 알아차릴 수 있다. 바로, 스크롤바를 아래로 움직이면 표의 타이틀이 보이지 않는다는 점이 문제가 되는 것이다. 컬럼의 갯수가 많고 대부분의 컬럼들이 금액 관련 데이터를 담고 있는 경우, 타이틀이 보이지 않으면 사용자들은 어떤 컬럼이 어떤 데이터를 나타내는 것인지 매우 혼란스러울 수 밖에 없다. 개발자의 입장에서도 충분히 공감할 수 있는 이유이기는 하다. 그래서, 어떤 개발자가 그야말로 참신한 아이디어를 내놓았다. 먼저 다음의 표를 살펴보자. 일견하기엔 기존의 표와 그다지 다른 부분이 없는 것처럼 보일지도 모르겠지만 스크롤바를 위, 아래로 움직여보면 아이디어의 참신함을 깨닫게 될 것이다.
Column 1 | Column 2 | Column 3 | Column 4 | Column 5 |
Column 1 | Column 2 | Column 3 | Column 4 | Column 5 |
A1 | B1 | C1 | D1 | E1 |
A2 | B2 | C2 | D2 | E2 |
A3 | B3 | C3 | D3 | E3 |
A4 | B4 | C4 | D4 | E4 |
A5 | B5 | C5 | D5 | E5 |
A6 | B6 | C6 | D6 | E6 |
A7 | B7 | C7 | D7 | E7 |
기본적인 구현 원리 자체는 매우 간단하다. 즉, TABLE 태그를 하나 더 추가해서 원본 표의 타이틀 부분만을 그대로 복사하고 동일한 크기와 모양으로 구성한다. 그리고, 케스케이딩 스타일시트를 적절히 사용해서 복사본에 해당하는 표, 즉 타이틀만 존재하는 TABLE 태그가 위에 위치하도록 동일한 좌표에 두 표가 정확하게 겹치도록 구성해놓고 스크롤바가 이동할 때마다 자바스크립트로 스크롤바가 이동한 좌표만큼씩만 복사본 표의 위치를 조절해주는 것이다. 그러면, 지금부터 이 작업을 한 단계씩 따라해보도록 하겠다. 단순하게 스크롤바가 추가된 상태에서부터 다시 시작해보자. 표의 본래 모습은 다음과 같았으며 이미 알고 있는 것처럼 현재 상태에서는 스크롤바를 위, 아래로 움직이면 타이틀이 여지없이 가려져버린다.
Column 1 | Column 2 | Column 3 | Column 4 | Column 5 |
A1 | B1 | C1 | D1 | E1 |
A2 | B2 | C2 | D2 | E2 |
A3 | B3 | C3 | D3 | E3 |
A4 | B4 | C4 | D4 | E4 |
A5 | B5 | C5 | D5 | E5 |
A6 | B6 | C6 | D6 | E6 |
A7 | B7 | C7 | D7 | E7 |
이제 원본 표의 타이틀 부분만 복사한 새 TABLE 태그를 생성해서 DIV 태그 안에 추가한다. 단지 TABLE 태그를 하나 추가하기만 한 상태이므로 다음과 같이 두 개의 타이틀이 존재하는 것처럼 보일 것이다. 자, 지금부터 진짜 재미있는 부분이 본격적으로 시작된다.
Column 1 | Column 2 | Column 3 | Column 4 | Column 5 |
Column 1 | Column 2 | Column 3 | Column 4 | Column 5 |
A1 | B1 | C1 | D1 | E1 |
A2 | B2 | C2 | D2 | E2 |
A3 | B3 | C3 | D3 | E3 |
A4 | B4 | C4 | D4 | E4 |
A5 | B5 | C5 | D5 | E5 |
A6 | B6 | C6 | D6 | E6 |
A7 | B7 | C7 | D7 | E7 |
다음으로 케스케이딩 스타일시트를 설정해서 타이틀 부분만 존재하는 복사본 표를 원본 표의 타이틀 부분과 정확하게 겹쳐지도록 조정해야 한다. 본문에서는 케스케이딩 스타일시트에 관해서는 깊게 설명하지 않을 것이므로 케스케이딩 스타일시트에 대한 궁금증은 관련 서적이나 기타 문서들을 참고하기 바란다. 복사본 표의 TABLE 태그에 다음과 같이 style 속성을 추가하고 값을 적절히 설정해주면 된다. 이 설정은 해당 TABLE 태그의 좌표 체계를 절대 좌표로 바꾸고 Z 축을 원본 표보다 위로 설정한 것이다. top과 left의 좌표값을 모두 0으로 설정한다고 해서 태그가 무조건 전체 페이지 좌상단을 기준으로 이동하는 것은 아니라는 점에 유의하도록 한다.
<table ... style="position: absolute; left: 0px; top: 0px; z-index: 10;">
<!--
위의 태그는 사이트 리뉴얼 이후, DTD 변경 등의 영향을 받아 다음과 같이 변경되었다.
다만, 본문의 설명은 본문이 작성되던 당시를 기준으로 한다
-->
<div ... style="...position:relative;">
<table ... style="text-align:center;margin:0px;position:absolute;z-index:10;">
이 설정으로 인해서 다음과 같은 결과가 얻어진다. 겉보기에는 다시 원래대로 돌아온 것처럼 보이겠지만, 실은 타이틀 부분이 두 겹으로 겹쳐 있는 상태라는 사실을 명심하도록 하자. 시험삼아 스크롤바를 위, 아래로 움직여보면 여전히 타이틀이 가려지기는 하지만 실망하기는 너무 이르다. 아직 그 어떤 자바스크립트 코드도 작성하지 않았다는 점을 기억하기 바란다.
Column 1 | Column 2 | Column 3 | Column 4 | Column 5 |
Column 1 | Column 2 | Column 3 | Column 4 | Column 5 |
A1 | B1 | C1 | D1 | E1 |
A2 | B2 | C2 | D2 | E2 |
A3 | B3 | C3 | D3 | E3 |
A4 | B4 | C4 | D4 | E4 |
A5 | B5 | C5 | D5 | E5 |
A6 | B6 | C6 | D6 | E6 |
A7 | B7 | C7 | D7 | E7 |
이제 자바스크립트에서 사용할 id 속성을 설정해보자. 가장 바깥 쪽에 위치한 DIV 태그에 SAMPLE_DIV라는 id 값을, 그리고 복사본 표, 즉 타이틀만 존재하는 표의 TABLE 태그에 SAMPLE_TABLE이라는 id 값을 설정한다. 결과적으로 다음과 비슷한 형태의 태그가 구성될 것이다.
<div id="SAMPLE_DIV" style="width: 400px; height: 89px; overflow-y: auto;">
<table id="SAMPLE_TABLE" ... >
이제 준비가 거의 끝났다. 그저 적당한 이벤트 헨들러에 자바스크립트 함수를 작성해서 설정해주기만 하면 된다. 자주 사용하지 않는 이벤트 중에 onScroll이라는 이벤트가 있는데, 그 이름 그대로 스크롤바가 이동할 때마다 발생하는 이벤트다. 정확하게 우리가 필요로 하는 이벤트인 셈인데 onScroll 이벤트에 관한 자세한 정보는 다음 MSDN 문서를 참고하기 바란다.
이번에는 자바스크립트 함수를 작성해야 하는데, 직접 코딩에 들어가기 전에 어떤 작업을 처리해줘야 할지 잠시 생각해보도록 하자. 현재 문제의 핵심은 스크롤바가 아래쪽으로 x 만큼 이동하면, 상대적으로 표는 -x 만큼, 즉 절대값 x 만큼 위로 이동한다는 점이다. 결국, 복사본 표의 위치를 스크롤바가 이동한 위치와 똑같이 x 만큼 아래쪽으로 조정해주면 마치 타이틀이 제자리에 고정되어 있는 것처럼 보이게 된다. 이 작업을 처리하는 자바스크립트 함수는 정말 깜짝 놀랄만큼 단순하기 그지 없다.
<script language="JavaScript" type="text/javascript">
<!--
function SetScrollPos_Sample(tagDIV)
{
var positionTop = 0;
if (tagDIV != null)
{
positionTop = parseInt(tagDIV.scrollTop, 10);
document.getElementById("SAMPLE_TABLE").style.top = positionTop + "px";
}
}
//-->
</script>
이 자바스크립트 함수는 그다지 난해한 부분이 존재하지 않으므로 별로 어렵지 않게 이해가 될 것이다. 이 함수에는 tagDIV라는 이름으로 인자가 하나 넘어온다. tagDIV 인자는 DIV 태그 자체에 대한 참조를 갖고 있는 Object 개체 변수로, 나중에 보면 알겠지만 onScroll 이벤트에서 this 키워드로 넘어온다. 그리고, positionTop이라는 변수에 DIV 태그의 scrollTop 프로퍼티 값을 10진수로 파싱한 값을 담고 있는데, 바로 이 값이 스크롤바가 아래로 이동한 거리이다. scrollTop 프로퍼티는 IHTMLElement2 인터페이스에 정의되어 있으며 다음의 문서에서 보다 상세한 정보를 살펴볼 수 있다.
결국, 이 자바스크립트 함수가 처리해주는 작업은 스크롤바가 이동한 만큼 복사본 표의 위치를 조정해주는 것 뿐이다. 그리고, 코드도 언제나 일상적으로 사용하던 코드와 별반 다른 점이 없다. 마지막으로 이 함수를 적당한 위치에 선언해주고, 다음과 같이 DIV 태그의 onScroll 이벤트 헨들러로 지정해주면 관련된 작업들이 마무리 된다. 자바스크립트 함수에 인자로 this를 넘기는 부분에 주의하기 바란다.
<div id="SAMPLE_DIV" ... onScroll="SetScrollPos_Sample(this);">
다음 표는 지금까지 작업한 과정의 최종 결과물이다. 여러분들은 어떨지 모르겠지만 필자 개인적으로는 매우 만족스러운 결과라고 느껴진다. 그리고, 조금만 더 아이디어의 범위를 넓혀보면 세로축뿐만 아니라 가로축에 대해서도 동일한 작업을 할 수 있다는 점을 알 수 있다.
Column 1 | Column 2 | Column 3 | Column 4 | Column 5 |
Column 1 | Column 2 | Column 3 | Column 4 | Column 5 |
A1 | B1 | C1 | D1 | E1 |
A2 | B2 | C2 | D2 | E2 |
A3 | B3 | C3 | D3 | E3 |
A4 | B4 | C4 | D4 | E4 |
A5 | B5 | C5 | D5 | E5 |
A6 | B6 | C6 | D6 | E6 |
A7 | B7 | C7 | D7 | E7 |
다만, 같은 작업을 가로축에 대해서 구현하려면 몇 가지 고려가 더 필요하다. 우선, 대부분의 경우 표에 몇 개의 행이 존재할지 미리 알 수 없다는 점을 감안해야 한다. 그리고, 조금만 더 깊게 생각해보면 가장 좌측열에 출력되는 실제 내용들이 매번 달라지게 된다는 점도 알 수 있을 것이다. 따라서, 복사본 표를 만드는 작업이 더 어려워지는 것은 물론이다. 그리고, 한 가지 더 짚어봐만 할 부분은 이런 기능들을 구현하는 방법에는 지금 소개한 방법 외에도 다른 다양한 방법들이 존재한다는 점이다. 단적으로 말해서 필자가 추가로 알고 있는 방법만도 벌써 두 가지 정도 다른 방법들이 존재한다. 그러므로, 여러분의 상상력을 미리 제한하지는 말기 바란다.
만약, 필자가 본문을 여기에서 끝내버린다면 여러분은 자바스크립트의 재미를 절반 정도 밖에 경험해보지 못할 것이다. 아주 조금만 더 얘기를 진행해보도록 하자. 지금까지 살펴본 작업 자체도 그리 난해하다고 평하기는 어려운 것들이다. 다만 단호하게 말해서 조금 번거로운 작업임은 부정하지는 못한다. 게다가, 한창 프로젝트가 진행 중일 때라면 같은 코드를 몇 번이고 반복해서 작성해야만 할 것이다. 개발자라면 정말 원하지 않는 종류의 작업이다. 그렇다면 뭔가 개선의 여지는 없을까? 다행스럽게도 이런 현실을 개선할 수 있는 방법이 존재한다. 그것도 아주 강력한 방법으로. 이번에는 지금까지의 작업들을 HTCs(HTML Components)로 구현해보도록 하겠다. 다만, 본문에서는 HTCs가 무엇인지, 어떻게 구현하는 것인지 같은 근본적인 부분들에 대해서는 다루지 않을 것이다. 이런 부분들에 대해서는 이어질 다음 글에서 논의할 예정이며 본문에서는 일단 그 강력함을 느껴보는 일에만 집중하도록 한다.
다음 표를 살펴보도록 하자. 지금까지 설명한 내용들의 결과와 조금도 틀리지 않다는 것을 알 수 있을 것이다. 그러나, 놀랍게도 그 내부가 지금까지와는 전혀 다른 방식으로 구현되어 있다.
다시 한 번 강조하지만 HTCs는 IE 10에서 지원이 중단되었다. 따라서, IE 10 이상을 사용하는 분들은 HTCs를 테스트해보려면, F12 개발자 도구에서 문서 모드를 IE9 표준으로 변경해야 한다.
Column 1 | Column 2 | Column 3 | Column 4 | Column 5 |
A1 | B1 | C1 | D1 | E1 |
A2 | B2 | C2 | D2 | E2 |
A3 | B3 | C3 | D3 | E3 |
A4 | B4 | C4 | D4 | E4 |
A5 | B5 | C5 | D5 | E5 |
A6 | B6 | C6 | D6 | E6 |
A7 | B7 | C7 | D7 | E7 |
본문의 소스를 살펴보면 알 수 있지만 명시적으로 추가된 DIV 태그도 없고, 복사본 표를 구성하는 TABLE 태그도 없다. 심지어 onScroll 이벤트를 처리해주는 자바스크립트 함수도 없다. 물론, 내부적으로는 이런 요소들이 어딘가 존재하지만 일단 겉보기에는 다음의 한 문장이 지금까지 우리가 논의해왔던 그 모든 작업들을 일괄로 처리해버린다. 너무나 간단해서 지금까지 살펴본 많은 얘기들이 허탈하게 느껴질 지경이다.
<table id="HTC_SAMPLE_TABLE" ... style=" ... behavior:url(/Content/HTC/TableScroll.htc);">
이미 눈치채신 분들도 계실테고, 어떤 면에서는 당연한 얘기겠지만 지금까지 본문에서 논의했던 그 모든 작업들은 바로 저 TableScroll.htc 라는 파일 내부에 구현되어 있다. 어떤분은 이렇게 반문을 할 지도 모른다. "그렇다면 작업분량이 줄어드는 것이 아니지 않은가? 게다가 이 방식으로는 구현이 더 어려워질텐데 또 잠깐동안 유행처럼 번지다가 사라질 기술이 아닌가?" 필자도 그 지적에는 일부 동의한다. HTCs는 인터넷 익스플로러 스크립팅 개체들에 관해서 어느 정도 이상의 지식을 갖고 있지 않다면 효과적으로 사용하기가 쉽지 않다. 아직까지 위의 사례에 사용된 HTCs 파일의 소스를 보여드리지는 않았지만 구현 내용을 살펴보면 약간의 테크닉을 필요로 한다는 사실을 알 수 있을 것이다. 가령, DIV 태그나 복사본 TABLE 태그를 동적으로 생성해서 목적에 맞게 조합하고 수정한다던가 하는 등의 작업이 구현되어 있는데 초급 개발자에게는 약간 버거운 작업이라고 생각한다. 그러나, 바로 그런 이유 때문에 팀 단위 작업에서는 HTCs가 보다 놀라운 힘을 발휘하게 된다. 즉, 전문 자바스크립트 개발자나 선임급의 개발자가 전담해서 HTCs를 작성하고 나머지 팀원들은 그냥 적당한 케스케이딩 스타일시트를 구성하기만 하면 되므로, 코드 재사용이 용이해지고 HTML 코드가 극적으로 심플해지는 것이다. 그런데, 이런 얘기들을 어디선가 많이 들어봤다고 느껴지지는 않는지? 그렇다. 많은 서적들이 COM 컴포넌트나 클래스의 재사용성에 관해서 이와 비슷한 설명을 하고 있다. 결국 HTCs의 기본 목적도 동일하다고 할 수 있는데, 재사용 그리고 간결한 결과물과 쉬운 유지보수가 바로 그것이다.
다음 두 파일이 바로 이번 예제에서 사용된 HTCs 파일들이다. 두 개의 파일이 내부적으로 모두 사용되므로 모두 다운로드 받아서 각자 살펴보기 바란다. 개선해야 할 여지가 많은 코드이긴 하지만 HTCs가 대략 어떠한 형태로 구성되는지를 살펴보기에는 충분할 것이라고 생각한다. 테이블의 폭이나 높이를 인자로 전달받아 적용하거나 타이틀에 해당하는 TR 태그의 갯수를 가변적으로 설정하는 등 여러 가지 확장을 생각해볼 수 있을 것이다. 각자 이러한 기능들을 직접 구현해보기 바란다. 필자 스스로도 만들어 놓고서는 마음에 들지 않아서 투덜대고 있는 코드들이므로 마음놓고 여러분이 원하는 대로 바꿔버려도 좋다.
TableScroll.htc (2.27k), AttachScrollEH.htc (0.6k)
이처럼 특정 작업을 처리하는 HTCs 파일이 일단 하나 작성되고 나면, 그 다음부터는 해당 기능을 필요로 하는 HTML 태그에 적절한 케스케이딩 스타일시트를 설정해주기만 하면 똑같은 코드를 여러 차례 반복할 필요 없이 모든 작업이 끝난다. 따라서 HTCs 파일에 자바스크립트로 구현된 프로그램의 완성도가 높으면 높을수록 다양한 패턴에 대응이 가능해지며, 해당 HTCs 파일 하나만 수정하면 그 결과가 모든 부분에 반영된다. 게다가 몇 번이고 반복해서 사용할 수 있다. 마치 다음과 같이 말이다.
Column 1 | Column 2 | Column 3 | Column 4 | Column 5 |
A1 | B1 | C1 | D1 | E1 |
A2 | B2 | C2 | D2 | E2 |
A3 | B3 | C3 | D3 | E3 |
A4 | B4 | C4 | D4 | E4 |
A5 | B5 | C5 | D5 | E5 |
A6 | B6 | C6 | D6 | E6 |
A7 | B7 | C7 | D7 | E7 |
Column 1 | Column 2 | Column 3 | Column 4 |
A1 | B1 | C1 | D1 |
A2 | B2 | C2 | D2 |
A3 | B3 | C3 | D3 |
A4 | B4 | C4 | D4 |
A5 | B5 | C5 | D5 |
A6 | B6 | C6 | D6 |
A7 | B7 | C7 | D7 |
Column 1 | Column 2 | Column 3 | Column 4 | Column 5 |
A1 + A2 | B1 | C1 | D1 | E1 |
B2 | C2 | D2 | E2 | |
A3 + A4 | B3 | C3 | D3 | E3 |
B4 | C4 | D4 | E4 | |
A5 + A6 | B5 | C5 | D5 | E5 |
B6 | C6 | D6 | E6 |
그러나, 안타깝게도 HTCs가 모든 웹 브라우저에서 지원되는 것은 아니므로 도입 여부는 신중히 결정되야 한다. 우선 HTCs는 인터넷 익스플로러 5.5에서 처음 도입된 기술이다. 따라서, 인터넷 익스플로러에서도 그 이전 버전에서는 사용이 불가능하다. 다만, 기업체 내부와 같이 제한된 구성원들에게만 서비스를 제공하는 웹 기반의 시스템에서라면 제법 매력적인 모습으로 다가올 수 있을 것이다. 그리고, HTCs가 아직 널리 알려진 기술은 아니어서 처음 접하는 개발자들이 참고할 만한 사례나 레퍼런스가 많이 부족한 편이라는 점도 아쉽다. 필자의 경우 HTCs를 처음 접하게 된 계기는 Taeyo's ASP & ASP.NET 사이트로 유명한 김태영님의 코드를 통해서였는데 개인적으로 그 편의성에 놀라 감탄했던 기억을 갖고 있다. 덕분에 필자는 고품질의 코드 샘플을 직접 눈으로 살펴보면서 천천히 HTCs를 검토해볼 수 있는 기회를 누릴 수 있었다.
그러나, 필자의 이런 빈약한 설명들만으로는 여러분에게 HTCs에 대한 강렬한 인상을 심어주기에는 많이 부족하다고 느껴진다. 그래서, 실무에 HTCs가 사용된 사례를 몇 가지 소개하도록 하겠다. 그 첫 번째 사례는 약간 놀라실지도 모르겠지만 MSDN 라이브러리, 그 자체다. 영문 MSDN 라이브러리에 접속해보면 이제는 많이 친숙해진 좌측의 트리뷰를 볼 수 있을 것이다. 놀랍게도 이 트리뷰 전체가 바로 HTCs이다. 트리뷰를 담고 있는 프레임에서 소스 보기를 해보면 썰렁할 정도로 허전한 HTML 소스를 볼 수 있는데, 그저 다음과 같이 간단하기 그지없는 네 줄의 태그가 BODY 태그의 내부에 존재하는 태그들의 전부다. 결과물의 대단함에 비교해 볼 때 말 그대로 허탈할 지경이다.
<nobr>
<div id="deeptree" class="deeptree" CfgXMLSrc="/library/deeptreeconfig.xml">
</div>
</nobr>
일견 이 HTML 소스에서는 그 어디서도 HTCs와 관련된 단어나 문장을 찾아볼 수 없는 것처럼 보인다. 그러나, 소스를 잘 살펴보면 DIV 태그의 class 속성이 deeptree라는 값으로 설정되어 있는 것을 발견할 수 있다. 그렇다. 바로 케스케이딩 스타일시트를 사용해서 HTCs를 설정하고 있는 것이다. 동일 페이지의 LINK 태그를 추적해서 케스케이딩 스타일시트 파일을 다운로드 받아서 그 내용을 열어보면 다음과 같은 스타일 정의를 확인할 수 있다.
.deeptree
{
padding:4px 5px;
behavior:url(/library/shared/deeptree/htc/deeptree.htc);
}
그렇다. 결론적으로 MSDN 라이브러리의 좌측 트리뷰는 그 전체가 HTCs로 구성된 것이다. 이 HTCs 파일을 다운로드해서 소스를 살펴보면 내부적으로 Microsoft.XMLDOM과 MSXML2.XMLHTTP를 사용해서 코드의 중요한 부분들을 구현하고 있다는 것을 알 수 있다. 이처럼 하루에도 수 많은 개발자들이 빈번하게 방문하는 MSDN 라이브러리에서 그 핵심 부분에 HTCs를 사용하고 있다는 사실은 여러분이 HTCs를 선택하고자 결심할 때 중요한 판단 기준이 되리라고 믿는다. 또 다른 사례를 살펴보도록 하자.
개인적으로 필자가 생각하는, HTCs의 기능을 그야말로 극대화시킬 수 있는 또 하나의 용도는, ASP.NET 사용자 정의 서버 컨트롤, 또는 사용자 지정 서버 컨트롤을 작성하는 경우다. 한편으로 생각해보면 너무나 당연한 것이 ASP.NET 서버 컨트롤이 아무리 잘 작성됐다고 하더라도 웹 브라우저에서 보다 다이나믹하게 실행되기 위해서는 결국 자바스크립트 코드가 개입되야 한다. 그런데, 문제는 기존의 .js 파일만으로는 배포와 적용에 있어, 가령 이벤트 헨들러를 설정해주는 부분과 같은 면에서 약간의 아쉬움이 남는다는 점이다. 물론, 이 부분은 어느 정도 개인의 성향이 반영될 수 있는 부분이라는 점에는 동의한다. 게다가 인터넷 익스플로러의 하위 버전과 다른 웹 브라우저를 감안하는 경우에는 HTCs가 그다지 좋은 선택이 아니라는 점도 명확하게 짚고 넘어가기로 하겠다. 그러나, 본문의 주제는 HTCs의 활용 사례를 소개하는 것이므로 현실적인 이 문제에 대한 결정은 여러분 각자에게 넘기기로 한다.
이미 알고 있는 분들도 많이 계시겠지만 MSDN에서 무료로 소스 코드를 다운로드를 받아서 컴파일하여 사용 가능한 ASP.NET 서버 컨트롤 중에, Microsoft® Internet Explorer WebControls라는 것이 있다. 이 컨트롤들이 제공된지는 상당히 오래됐는데 .NET 프레임워크 1.0을 기준으로 작성된 컨트롤들이기는 하지만 사용에 별다른 문제가 없고 꽤나 유용한 기능들을 제공하기 때문에 실무에서도 종종 사용되는 것으로 알고 있다. 가령, 탭 기능을 구현해주는 TabStrip 컨트롤이나 TreeView 컨트롤처럼 재미있는 컨트롤들이 제공되는데 다음 URL에서 다운로드 받을 수 있으므로 참고하기 바란다.
다운로드 받은 파일을 설치하면 바로 컨트롤들이 설치되는 것이 아니라 소스 코드들이 설치되는데, 컨트롤들을 사용하려면 먼저 메뉴얼에 따라 이 소스 코드들을 컴파일하고 몇 가지 설정을 해줘야 한다. 그러나, 지금은 컨트롤 자체에 관심을 갖기 보다는 ASP.NET 서버 컨트롤에서 적용된 HTCs의 적용 실례를 살펴봐야 하므로 소스 코드들이 어떤 방식으로 구성되어 있는지만 살펴보기로 하자. 기본값으로 해당 파일들은 C:\Program Files\IE Web Controls 폴더에 설치된다. 그리고, 그 하위를 살펴보면 \src\Runtime 폴더에 몇 개의 HTCs 파일들이 존재하는 것을 볼 수 있다. 그 중, 파일 크기가 가장 큰 treeview.htc의 자바스크립트 코드는 약 4,000 라인에 달한다. 그야말로 어마어마한 자바스크립트 코딩량에 먼저 놀라고, 문제 없이 모든 기능들이 동작하는 것을 직접 보면서 또 한번 놀라게 된다. 그리고, 중요한 점은 .js 파일은 관련된 폴더 그 어디에도, 단 하나도 존재하지 않는다는 사실이다. 이처럼 HTCs는 ASP.NET 서버 컨트롤의 클라이언트 측 기능을 효과적으로 구현하기 위해 선택할 수 있는 또 하나의 적절한 장소다.
이제 마지막으로 마이크로소프트에서 제시하고 있는 수 많은 HTCs 관련 샘들 중에서 흥미로운 몇 가지를 살펴보도록 하자. 아마 상당히 재미있기도 하고 또 한편으로는 놀랍기도 할 것이다. 그리고, 또 한 가지 주의해서 살펴봐야 될 부분은 해당 샘플들이 릴리즈된 날짜들이다. 과연 국내 웹 개발자들이 얼마나 마이크로소프트의 트렌드를 따라가고 있는지, 혹은 그렇지 못한지 스스로 생각해보는 시간이 될 것이다. 다음은 Dave Massy라는 마이크로소프트의 에반젤리스트가 2001년 7월 24일, DHTML Dude라는 컬럼에 기고한 내용이다. 필자는 이 문서를 처음 봤을 때 그 충격을 말로 다 설명할 수가 없을 정도였다.
모두 세 가지 간단한 HTCs 프로그램을 소개하고 있는데, 그 첫 번째는 Highlighter로 마우스 커서의 이동에 따라 TABLE의 로우, 즉 TR 태그들의 색상이 반전된다. 또한, 마우스로 특정 로우를 클릭하면 그 로우가 선택되면서 특정 색상으로 반전된다. 물론, 이런 수준의 기능은 일반적인 자바스크립트 기술만으로도 무난히 구현이 가능하다. 그러나, 다시 한 번 강조하고 싶은 것은 적용이 매우 간단하고 프로젝트 단위의 팀 개발에서 전원이 비교적 동일한 수준의 퀄리티를 큰 노력 없이도 보장받을 수 있다는 점이다. 아무튼 Highlighter 의 실제 동작을 확인해보려면 다음의 링크를 클릭해보기 바란다. 그리고, 이 HTCs와 관련된 저작권 및 기타 권리는 모두 마이크로소프트에 있으며 필자는 단지 편의를 위해서 링크만 제공하는 것이라는 점을 다시 한 번 명시하고자 한다.
이건 그저 가벼운 몸풀기에 지나지 않는다. 두 번째 HTCs는 Sorter라는 것으로, 포스트백이나 서브밋 없이 TABLE 태그의 내용들이 선택한 컬럼, 즉 TD 태그를 기준으로 실시간 정렬된다! 또 다시 강조하지만 이 HTCs들은 2001년도에 작성된 코드라는 점을 감안하고 내용을 살펴보기 바란다. 이런 점들을 고려해볼 때 그야말로 놀랍기만 하다는 것이 필자의 솔직한 심정이다. 샘플 페이지를 열어서 마우스로 TABLE 태그의 헤더들을 클릭해보기 바란다.
마지막 세 번째 HTCs는 더 놀랍다. 바로 Drag라는 것인데, 이름 그대로 TABLE 태그의 헤더 컬럼들을 드래그 & 드롭해서 컬럼들의 순서를 재지정 할 수 있다. 이 정도면 기능을 약간 추가하는 것만으로도 윈도우즈 응용 프로그램의 그리드 컨트롤과 비슷한 수준으로까지 퀄리티를 끌어올리는 것도 불가능하지 않을 것 같다. 너무 과대평가하는 것이 아니냐고 반문할지도 모르겠지만 마지막 샘플을 보고나면 대부분 필자의 생각에 어느 정도는 동의하시리라고 믿는다.
가장 놀라운 마지막 샘플은 지금까지 설명한 세 개의 HTCs를 동시에 적용하고 있다. 게다가 그 방법도 단순하기 그지없다. 그저 앞에서 살펴본 세 가지 HTCs를 동시에 설정하는 것만으로 모든 작업이 마무리 된다. 즉, 일반 개발자는 다음과 같은 케스케이딩 스타일시트 설정만으로 모든 작업이 끝나는 것이다.
<table ... style="behavior:url(dragdrop.htc) url(tablehl.htc) url(sort.htc);">
이런저런 설명보다는 역시 직접 눈으로 살펴보는 편이 더 이해가 빠를 것이다. 다음 링크를 살펴보기 바란다. HTCs의 강력함을 피부로 느낄 수 있을 것이다.
물론, 이 세 가지의 HTCs를 하나로 구현할 수도 있으며 실제로 해당 문서의 마지막 부분에서는 그렇게 구현한 샘플을 제시하고 있다. 그러나, 필자가 강조하고자 하는 진짜 중요한 부분은 이런 기능들 자체가 아니라는 점을 이해하기 바란다. 이렇게 HTCs로 구현이 가능하다는 말은 일반적인 자바스크립트 코드만으로도 얼마든지 동일한 기능의 구현이 가능하다는 것을 의미한다. 그럼에도 불구하고 HTCs는 이벤트 헨들러 설정과 재사용성면에서 일반적인 자바스크립트를 사용하는 경우보다 월등히 뛰어나기 때문에 비로소 그 가치가 돋보인다는 것이다. 만약, 위의 세 HTCs를 일반적인 자바스크립트 코드로 구현했다면 작업의 대상이 되는 TABLE 태그에는 꽤나 많은 양의 이벤트 헨들러가 지정되었을 것이다. 또한, 중구난방으로 여기 저기에 코드가 널려있을 터이기 때문에 프로젝트 팀원 개개인의 스킬에 따라 매번 상당한 퀄리티의 차이가 나타나게 된다. 그러나, 앞에서 본 것처럼 HTCs를 사용했기 때문에 style 속성에 약간의 설정을 해주는 것만으로도 모든 작업이 끝나고 결과적으로 누가 작업을 하던지 편차 없는 동일한 퀄리티의 결과물을 얻을 수 있다.
마지막으로 한 가지 사례만 더 살펴보고 본문을 마무리하도록 하겠다. 아마도 여러분 중에 리모트 스트립팅(Remote Scripting)이라는 기술을 알고 계신 분들이 적지 않으실 것으로 생각된다. 리모트 스크립팅은 한 때 상당한 기대를 모았던 기술이었지만 언제부턴가 시들해져서 지금은 그다지 사용되지 않고 있다. 이 기술을 잠시 간단하게 설명하고 넘어가면 페이지를 새로 고침하지 않고도 서버로부터 필요한 정보들을 가져와서 DHTML적인 기법을 활용해서 현재 페이지의 일부, 또는 다수의 부분을 갱신할 수 있게 해주는 기술이다. 생각하기에 따라 활용 가능성이 무궁무진한 기술로 서버 측 비주얼 베이직 스크립트 클래스와 클라이언트 웹 브라우저 측 경량 애플릿 조합으로 동작한다. 마이크로소프트에서는 이 리모트 스크립팅의 최신 버전이라고 할 만한 기술을 WebService Behavior라는 이름으로 제공해주고 있다. 물론 그 기본적인 목적과 활용면에서는 리모트 스크립팅과 그다지 다를 바가 없으나 그 세부 구현에 있어서는 많은 부분들이 변화되었다.
먼저 서버 측 비주얼 베이직 스크립트 클래스가 웹 서비스로 대체됐으며, 그에 대응하는 클라이언트 웹 브라우저 측의 경량 애플릿도 내부적으로 Microsoft.XMLDOM과 MSXML2.XMLHTTP를 사용하여 구현된 HTCs로 대체되었다. 실제로 이 기술을 사용하려면 WebService.htc를 다운로드 받아서 개발하려는 웹 서버에 복사해야 한다. 이 파일에는 자바스크립트로 작성된 2,300여 라인 가량의 코드가 구현되어 있으며 SOAP 프로토콜을 사용해서 리퀘스트를 전송하고 그 결과를 받아오는 등의 처리들이 그 핵심적인 내용이다. 만약, 이런 코드를 프로젝트 팀원들 각자에게 그 때마다 작성해서 사용하라고 한다면 그 결과를 장담하기가 매우 힘들 것이다. 그러나, HTCs를 사용하기 때문에 그런 문제점들이 수월하게 해소된다. 만약, 본문을 읽고 처음으로 리모트 스트립팅이나 WebService Behavior 류의 프로그래밍 기법을 접하게 되었으며 다소라도 흥미를 느꼈다면 참고로 다음 자료를 다운로드 받아서 천천히 살펴보기 바란다.
이 자료는 김태영님이 작년 12월 경 ASP.NET 2.0 관련 MSDN 세미나의 발표 자료 중 일부로 작성한 문서인데, 프리젠테이션 문서와 약간의 소스 코드를 같이 포함하고 있어서 처음 접하시는 분들께는 간략한 개요와 앞으로의 전망 등을 부담없이 살펴볼 수 있는 좋은 참고 자료가 될 것이다. 특히 ASP.NET 2.0에서의 관련 기법의 변화 등과 같은 부분은 미리 한 번쯤 인지해두고 있을 만한 가치가 있다고 생각한다.
- ASP(Active Server Page)는 프로그래밍 언어가 아니다. 2002-03-15 00:00
- Microsoft Windows Script 5.6과 VBScript 5.6 2002-03-15 00:00
- VBScript 5.6과 정규 표현식(Regular Expression) 2002-04-14 20:15
- RegExp.Test() 메서드와 RegExp.Execute() 메서드의 활용 2002-04-29 11:24
- RegExp.Replace() 메서드의 활용 2002-05-26 22:49
- VBScript 5.6과 클래스(Class) 2002-06-19 12:31
- 접근 제한문, Initialize 이벤트와 Terminate 이벤트, 그리고 프로퍼티 프로시저 2002-08-19 16:08
- 인자를 가진 프로퍼티와 디폴트 프로퍼티(Default Property) 2002-09-11 09:12
- 그 밖의 유용한 VBScript 5.X 버전의 기능들 2002-11-03 16:19
- 기존의 ASP 프로그램을 이용한 간단한 스케줄링 잡(Scheduling Job) 설정 2003-02-21 10:31
- FileCube 버전 0.0.3 (설치 방법 및 기타 관련 정보) 2003-05-26 09:31
- FileCube 버전 0.0.4 (커스텀 레코드셋으로 구현한 정렬 기능) 2003-09-15 12:28
- 인터넷 익스플로러 스크립팅 개체와 인터페이스 2004-01-07 09:06
- 인터넷 익스플로러가 HTML을 처리하는 기본적인 방법에 대한 이해 2004-03-29 14:54
- 재미있는 자바스크립트 01, TABLE 태그와 HTCs의 활용 2005-04-25 14:00
- 재미있는 자바스크립트 02, HTCs의 작성 2005-07-13 09:18
- 재미있는 자바스크립트 03, HTCs의 작성과 ASP.NET 사용자 지정 컨트롤 연동 2006-05-25 16:49