요 근래 윈도우 XP SP2 때문에 몇몇 골치 아픈일이 많이 발생하는 걸 보고, 그에 따른 뒷 처리를 보강하는 작업을 하고 있는데, 조금은 비 생산적인 일을 하고 있다는 생각을 지울 수가 없네요. 아무리 "신뢰할 수 있는 컴퓨팅" 이라는 이니셔티브 때문에 보안을 강화하였고, 이에 따른 어느정도의 불편함도 결과적으로는 사용자의 이득을 위해서다. 라고... 하지만 이래저래 좀 수정되었다 싶으면 자꾸 터지니까, 이건 제대로 "MS는 수익을 목적으로 하는 기업이다라는 걸 분명히 알리기 위한 포석이"라는 생각이 드네요. 이 부분이 어느 정도 관철되면 앞으로 이와 비슷한 일을 편한 마음으로 더 할 수 있을테니까. 보안을 위해 정말 다른 방법이나 대안이 없었는지 아쉬울 따름입니다.
그래서 요즘 새롭게 부상중인 파이어폭스나 모질라같은 웹 브라우저의 선전을 많이 기대하고 있습니다.
역시 경쟁이 있어야 서로 간에 발전이 있으니까요. (개인적으로 음모론 같은 가정을 즐깁니다. 별뜻 없습니다 ^^;;;)
이번 강좌에서는 지난 강좌에 이어 컬렉션 태그와 컨테이너 태그 그리고 비베 스크립트에서 HTML 객체에 접근하기 위해 제공하는 대표적인 기능 몇가지를 알아 보겠습니다. 이것들을 알아야 앞으로 개발 할 때 많은 도움을 받을 수 있기 때문인데, 난이도를 중,고급으로 해놓았지만 되도록 쉽게 설명하도록 하겠습니다.
익스플로러에서는 Dynamic HTML (DHTML) Object Model 에 근거한 <FORM>태그를 컬렉션 태그로 활용 할 수 있습니다. 그래서 단순히 서버에 각 컨트롤의 데이터를 넘겨주기 위한 역할만 하는 것이 아닌 다양한 부분에 활용할 수가 있는데, 이와 같은 컬렉션 태그 말고도, 얼핏 비슷하게 컨테이너 역할을 하는 자사 전용 확장 태그도 사용할 수 있습니다. (근래에 모질라에서도 몇몇 지원을 합니다만, 대부분 완벽하게 동작하지 않는 태그가 많습니다.)
컨테이너 태그라는 건
컨테이너라는 단어에서 알수 있듯이 HTML내에서 다양한 타입의 자식 태그들을 담아서 관리 할 수 있는 기능을 가질 수있고, 또는 다양한 물건을 넣고 빼듯 임시적으로 데이터를 관리하고자 할 때, 사용 할 수 있는 태그입니다.
<FORM> 태그는 컬렉션 태그중 가장 많이 쓰이지만, 일반적인 컬렉션 태그와는 달리 자신의 태그안에 사용자 입력을 받는 다양한 컨트롤들을 그룹으로 묶어 서버의 전송하는 역할을 하고, 컨테이너 태그와는 다르게 스크립트에서 객체에 접근 할 때 보다 직관적인 인터페이스를 제공하므로 개발에 사용하기가 용이합니다.
컬렉션과 컨테이너 태그 두 개념은 주어진 업무 상황에 따라 차이가 있습니다만, 웹 개발시 반복되는 코드나 빈번하게 작업되는 로직을 구현 할 때 유용하게 사용할 수 있습니다. 그래서 웹 개발시 HTML 컬렉션 태그와 컨테이터 태그의 각 목적과 용도가 무엇인지 알아 둘 필요가 있습니다.
>> HTML 컬렉션 태그
컬렉션은 언어마다 해석이 조금씩 틀리지만, 웹 개발 분야에서 사용하는 컬렉션이라는 단어가 주는 의미는 "자신과 관련된 객체들을 가지고 있는 객체" 라고 생각하시면 됩니다. 그 어떤 태그를 넣어도 되는 컨테이너 태그와는 조금 틀리죠. HTML 컬렉션 태그로 사용할 수 있는건 20개 이상되지만, 이 모든 태그에 근본이라고 할 수있는 FORM 태그에 대해 많은 연구를 해보실 것을 추천합니다.
FORM 태그 : http://msdn.microsoft.com/workshop/auth ··· view.asp
그럼 예제를 만들면서 컬렉션 태그를 활용하는 기초를 보겠습니다.
<INPUT type="text" id="txtTest" value="안녕하세요">
위와 같이 HTML이 있습니다. 그렇다면 비베 스크립트 에서는
MsgBox txtTest.value
와 같이 txtTest 객체를 가지고 작업 하실 수 있습니다. 그럼 다음과 같이 HTML이 구성된 경우는 어떻게 해야 할까요?
......
<INPUT type="text" id="txtTest" value="안녕하세요1">
<INPUT type="text" id="txtTest" value="안녕하세요2">
<INPUT type="text" id="txtTest" value="안녕하세요3">
......
아까와 같이
MsgBox txtTest.value
이렇게 코드를 작성하면 "개체가 이 속성 또는 메소드를 지원하지 않습니다." 라는 에러 창이 뜨게 됩니다. 스크립트에서 객체로 접근하기 위한 name, id 값은 언제나 유일해야 하지만 위와 같이 중복된 값이 들어가게 된다면, 익스플로러는 위의 태그를 txtTest 라는 컬렉션으로 구성하게 됩니다.
컬렉션은 그 자신만으로는 별다른 작업을 할 수 없기 때문에 컬렉션으로 구성 된 태그에 접근하기 위해서 Item, Length 키워드를 사용하여 작업해야 합니다. 위의 코드를 약간 수정해보면
MsgBox txtTest.Item(0).value
MsgBox txtTest.Item(1).value
MsgBox txtTest.Item(2).value
또는
For iIndex = 0 To txtTest.Length
MsgBox txtTest.Item( iIndex ).value
Next
이렇게 해야 에러가 나지 않습니다. 이와 같은 특성을 이용하여 아래와 같이 id와 name을 같이 사용하면 개발 시 많은 도움을 받을 수 있습니다. 그럼 하나의 예를 더 들어보겠습니다.
<INPUT type="text" id=txtTest1 name="collect">
<INPUT type="text" id=txtTest2 name="collect">
위와 같이 HTML이 구성되어 있다면, 지난 강좌에서 얘기했듯이 이제 비베 스크립트에서 객체에 접근하기위해 txtTest1, txtTest2를 이용 할 수도 있고 collect 명으로 컬렉션에 접근하여 동일한 작업을 수행 할 수도 있다는 것을 아실 겁니다.
흔히 체크박스가 많은 웹 페이지에서 몇 개의 체크박스가 선택 되었는지, 특정 체크 박스가 선택됨에 따라 업무로직을 별도로 삽입해야 한다면, collect 로 반복문을 돌면서 id 값으로 조건문을 주어 작업 하실 수 있게 되는 겁니다. 이렇게 비베 스크립트만으로 구현하기 까다로운 부분을 HTML 컬렉션과 적절히 연동하면 쉽게 해결되는 부분이 많습니다.
컬렉션을 이용한 중, 고급에 해당하는 내용을 보고 싶으시면, 여기를 참조하세요.
http://msdn.microsoft.com/workshop/auth ··· e%3Dtrue
--------------------------------------------------------------------------------------------------------------
>> 컨테이너 태그
컨테이너 태그는 대표적으로 <DIV>, <SPAN> 태그가 그 예로 들 수 있는데, 이 태그는 자신의 태그 안에 그 어떤 태그들도 자식으로 활용 할 수 있습니다. 이 기능을 잘 사용한 사이트가 MSDN TOC 라는 생각이 드는데요. 이 MSDN TOC 의 핵심은 하나의 메뉴를 가지고 있는 항목을 클라이언트 스크립트를 이용하여 아래와 같은 태그로 구성하게 만드는 것입니다.
MSDN 라이브러리 온라인 : http://msdn.microsoft.com/library/default.asp
MSDN 라이브러리 온라인에서 가장 처음에 있는
이 메뉴는 HTML을 풀어보면 아래와 같이 구성되어 있습니다.
......
<div class='clsItem' type='leaf'>
<span class='clsSpace' type='img'>
<span class='clsLeaf' type=''>+</span>
</span>
<span class='clsLabel' type='label' classType=''>Welcome to the MSDN Library
<span type='' classType='' class='clsUnavailable'>(DIV 반복 태그 예 : <div class='clsItem'... )</span>
</span>
</div>
......
그 다음 사용자가 메뉴 클릭시 자식 메뉴들(그것도 하나하나의 메뉴가 위와 같은 구조입니다)을 가져와 DIV 반복 태그구역에 innerHTML 을 이용해서 추가가 됩니다. 이렇듯 다양한 타입의 자식 태그를 가질수 있기 때문에 동적인 효과를 보여줄 때 자주 사용하기도 합니다.
이번엔 좀 더 실질적인 예제를 가지고 DIV 태그의 활용성에 대해 생각해 보겠습니다. 오른쪽 마우스 버튼을 누르면 팝업 이벤트를 잡아 제가만든 팝업메뉴로 띄운다음 메뉴를 선택하면 몇번째의 메뉴를 선택했는지 에 대한 메시지 박스를 출력하는 간단한 프로그램을 함수 3개로 만들어 보겠습니다.
|
<HTML>
<HEAD>
<TITLE></TITLE>
</HEAD>
<BODY type="">
<div id="menu">
</BODY>
</HTML>
여기에 비베 스크립트 구역을 하나 선언하고 컨텍스트 메뉴 호출 이벤트에 대응하는 핸들러 함수를 하나 선언합니다. 아래 코드는 화면에서 컨트롤 키를 누르고 오른쪽 마우스를 클릭해야 본래 팝업이 띄게 해놓았습니다.
<SCRIPT ID=clientEventHandlersVBS LANGUAGE=vbscript>
<!--
document.oncontextmenu = GetRef("ContextMenu_Handler")
Function ContextMenu_Handler()
show_context()
If window.event.ctrlKey Then
ContextMenu_Handler = True
Else
ContextMenu_Handler = False
End If
End Function
-->
</SCRIPT>
그리고 메뉴 클릭시 몇번째의 메뉴를 선택했는지에 필요한 이벤트 함수 선언을 추가 합니다.
Sub document_onclick()
If IsObject( context_menu ) = True Then
context_menu.style.display = "none"
Set objUnknown = window.event.srcElement
If objUnknown.type = "context_item" Then
MsgBox objUnknown.id & " 의 메뉴를 선택했습니다."
End If
End If
End Sub
위의 코드를 보면 context_menu 객체를 화면에서 숨겨주는 스타일시트를 넣었지만, 기본적인 BODY 태그안에 있는 HTML은
<div id="menu"> 이게 전부입니다. 상식적으로 이 코드는 에러가 발생해야 정상이지요. 하지만 스크립트로 id가 context_menu 인 DIV 태그를 만들어 BODY 태그안에 이 로직이 실행되기전에 선언을 해주면 됩니다.
이렇게 선언된 DIV 객체는 DOM에 근거한 이벤트를 가질 수 있게 되기 때문에 DIV 태그 위에 마우스가 오버하면 onmouseover 이벤트가 발생하며, window 최상위 객체는 이벤트가 발생한 자식객체를 알아내어 objUnknown 객체로 참조값을 넘길 수 있게 됩니다. 그래서 If objUnknown.type = "context_item" Then 이 코드에서 클릭 이벤트 발생시 팝업 메뉴위에서 이벤트가 발생했는지의 여부를가지고 몇번째의 메뉴를 선택했는지 메시지 박스로 출력 하게 됩니다.
이제 가장 중요한 함수 하나가 남았습니다. 먼저 화면에 팝업 메뉴가 뜬적이 있는지 여부를 가지는 전역변수와 팝업 메뉴 HTML을 가지는 전역 객체를 하나 선언 합니다.
Dim contextYN, oDivTag
contextYN = False
Function show_context()
If contextYN = True Then
menu.removeChild oDivTag
Set oDivTag = Nothing
End If
Set oDivTag = document.createElement("div")
oDivTag.id = "contextDiv"
oDivTag.setAttribute "type", "conDiv"
oDivTag.innerHTML = ("<div id='context_menu' type='context' style='DISPLAY:none;BORDER-RIGHT: menu 2px outset; PADDING-RIGHT: 1pt; BORDER-TOP: menu 2px outset;PADDING-LEFT: 1pt; FONT-SIZE: 9pt; PADDING-BOTTOM: 1pt; BORDER-LEFT: menu 2px outset; WIDTH: 100px; CURSOR: default; PADDING-TOP: 1pt; BORDER-BOTTOM: menu 2px outset; POSITION: absolute; BACKGROUND-COLOR: menu;' align=center>" _
& "<span id='menu1' class='menuitem' type='context_item' style='BORDER-LEFT-COLOR: menu; BORDER-BOTTOM-COLOR: menu; WIDTH: 100px; BORDER-TOP-COLOR: menu; TEXT-ALIGN: center; BORDER-RIGHT-COLOR: menu'>1번째 메뉴</span>" _
& "<span id='menu2' class='menuitem' type='context_item' style='BORDER-LEFT-COLOR: menu; BORDER-BOTTOM-COLOR: menu; WIDTH: 100px; BORDER-TOP-COLOR: menu; TEXT-ALIGN: center; BORDER-RIGHT-COLOR: menu'>2번째 메뉴</span>" _
& "<span id='menu3' class='menuitem' type='context_item' style='BORDER-LEFT-COLOR: menu; BORDER-BOTTOM-COLOR: menu; WIDTH: 100px; BORDER-TOP-COLOR: menu; TEXT-ALIGN: center; BORDER-RIGHT-COLOR: menu'>3번째 메뉴</span>" _
& "</div>")
menu.appendChild oDivTag
context_menu.style.posLeft = window.event.clientX
context_menu.style.posTop = window.event.clientY
context_menu.style.display = "block"
context_menu.setCapture()
contextYN = True
End Function
위의 스크립트에서 아래와 같은 코드로 DIV 태그를 하나 만듭니다.
Set oDivTag = document.createElement("div")
oDivTag.id = "contextDiv"
oDivTag.setAttribute "type", "conDiv"
결과 : <div id=contextDiv type=conDiv></div>
그 다음 context_menu id 값을 가지고 있는 DIV HTML을 contextDiv 객체 안에 넣고 실제 BODY 태그안에 있는 menu 객체에 그 값을 넣으면 이 시점에서 익스플로러는 화면을 재구성을 합니다. 이 다음 부분에서
alert document.body.innerHTML
을 하게 되면 BODY 태그내에 HTML 소스가 변경이 되고 익스플로러는 화면을 재구성하게 됩니다.
! 중요체크
여기서 잠시 논외로 재구성이라는 것에 주목할 필요가 있습니다.
비베 스크립트나 J 스크립트내에서 가장 비싼 비용을 소모하는 코드는 물론 생각없이 만든 메모리 누수 코드이고, 그 다음으로 비용을 치르는 코드가 이 화면 재구성에 필요한 리소스에 해당되는 코드입니다.
좀 더 쉽게 얘기하면 BODY 태그내에 복잡한 HTML이 있으면 있을수록 화면 재구성에는 비용이 많이 듭니다. 이건 근본적인 DOM 모델 방식의 단점이지요. DOM은 언제나 데이터를 가공하기 위해 문서를 FULL로 로딩한 다음 가공합니다. 그래서 화면상에 디자인이 조금이라도 바뀌게 되면, 메모리 상에서 기존의 문서를 지우고, 다시 로딩을 해야하기 때문에, 사용자는 모르지만 내부적으로 많은 리소스를 소모하게 되지요.
실제 비베 스크립트에 백만건의 배열에 랜덤한 값을 넣고, 간단한 버블 소트 알고리즘으로 순차적으로 재구성후 화면에 출력하는 기능을 가진 로직을 수행 할 때 걸리는 시간은 2초이상 걸리지 않습니다. 하지만 아무리 간단하더라도 화면 재구성이 있는 코드안에 만건정도의 반복문 안에다가 돌리게되면 잠시 화면이 멍해지고, 이 순간 만큼은 CPU는 100% 점유율을 가지게 됩니다. 개발하다보면 많이 경험하는 부분인데, 결과값은 한번에 처리해 주는게 좋습니다.
언뜻 잠시 다른 얘기가 나왔지요? 그 다음은 크게 어려운 코드가 아니기 때문에 이해하시는데 별 어려움이 없으실겁니다. 이 예제는 첨부파일로 등록해두었으니 다운받아 천천히 분석해 보세요. 이렇듯 컨테이너 태그를 활용하면 다양한 프로그램을 만들어 낼 수 있습니다. 다른 태그가 할 수 없는 아주 매력적인 기능이지요.
DIV 태그에 대한 레퍼런스는 아래를 참조하세요.
http://msdn.microsoft.com/workshop/auth ··· Fdiv.asp
엄청 느리고, 쓸모는 크게 없지만, 스크립트만으로도 MSDHTML 컴포넌트를 사용하지 않고, 폼 마법사같은 위지윅 툴도 흉내낼수 있을 정도로 다양한 기능을 구현 할 수 있습니다. 위의 코드와 설명을 이해하셨다면 스스로 컬렉션 태그및 컨테이너 태그에 대한 연구는 어렵지 않게 진행하실 수 있습니다.
이제 마지막으로, 비베 스크립트내에서 DHTML 객체를 잡아 내기 위해 지원하는 함수와 간단한 응용법에 대해 알아 보겠습니다.
이 주제는 웹 개발에 입문한지 얼마되지 않는 분들을 위해 만들었습니다. ( 만들어진 코드는 J 스크립트내에서도 언어상의 구문 차이를 제외한 모든 기능을 그대로 지원하고 있습니다)
|
eval(): |
함수는 문자열, 숫자 또는 개체를 만드는 키워드, 연산자, 변수등의 모든 식을 수행하거나, 문자를 조작하거나, 데이터를 검사할 수 있는 유용한 함수입니다. |
|
formID: |
FORM 태그의 id를 가리키는 것이며, 다른 컬렉션 태그와는 달리 자식 개체에 접근하기 위한 인터페이스를 가지고 있습니다. |
|
document: |
익스플로어에서 제공하는 기본객체중 하나로서 화면상에 보여지는 부분을 담당하는 객체입니다. |
예제 HTML
......
<BODY>
<FORM id="MASTER">
<INPUT type="text" id="test1">
<INPUT type="button" id="test2">
<INPUT type="hidden" id="test3">
<INPUT type="checkbox" id="test4">
<INPUT type="radio" id="test5">
</FORM>
</BODY>
......
아래의 예제는 각 INPUT 객체의 타입을 메시지 박스로 출력하는 동일한 기능을 3가지의 경우로 나누어 만든 것입니다.
eval()
For iIndex = 1 To 5
' MASTER.test1, MASTER.test2...... 의 객체를 잡아낸다.
Set oUnKnow = eval("MASTER.test" & iIndex )
MsgBox oUnKnow.type
Next
formID
'FORM 태그안에 있을경우 아래처럼 FORM id를 먼저 기술해야 합니다.
MsgBox MASTER.test1.type
MsgBox MASTER.test2.type
MsgBox MASTER.test3.type
MsgBox MASTER.test4.type
MsgBox MASTER.test5.type
document
'BODY 태그안에 있는 모든 INPUT 컨트롤을 가져온다.
Set oInput = document.getElementsByTagName("INPUT")
For iIndex = 0 To oInput.Length - 1
MsgBox oInput( iIndex ).type
Next
위의 코드들을 적절할 때 사용해주면 많은 자동화 기능에 활용할 수 있습니다. 예를 들어 업무 프로그램 개발시 HTML상의 id 값들과 데이터베이스의 테이블 컬럼 아이디를 동일하게 만들어 놓고 프로그램 로딩시 테이블의 스키마(길이, 타입등등)를 얻어와 MaxLength라던가 타입 비교에 따라 추가적으로 기본값들을 미리 지정해놓을 수 있으며, 반대로 화면상에 있는 각 컨트롤들의 값을 서버로 넘기고자 할 때, 데이터를 업데이트를 위한 각 컨트롤의 값들을 쉽게 가져올수 있습니다.
>> 정리
컬렉션, 컨테이너 태그의 용도와 활용법 그리고 객체를 잡아내기 위한 스크립트에서 작업하는 방법에 대해 알아봤습니다. 내용이 부족하지만 웹 개발시 조금이라도 도움이 되었으면 합니다. 내용이 어렵다고 생각하시는 분들에겐 좋은 고민거리가 될 수 있을겁니다. 저도 강좌를 쓰는게 하도 오랫만이라 부족한게 많이 보여 아쉬운 점이 많네요. 보충이 필요한 부분이 있으면 답글 달아주세요. 그 부분에 대한 보강을 넣겠습니다.
요즘 전 일렉기타를 공부하고 있습니다. 왠만한 잡일에는 쉽게 질리는 체질인데도 기타는 거의 1년이 다 되어 가네요. 그래도 아직 기초도 제대로 소화하지 못하고 있습니다. 어떤 분이 말하길 훌륭한 기타 플레이어가 되기 까지는 연습만 하루 5시간으로 15년만 하면 누구든지 할 수 있다고 합니다. 노력한 만큼 거둔다는 이 말에 감동해서 일렉기타를 포기 못 하는 이유이기도 하죠. ^^;; 읽어주셔서 감사드리고 담에는 좀 더 유익한 내용으로 찾아 뵙겠습니다.
- Power of VBScript (0)2007/01/05
- Power of VBScript ( Document Object Model Vol II ) (0)2007/01/05
- Power of VBScript ( Document Object Model Vol I ) (0)2007/01/05
- Style Sheet (0)2005/07/06

수안이의 컴퓨터 연구실




Leave your greetings.