ns2 installation
ns2 debuging
'Computer_language > Debug' 카테고리의 다른 글
Pedro Vale Estrela - NS2 Debugging Page (0) | 2009.01.12 |
---|---|
[From NS-User] (0) | 2009.01.12 |
NS2 Programming (0) | 2009.01.12 |
Pedro Vale Estrela - NS2 Debug / BugFix Tutorial (OTCL + C++) (0) | 2009.01.12 |
GDB 잘 쓰기 2: User Defined Commands (0) | 2009.01.12 |
Pedro Vale Estrela - NS2 Debug / BugFix Tutorial (OTCL + C++)
| Computer_language/Debug 2009. 1. 12. 02:29This tutorial will focus on how to use the oTcl and C++ debugger tools to find a bug in NS2.28 or earlier.
(recent CVS snapshots and future 2.29 version will have it corrected, as the patch was already been applied to the CVS tree.
Thus, this tutorial will guide you in the typical debug process that are useful for a variety of situations.
Files and Patches (contains the scripts patches mentioned in these pages)
Contact: pedro.estrela@inesc.pt
--------------------------------------------------------------------------------
NOTE 1: The tutorial mentions several scripts. These are available at the files directory. I've also made a compressed file that has everything you'll need on this guide test-suite-hier-routing-bug.zip. It will also depend on recent versions of my ns2_shared_procs.tcl file.
NOTE 2: This tutorial will give greater detail on the otcl debugging part; However, an experienced NS developer could directly jump to the C++ debugging part, by closely studing the call stack dump information.
NOTE 3: A different way to modify the built-in tcl functions would be do modify them directly in the tcl source files and recompiling NS. However, the method outlined below is preferable to begginners, as it doesn't require recompilation, and doesn't changes the existing code (resuting in trivial backtraction, if necessary).
NOTE 4: Like my other tutorial, I'll present a complete script and an image for each step. however, one should try to make the modifications required by hand, to get a much better understanding on modifiyng NS.
--------------------------------------------------------------------------------
Step 0 - Prologue
The bug that will be investigated in this tutorial appeared when I've tried to add dynamic routing capabilities (eg, possibility to simulate link failures recovery) to a fairly complex script that featured a large topology of wired links, coupled with several wireless links (both base stations and pure mobile nodes). Another relevant point is that the script used hierarchical routing in all the nodes, for Mobile IP usage.
The said script was working 100% until I've added to it instructions to simulate a link failure on one of the wired links. As explained in this section of the Marc Greis's tutorial, all that is required is to add "$ns rtmodel-at time up|down node1 node2" commands to the script.
However, the problem was when I've enabled the "session" dynamic routing to use the alternative paths of the wired topology. (e.g., using "$ns rtproto Session" at the start of the script).
At run time, the simulator crashed in the middle of the simulation with the following error: test-suite-hier-routing.error1.txt.
Step 1 - Choosing a simpler scenario that is known to be correct
To try to isolate the bug, a common heuristic is to try to simplify the scenario, by removing unused parts that (hopefully) are unrelated to it. On the above example, I've suspected that the bug was somewhere in the interaction of the dynamic routing and the hierarchical routing (as the simulator crashed when the wired link went down); In that case, the wireless nodes and complex topologies only further obscured the real problem. (As it will be shown later, this supposition was correct).
On the other hand, I also wanted to validate my own script, has I could be doing something in it that could be corrupting the simulator.
Thus, one good approach to find the bug is to start from a known correct scenario, and slowly introduce minimal features to force the bug to appear. The best example for this are the standard test suites included in NS2, which are used to validate the simulator itself, againt the most recent modifications and patches.
(note: as explained here, these tests suites are the only scripts that are guaranteed to use the latest APIs; on the contrary, the examples in "ns/tcl/ex" and the Marc Greis's tutorial is known to be out-of-date, especially on the wireless examples).
Searching in "ns/tcl/test", I've found that the only test suite that used Hiererarchical routing was "test-suite-hier-routing". This test used a simple non-redundant topology (eg, only direct paths) and used regular static routing. This has produced a topology with 9 nodes.
Script: test-suite-hier-routing_1.tcl
Result: hier_step1.gif
To run the simulation: "ns test-suite-hier-routing.tcl hier-simple"
To view the simulation in nam: "nam temp.rands.nam"
Step 2 - Making the bug appear in the simpler scenario
Now let's try adding a new link between nodes 5 and 7, and make it go down at time 2. This is attained by introducing these 2 lines in the script, in the instproc "TestSuite instproc init".
$ns_ duplex-link $n_(5) $n_(7) 5Mb 2ms DropTail
$ns_ rtmodel-at 2 down $n_(5) $n_(7)
Use the same commands as before with the new script. Using it, the traffic first goes to the new link, and at time 2, all packets are lost at the new link, making nodes 7 8 and 9 unreachable.
Script: test-suite-hier-routing_2.tcl
Result: hier_step2.gif
Now, let's use dynamic routing to correct this, choosing type Session. Just add "$ns_ rtproto Session" after the simulator object creation, in init-simulator {}.
If you now run the new script, it will crash with the exact same error as before. Good work! Now we have a much simpler scenario which is sufficient to trigger the bug, and will be much easier to debug!
Note that only now you should ask on the NS2 mailing lists concerning about the bug that you've found, to know if somebody has made any work for its fix. It is fairly important to use a simple scnenario as the one exaplined here. As an example, check the email I've sent to the NS developer's mailing list for this very bug: Bug report
Script: test-suite-hier-routing_3.tcl
Error (Call Trace): test-suite-hier-routing.error2.txt
Step 3 - Getting to know what is going on at the beginning of the simulation
In this section we'll take an inside look on the TCL objects that are created by the script, to get a insight view of the inner workings of the simulator. I assume that you've followed and experimented my tutorial on otcl debugging.
The ideia will be to stop the simulator immediately before the simulation starts (eg, before $ns run). For this:
a) modify the script to include a new MashInspector object in "Test/hier-simple instproc run", before "$ns run";
b) make it stop before "$ns run" with "debug 1";
c) modify it to run the "hier-simple" test, ignoring command line parameters (check runtest() of the resulting script if its too dificult);
Then use the resulting script as follows:
a) start nstk without parameters. It should open the tkcon console.
b) start the script ("source test-suite-hier-routing_4.tcl").
You'll now see the Mash's Object Inspector that you can use to peek into the otcl objects that are created at the start of the simulation. In folowing figure, I'm inspecting the main "simulator" object, which is created in the script by "set ns [new Simulator]". For this, I've selected the "Simulator" class on the first column, and its unique instance on the fourth column (in my case, it was object _o5).
At this stage you'll find _o5's private variables in the last column, namely the node information (array Node_[]), each link (link_[]), and private variables that contain references to the name of other core objects, namely the scheduler in use, type of trace in use, etc. Another important column is the second, as it contains the references to the procs available to the selected object. If you click on each, you'll check the source code for it (This will be very important on the next step).
Navigating with the references, you can now inspect each object in succession. For example, clicking on the private variable "routingTable_", you are moved to an instance of "RoutingLogic", that contains a private variables rtprotos_(Session). This is enough to confirm that you are using correctly the "Session" type of dynamic routing.
Using this technique is useful to check the inner state of the objects created by your script before the simulation, to make sure that these start as intended.
However, our specific error ocours at run-time 2.0, when the link goes down. Thus, our next step is to stop the simulator at exactly this event.
Script: test-suite-hier-routing_4.tcl
Image: hier_step3.gif
Step 4 - Getting to now what is going on immediately before the crash at runtime.
The ideia to debug at run-time is to insert "debug 1" commands at interesting points of the code, to break the execution at runtime. For this, we'll check the tcl call stack
that simulator dumps when it crashes; it starts from the innermost tcl procedure that crashed, then the function that called it, etc, until the first tcl function that triggered the calling stack.
In our case, the outermost function (eg the first) is "runq" proc. Note that there is no easy reference to the actual tcl source code file that contains this function; for this, you should make a recursive grep of teh string "runq" in the whole ns/tcl sourcetree:
ns/tcl> grep -d recurse "runq" *
You'll be able to check that this procedure resides inside the file "rtglib/dynamics.tcl". Next, you could simply modify proc "runq" and recompile NS. However, TCL enables to replace any given proc in run-time; thus, to avoid modifying the ns2 core files, we'll copy the "runq" proc to our script, and insert the "debug 1" instruction on our private copy.
Script: test-suite-hier-routing_5.tcl
Image: hier_step4.gif
The next image shows actual interaction at run-time. Notice as I've confirmed what is the current simulation time when the debugger breaks in (e.g., at 2 seconds); for that, I've just called the "now" proc of the simulator object on the bottom evaluation line (also check that I'm showing the actual code for the "now" procedure).
Now you can position yourself on the current running object, in order to inspect it. For this, run "puts $self" on the debugger window and find the object name on the list of all instances. Then open the "runq" procedure - see the folowing image.
Image: hier_step5.gif
You are now on an rtQueue object, that has a list of events (see array rtq_[]). You can now do a step by step trace in the debugger window, and check the code to be executed in the Mashinspector window at each time (using the enter key in the debugger console). This will take you, step by step, to all procs that are mentioned on the call trace after the crash. However, at any time you can check the internal state of the objects, to check for logical bugs.
Using these techniques, and more closer "debug 1" statements up the stack, you'll eventually reach the "simulator compute-hier-routes" function, and conclude that the bug is triggered when the "$r hier-reset $srcID $dstID" line is called. (the compute-hier-routes is in ns/tcl/lib/ns-route; use recursive grep to find its location).
The following script has debug code immediately before this function call, to produce the correponding screenshot:
Script: test-suite-hier-routing_6.tcl
Image: hier_step6.gif
Here, i'm checking what are the values of the parameters for the link (_o12), the source node (1.1.0) and the destination node (1.0.0). As all these values are correct, lets now check the proc itself (hier-reset).
Step 5 - Understanding Shared C++ / TCL procs
For this, we'll go to object _o12 and check its procs. However, as it can be seen on image7, this proc doesn't appear in the list. This happens because of a powerful (but confusing to beginners) mechanism that simplifies C++ procedures calling in TCL.
When an unexisting procedure is called to an otcl object, the tclcl library that is part of the core ns modules calls the "*command(argv argc)" of the corresponding C++ object, with all the parameters as string.
This function inspects the command name in the argument, and if its know, executes it; if not, an error is returned.
This way, the available procs that can an object can execute are:
- defined in its own oTCL class;
- heritaged from parent otcl super classes;
- contained in the C++ command() of the corresponding C++ class ;
However, only the first types appears directly in the object inspector; the heritaged otcl procedures are visible if one chooses the parent classes in the heritage column (3rd column). As the hier-reset proc isnt present in the otcl class or super classes, it has to be in the C++ code.
For this, make a recursive grep from the base of the ns2 tree:
ns2> grep -d recurse "hier-reset" *
(NOTE: must faster way would be to only check for .cc files, for example:
grep -d recurse "hier-reset" *.c
grep -d recurse "hier-reset" */*.c)
The recursive grep tells us that the function is inside RouteLogic::command(argc, argv), on routing/route.cc.
The relevant part is:
...
} else if (strcmp(argv[1], "hier-reset") == 0) {
int i;
int src_addr[SMALL_LEN], dst_addr[SMALL_LEN];
str2address(argv, src_addr, dst_addr);
// assuming node-node addresses (instead of
// node-cluster or node-domain pair)
// are sent for hier_reset
for (i=0; i < level_; i++)
if (src_addr[i]<=0 || dst_addr[i]<=0){
tcl.result ("negative node number");
return (TCL_ERROR);
}
hier_reset(src_addr, dst_addr);
} else if (strcmp(argv[1], "hier-lookup") == 0) {
...
We'll now proceed into C++ level debugging. However, you should now comment the lines that called the otcl debugger.
Script: test-suite-hier-routing_7.tcl
Step 6 - Move into C++ debugging
Fortunately we'll now proceed into C++ level debugging, which has much better tools for debugging. I suggest using ddd, which is a front end to gdb. (check details and tutorials here).
Start ddd, open the ns executable (menu file / open program ) then put a breakpoint in route.o's RouteLogic::command().
(menu file / open source / route.cc )
Image: hier_step8.gif
Now lets run the program (menu program / run / arguments: test-suite-hier-routing_7.tcl))
Notice how you'll have a source level debugger window that is stopped at the breakpoint.
Now, use step by step (f5), and notice how the arguments are processed; then the hier_reset() function is called, to perform the actual work.
Now notice that after hier_reset(), the control falls trough to the end of the command() function, reaching return(TclObject::command(argv, argc));
Image: hier_step9.gif
This line passes control to the TCL standard command processor, which doesnt know anything about link failures, hierarchical resets etc. Thus, this function will return an error, and the simulator will crash in run-time.
Looking for the other commands processed by this function, a simple pattern is easy to catch:
- each "if" verifies the command name (strcmp== 0);
- arguments are collected from the argv/argc array;
- a function is called that does the actual work;
- the function either returns with TCL_OK or TCL_ERROR.
However, such is not the case in our hier-reset function, as there is no return(TCL_OK) anywhere.
Thus, the control falls-through to the default behaviour, which will subsequently let to the simulator crash.
As the hier-reset is a void function, it will not have anything to return; thus, we'll arbitrate that the command() function should return TCL_OK, to indicate to tcl that it has processed the hier-reset call just fine.
As such, just insert a "return (TCL_OK);" immediately after the existing hier_reset(src_addr, dst_addr);. Then recompile the simulator and rerun the script.
You'll then check that it no longer crashes at run time, and is able to do the whole simulation without problems. Then, use nam and check that the original problem has been corrected (e.g. Hierarchical + Dynamic Routing). As you can check in the folowing image, where the link failure at time 2 is instantly "healed" by the Session routing.
Image: hier_step10.gif
Now its the time to go outside, and celebrate the bugfix that you've acheived!
Step 7 - Contribute a patch to the NS developers with your newest bug discovery
Er, actually not so fast. :-)
That celebration idea should be delayed until the WHOLE work is done. And no bug is fixed until a patch is submitted to the NS developers.
This will enable the bug to be corrected on the following version of NS2, benefiting the whole community at once; on the other hand, it saves other fellow researchers the necessary time to fix the same bug over and over, enabling actual research work to be done.
For this, I recommend the use of CVS, for you to keep track on your own modifications and bugfixes to the simulator.
Other simpler usage to make a patch is to make a comparisation of the modified source files. For this, try the folowing line
diff -C3 original unmodified source file your modified source file
...and send the result in a SHORT but CLEAR email as a bug fix to the developers.
As an example, check the patch report on this very bug: Contributed Patch
--------------------------------------------------------------------------------
Check the files, patches, etc in this directory
Go back to my NS2 page
Contact: pedro.estrela@inesc.pt
www.terraview.org Programa de apoio cartogr?co (SIG) para planeamento agricola, florestal e ambiental

'Computer_language > Debug' 카테고리의 다른 글
Pedro Vale Estrela - NS2 Debugging Page (0) | 2009.01.12 |
---|---|
[From NS-User] (0) | 2009.01.12 |
NS2 Programming (0) | 2009.01.12 |
ns2 gdb debug 관련 파일 (0) | 2009.01.12 |
GDB 잘 쓰기 2: User Defined Commands (0) | 2009.01.12 |
[Tip] win32k.sys 덤프가 뜰 경우..(메모리 테스트 프로그램들) [출처] [Tip] win32k.sys 덤프가 뜰 경우..(메모리 테스트 프로그램들)
| Computer_language/Comfile 2009. 1. 12. 02:28하지만, 저 메시지가 뜬다면 win32k.sys(0X00000050) 한번쯤 메모리 테스트 해보는 수도 있습니다.
테스트 프로그램은
1. windiag(http://oca.microsoft.com/ko/windiag.asp#top) -> 자료실 15번
2. memtest86 3.4a(http://memtest86.com/ -> Free Download)
3. memtest86 2.1(http://memtest.org -> Download(Pre-built & ISOs))
4. memtest 3.7(http://hcidesign.com/memtest/download.html) -> 자료실 57번(신기센터장님)
(버전 업이 되어서 3.7까지 올라갔네요..)
몇군데는 usb용도 존재하네요..
입맛에 맞게 사용하세요..
오늘 며칠전에 출고한 컴인데, 고객이 자꾸 파란화면이 뜬다고 해서 오늘 입고처리했습니다.
(그땐 이상없이 동작해서 윈도우도 깔고, 가져다 준건데....)
메모리 테스트를 해보았는데, 오류 메시지를 듬뿍~!! 쏟아내더군요..
메모리 교체후 몇시간 테스트해보고 있지만, 현재까진 이상이 없네요..
참고하세요..
[출처] [Tip] win32k.sys 덤프가 뜰 경우..(메모리 테스트 프로그램들)|작성자 제우스신
'Computer_language > Comfile' 카테고리의 다른 글
프로그램 덤프 뜨기... (0) | 2009.01.12 |
---|---|
[디버깅] core dump file을 분석해 보자 (0) | 2009.01.12 |
NS2 - 무선환경 시뮬레이션 (0) | 2009.01.12 |
[EJB] 객체지향과 컴포넌트 프로그래밍 [출처] [EJB] 객체지향과 컴포넌트 프로그래밍|작성자 젠센쭈 (0) | 2009.01.12 |
열심히 배울려고 자료를 찾고 있다..
음음..
디버깅 관련 문서를 보고 있는데..
http://msdn2.microsoft.com/en-us/library/ms954590.aspx
요놈을 보다가..
adplus 에 대해서 알게 되었다..
아무튼..
프로세스 상에 떠있는 놈을 덤프를 뜰수 있다..
옵션은 대충 hang, crash 의 옵션이 있는데..
hang 을 통하여 덤프를 뜨게 되면..
메모리의 대용을 그대로( hex ) 화일로 덤프를 뜨게 된다..
음.. 머 저걸로 분석을 한다는건 다른 문제지만..
그래도 일단은 통으로 덤프를 뜰수 있다는 정도..
아.. 그리고 한가지..
덤프를 뜨면서.. 프로그램과 함깨 로드된 모듈의 정보도 같이 나타나게 된다..
음음..
조금더 자세한 사항들은 더 연구를 해봐야.. 흐흐..
자아.. 이건 adplus 에 대한 문서..
http://support.microsoft.com/default.aspx?scid=kb;en-us;q286350
http://support.microsoft.com/default.aspx?scid=kb;en-us;q286350
덤프를 뜨는 예제..
adplus -hang -pn process.exe -o c:\dir\newdir
요래하면 된다..
[출처] 프로그램 덤프 뜨기...|작성자 베타
'Computer_language > Comfile' 카테고리의 다른 글
[Tip] win32k.sys 덤프가 뜰 경우..(메모리 테스트 프로그램들) [출처] [Tip] win32k.sys 덤프가 뜰 경우..(메모리 테스트 프로그램들) (0) | 2009.01.12 |
---|---|
[디버깅] core dump file을 분석해 보자 (0) | 2009.01.12 |
NS2 - 무선환경 시뮬레이션 (0) | 2009.01.12 |
[EJB] 객체지향과 컴포넌트 프로그래밍 [출처] [EJB] 객체지향과 컴포넌트 프로그래밍|작성자 젠센쭈 (0) | 2009.01.12 |
디버깅 작업 또는 프로그램의 안전성을 검사할 때 디버거를 잘 쓰면 꽤 많은 시간을 절약할 수 있습니다. 대부분 개발자들이 GDB를 써서 디버깅을 하고 있지만, GDB가 가지고 있는 강력한 기능들을 거의 쓰지 못하고 있기 때문에, 이 글에서는 자주 쓰이지는 않을 지언정, 알면 매우 도움이 되는 기능들을 위주로 살펴보겠습니다.
먼저, 이 글을 읽는 분들이 GDB의 기본적인 사용 방법 (특히 break, run, continue, file, backtrace, print 등)을 알고 있다고 가정하겠습니다. 기본적인 사용 방법을 모르신다면 Emacs/GDB/etags/cscope나 기타 GDB manual을 참고하기 바랍니다.
Breakpoints
break 명령은 대개 다음과 같이 쓸 수 있다는 것은 이미 알고 계실 것입니다:
(gdb) break # 현재 줄에 breakpoint 설정
(gdb) break 31 # 현재 파일 31번째 줄에 breakpoint 설정
(gdb) break foo # 함수 foo에 breakpoint 설정
(gdb) break list::next # list 클래스 next 멤버 함수에 설정
(gdb) break hello.c:main # hello.c 파일의 main 함수에 설정
(gdb) break util.c:300 # util.c 파일의 300번째 줄에 설정
특히 C++의 경우, 한 클래스의 모든 멤버 함수에 breakpoint를 설정하고 검사할 필요가 있는데, 이 경우, 정규 표현식(regular expression)으로 breakpoint를 설정하는 rbreak 명령을 쓰면 편리합니다. 예를 들어 보면:
(gdb) rbreak f*o # "f*o"를 만족하는 심볼 전체에 대해 설정
(gdb) rbreak list:: # "list::.*"를 만족하는 심볼 전체에 대해 설정
특히 위 두번째 예제를 보시면 ".*"이 항상 default로 따라 온다는 것을 알 수 있습니다. 사실 rbreak 명령에 "foo"를 준 경우 사용되는 정규 표현식은, 정확히 말하면 ".*foo.*"가 됩니다. 따라서 "foo"로 시작하는 함수 전체에 대해 breakpoint를 설정하고 싶다면, 다음처럼 쓰면 됩니다:
(gdb) rbreak ^foo
breakpoint를 설정하면, 해당 breakpoint마다 번호(BNUM)가 주어지고, 이 번호를 써서 다양한 작업을 수행할 수 있습니다. 예를 들어, 전체 breakpoint 목록을 보고 싶다면:
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x08066b44 in eventShow() at menubar.cpp:1017
breakpoint already hit 3 time
2 breakpoint keep y 0x080b06f4 in Play() at thumbview.cpp:416
3 breakpoint keep y 0x08066e7e in ActPlay() at menubar.cpp:1085
4 breakpoint keep y 0x08059cd3 in Play_SS(int, int) at widgets.cpp:2183
(gdb)
첫번째 컬럼(Num)은 각 breakpoint에 대한 고유번호(BNUM)를 나타냅니다. 그리고 두번째 컬럼(Type)은 breakpoint인지 watchpoint인지 catchpoint인지를 나타냅니다. (watchpoint와 catchpoint는 다음에 설명..) 그리고 세번째 컬럼(Disp)은 이 breakpoint의 특징을 나타냅니다. (다음에 설명). 네번째 컬럼(Enb)는 현재 이 breakpoint가 활성화되어 있는지를 나타냅니다. 비활성화(n)로 표시된 breakpoint는 동작하지 않습니다. 활성화/비활성화는 'enable br [BNUM]' 또는 'disable br [BNUM]'으로 변경할 수 있습니다. 예를 들어 1번 breakpoint를 비활성화하고 싶다면:
(gdb) disable br 1
전체 breakpoint를 활성화하고 싶다면:
(gdb) enable br
2번, 4번 breakpoint를 비활성화하고 싶다면:
(gdb) disable br 2 4
2번부터 5번까지 breakpoint를 활성화 하고 싶다면:
(gdb) enable br 2-5
등으로 할 수 있습니다.
때때로, 딱 한 번만 쓸 breakpoint가 필요한 경우가 있습니다. 이 경우 쓸 수 있는 명령은 enable br once [BNUM] 또는 enable br delete [BNUM]을 쓸 수 있습니다. 예를 들어 아래 명령은 1번, 3번 breakpoint를 활성화하고, 사용된 경우 바로 비활성화시킵니다:
(gdb) enable br once 1 3
아래 명령은 4번 breakpoint를 활성화하고, 사용된 경우, 이 breakpoint를 삭제합니다:
(gdb) enable br delete 4
쓸모있는 기능 중 하나가 바로 breakpoint에 조건을 지정하고, 해당 조건을 만족할 경우에 멈추도록 하는 것입니다. 예를 들어 다음과 같은 코드가 있다고 가정해 봅시다:
int i = 0;
/* do something #1 */
for (i = 0; i < 1000; i++) {
/* do something #2 */
/* do something #3 */
}
이상하게도 i가 456일때 반복문 안에서 프로그램이 이상하게 동작한다고 가정해 봅시다. 이 때 "do something #2" 부분에 breakpoint를 걸었다면 (이 breakpoint의 번호는 8번이라고 가정합시다), 반복할 때마다 계속 프로그램 실행이 멈출 겁니다. 정확히 1000번 멈추겠죠. 456번까지 진행한다는 것은 매우 귀찮은 일입니다. 이 경우, 다음과 같이 조건을 지정할 수 있습니다:
(gdb) cond 8 i == 456
즉, 8번 breakpoint는 i == 456을 만족할 때에만 멈추도록 지정합니다. 조건식에는 단순한 상수 비교 이외에, 복잡한 함수 호출도 가능합니다. 예를 들면 다음과 같습니다:
(gdb) cond 8 foo(i) > bar(rand())
앞에서 예로 든 코드는 단순 반복문이기 때문에, 처음 456 - 1번에 발생하는 breakpoint는 무시하라고 지정할 수도 있습니다. 처음 N번 발생하는 breakpoint를 무시하라는 명령은 다음과 같습니다:
(gdb) ignore 8 455
즉, 8번 breakpoint는 455번 동안 무시됩니다.
또, 다음과 같은 코드를 가정해 봅시다:
int i = 0;
int j, k;
long l;
while (1) {
j = rand();
k = some_funtion(j, time());
/* do something #1 */
l = j & 0xFF00 + (int)(log(k) * 3.2108) - ...;
if (some_condition)
break;
}
위 코드는 j와 k가 실행할 때마다 값이 변합니다. 그리고 이상하게도 j < k 일때 변수 l이 이상한 결과를 가지는 것 같지만, 확실하지는 않습니다. 우리가 확신할 수 있는 것은 j < k일 경우, l은 항상 양수이어야 한다는 것입니다. 그래서 l의 값이 전체 반복을 끝낼 동안 어떤 값을 가지고 있는지 검사해보고 싶습니다. 이 경우 해당 breakpoint에서 멈출 때, 특정 명령을 수행하도록 하는 GDB 명령인 commands를 쓰면 됩니다.
일단 "l = j & 0xFF00..." 부분에 breakpoint를 걸고 (9번 breakpoint라고 가정), 다음 명령을 내립니다:
(gdb) commands 9
Type commands for when breakpoint 9 is hit, one per line.
End with a line saying just "end".
>silent
>if j < k
>printf "l is %d\n", l
>end
>cont
>end
대충 눈치가 빠른 분은 아시겠지만 'commands [BNUM] ... end'는, BNUM breakpoint에서 멈췄을 때, "..."에 지정한 GDB 명령들을 수행합니다. 일단 silent 명령으로 명령 자체가 출력되지 않도록 한 다음, GDB printf 명령으로 변수 l 값을 출력합니다. 그리고 continue 명령으로 계속 프로그램을 진행하도록 합니다. 그 결과, 프로그램을 실행할 경우, breakpoint에서 멈추고 l 값을 출력한 다음 프로그램을 자동으로 진행합니다. 이 과정은 반복문이 끝날 때까지 계속되기 때문에, 다음과 같은 비슷한 출력을 얻을 수 있습니다.
(gdb) continue
l is 3
l is -2
l is 2
l is 1
l is -3
앞에서 j < k일 때, l은 항상 양수여야 한다고 말했습니다. 위 결과를 보고 우리는 l 값이 때때로 잘못된다는 것을 쉽게 알 수 있습니다.
commands에 쓸 수 있는 GDB 명령어 형태는 다음 기회에...
가끔 next나 step으로 실행 과정을 따라 가다가 반복문을 만날 경우, 반복문 끝난 부분으로 바로 건너뛰거나, 현재 함수의 실행을 정상적으로 끝내고 상위 함수로 돌아가야할 경우가 있습니다. 예를 들어:
for (i = 0; i < 1000; i++) {
/* do something #1 */
/* do something #2 */
}
/* do something #3 */
현재 "/* do something #2 */" 부분까지 실행했고, 이 반복문에 이상이 없다고 판단되면, 반복문 다음까지 빠르게 진행하고 싶을 겁니다. 이 경우, until 명령이나 advance 명령을 쓰면 편리합니다.
until 명령을 쓰면, 반복문이 아닌 경우에는 next 명령과 똑같이 동작합니다.
(gdb) until
반복문일 경우, 현재 스택 프레임 (즉, 현재 함수) 안에서, 현재 줄 다음 줄에 올 때까지 프로그램을 실행합니다. 쉬운 말로, 루프를 진행하고 빠져 나오는 순간까지 실행한 다음 "(gdb)" 프롬프트를 보여줍니다.
advance 명령은 continue 명령과 마찬가지로 프로그램을 주욱 실행시키는 대신, 지정한 곳에 코드 흐름이 오면 바로 멈춥니다. 예를 들어 위 코드의 "/* do something #3 */" 부분의 줄 번호가 34였다면, until 명령 대신 다음과 같이 실행할 수도 있습니다:
(gdb) advance 34
advance 명령은 스택 프레임에 대한 제한이 없기 때문에, 현재 함수가 아닌, 아무 곳이나 설정할 수 있으며, 위치 지정은 줄 번호 뿐만 아니라, break 명령에 쓰는 모든 형식을 다 지원합니다.
네트워크로 서비스 요청 데이터를 전송받아 분석하고, 적절한 기능을 수행하고, 그 결과를 돌려주는 서버 프로그램을 생각해 봅시다. 그리고 다음과 같은 꼴로 되어 있다고 가정해 봅시다:
#define PACKET_MAX 10
int
fetch(void)
{
int packet_received = 0;
int received[PACKET_MAX];
while (1) {
if (!packet_received) {
if (recv_data(received, PACKET_MAX) == 0)
packet_received = 1;
}
/* do work here */
process_packet(received, PACKET_MAX);
}
return 0;
}
이 프로그램은 평소에는 정상적으로 잘 동작하지만, 특정 패킷을 받으면 이상하게 동작한다고 가정합시다. 그리고 이 패킷은 아주 가끔 들어온다고 가정해 봅시다. 원하는 대로 패킷을 보내주는 프로그램을 따로 작성해 두지 않았다면, 이 프로그램을 디버깅하기 위해서, 문제를 일으키는 패킷이 올 때까지 하염없이 기다려야할 지도 모릅니다. 실제 코드는 다음과 같습니다:
만약 원하는 패킷이 recv_data()를 통해 들어왔다고 가정합시다. 이 때 packet_received는 1이 되고, 그에 따라 처리 작업이 이상하게 동작할 것입니다. 이 때, received의 내용을 저장하기 위해, 다음 명령을 쓸 수 있습니다:
(gdb) dump binary value buggy.dat received
위 명령을 수행하면 배열 received의 내용을 파일 buggy.dat에 저장합니다. 만약 시작 주소와 끝 주소를 알고 있다면 다음 명령을 쓸 수 있습니다:
dump binary data buggy.dat START-ADDR END-ADDR
이 때, START-ADDR는 시작 주소를, END-ADDR는 끝 주소를 나타냅니다. 즉, 앞 received 배열의 경우, 다음과 같이 쓸 수 있습니다.
(gdb) dump binary memory buggy.dat received received+10
어느 방법을 썼든지, 현재 디렉토리에는 buggy.dat이라는 파일로, 배열 received의 내용이 저장될 것입니다. 이는 메모리 내용을 그대로 dump시킨 것이므로 od(1)와 같은 툴을 써서 그 내용을 직접 볼 수 있습니다. received 배열은 int 배열이므로 다음과 같이 확인 가능합니다:
$ od -td buggy.dat
0000000 163 151 162 85
0000020 83 190 241 252
0000040 249 121
0000050
$ _
만약, 바로 디버깅을 성공적으로 끝냈다면, 사실 위와 같은 기능은 큰 역할을 발휘하지 못합니다. 하지만, 계속해서 디버거를 실행해서 여러번 디버깅을 해야 한다면 꽤 쓸모있다는 것을 알 수 있습니다.
일단, 새로 GDB를 띄워 디버깅을 시작했다고 합시다.
if (!packet_received) {
위 코드를 실행할 때, 강제로 packet_received를 1로 만들어, 패킷을 받는 부분을 건너뜁니다. 변수의 값 변경은 print 명령으로 쉽게 할 수 있습니다:
(gdb) p packet_received = 1
그리고 나서, received 배열을 아까 저장해 두었던 buggy.dat에서 다음과 같이
불러올 수 있습니다:
(gdb) restore buggy.dat binary received
Restoring binary file buggy.dat into memory (0xbfeda890 to 0xbfeda8b8)
이 외에도, GDB는 타 디버거에 비해 강력한 기능들을 많이 제공합니다. 다음 기회에 좀 더 알아보겠습니다.
'Computer_language > Debug' 카테고리의 다른 글
Pedro Vale Estrela - NS2 Debugging Page (0) | 2009.01.12 |
---|---|
[From NS-User] (0) | 2009.01.12 |
NS2 Programming (0) | 2009.01.12 |
ns2 gdb debug 관련 파일 (0) | 2009.01.12 |
Pedro Vale Estrela - NS2 Debug / BugFix Tutorial (OTCL + C++) (0) | 2009.01.12 |
core dump file이 발생하였을 경우 이것을 가지고 디버깅 하는 방법을 소개하고자 한다.
간단한 소스 코드를 보자.
#include <stdio.h>
int main(int argc, char* argv[]) {
char buffer[16];
buffer[80000] = 3;
return;
}
gcc -g -o main main.c
ps: -g 옵션은 디버그 정보를 넣어서 컴파일을 해 주는데, 이게 없으면 core 파일을 분석 할 수 없다.
frank@tightrope:~/tmp/gdbtest$ ./main
Segmentation fault
core dump file이 생성되지 않을 경우는 막아 놓았기 때문인데, ulimit 를 사용해서
이것을 풀어줄 수 있다.
ulimit -c 1024 (core file 용량을 정해준다.)
frank@tightrope:~/tmp/gdbtest$ ./main
Segmentation fault (core dumped)
frank@tightrope:~/tmp/gdbtest$ ls -als core
72 -rw------- 1 frank frank 147456 2006-01-13 21:19 core
분석을 해 보도록 하겠다.
frank@tightrope:~/tmp/gdbtest$ gdb ./main ./core
GNU gdb 6.3-debian
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...
Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1".
Core was generated by `./main'.
Program terminated with signal 11, Segmentation fault.
warning: current_sos: Can't read pathname for load map: Input/output error
Reading symbols from /lib/tls/i686/cmov/libc.so.6...done.
Loaded symbols for /lib/tls/i686/cmov/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
#0 main (argc=1, argv=0xbfca9944) at main.c:6
6 buffer[80000] = 3;
(gdb)
이걸 보고 우리는 main 함수에서 Segmentation fault로 종료되었다는 것을 알 수 있다.
함수 이름과 매개변수 값, 몇 번째 줄에서 segmentation fault가 났는지 보여준다.
이제는 조금 더 복잡한 소스를 디버깅해 보도록 해 보자.
#include <stdio.h>
int main(int argc, char* argv[]) {
// notice the erroneous "=", the coder meant "=="
if(argv = 0) return;
printString(argv);
return;
}
컴파일 하고 실행해 보자.
frank@tightrope:~/tmp/gdbtest$ gcc -g -o main main.c
frank@tightrope:~/tmp/gdbtest$ ./main
Segmentation fault (core dumped)
frank@tightrope:~/tmp/gdbtest$ ls -als core
68 -rw------- 1 frank frank 147456 2006-01-13 21:53 core
이제 디버깅을 해 보도록 하자.
frank@tightrope:~/tmp/gdbtest$ gdb ./main ./core
GNU gdb 6.3-debian
Copyright 2004 Free Software Foundation, Inc.
...
#0 0x08048396 in printString (string=0x0) at main.c:14
14 sprintf(string, "This is a test.\n");
#0 줄을 보면 string 이 널 포인터라는게 분명하다. 그런데 우리는 이게 어디서 왔는지
모른다. 단서는 파일 main.c에 14번 째 줄이라는 것과 main 에서 에러가 발생하지
않았다는 것이다. 그래서 우리는 backtrace를 할 것이다.
(gdb) backtrace
#0 0x08048396 in printString (string=0x0) at main.c:14
#1 0x0804837c in main (argc=1, argv=0x0) at main.c:8
'backtrace' 명령어는 함수를 연대기순으로 나열해 준다. 맨 위에 줄이 segmentation fault
가 발생한 소스이다. 저걸 보면 main.c:8 에서 main.c:14를 호출한 것을 알 수 있다.
더 많은 정보를 얻기 위해 'frame' 명령을 사용하도록 하자. 'frame' 명령은 'backtrace'
명령 실행으로 나온 항목들에 대해 더 많은 정보를 보여준다.
(gdb) frame 0
#0 0x08048396 in printString (string=0x0) at main.c:14
14 sprintf(string, "This is a test.\n");
(gdb) frame 1
#1 0x0804837c in main (argc=1, argv=0x0) at main.c:8
8 printString(argv);
이것을 보면 이미 main.c:8 에서 argv가 0으로 값이 넘어간 것을 알 수 있다.
*잡다한 tip
스레드를 사용해서 프로그래밍을 할 때 threadsafe 함수를 사용해야 한다. 예를 들어서 localtime
함수는 언젠가 프로그램과 충동할 것이다. 그 대신에 localtime_r 함수를 쓰는게 좋다. localtime_r
함수는 threadsafe 함수이다.
'Computer_language > Comfile' 카테고리의 다른 글
[Tip] win32k.sys 덤프가 뜰 경우..(메모리 테스트 프로그램들) [출처] [Tip] win32k.sys 덤프가 뜰 경우..(메모리 테스트 프로그램들) (0) | 2009.01.12 |
---|---|
프로그램 덤프 뜨기... (0) | 2009.01.12 |
NS2 - 무선환경 시뮬레이션 (0) | 2009.01.12 |
[EJB] 객체지향과 컴포넌트 프로그래밍 [출처] [EJB] 객체지향과 컴포넌트 프로그래밍|작성자 젠센쭈 (0) | 2009.01.12 |
유선과 무선 환경의 차이
- 노드 사이의 명시적인 링크가 존재하지 않음
- 라디오의 전송 범위 내에 노드들이 위치하면 통신 가능
- 무선상에서는 MAC 기술이 아주 중요
- NS2 유선 시뮬레이션 환경은 MAX이 존재하지 않음
- 무선상에서 노드는 이동성이 존재
- 라우팅
- 유선상에서는 특별히 라우팅을 설정하지 않아도 링크 설정관계를 통해서 최단 경로가 선택
- 무선에는 반드시 라우팅이 존재해야 함
- 주소
- 유선에서는 flat address
- 무선만 존재하면 flat address
- 유무선 연동인 경우는 hierarchical address
NS2에서의 유선과 무선의 차이
- C++ 상에서의
- 유선 : class Node
- 무선 : class MobileNode
- 노드 생성은 유무선 모두 $ns node로 하지만 무선에서는 node-config라는 추가 작업이 필요
- Trace
- $ns/common 에서
- 유선 : trace.{h, cc}
- 무선 : cmu-trace.{h, cc}
- $ns/common 에서
- 이동성
- 무선에서는 이동성을 지원
- 위치 정보가 중요
- 유선에서는 연결 구조가 중요, 노드의 배치는 중요하지 않음
- 무선에서는 위치에 따라서 전송 범위 내에 있는지 여부가 결정
- 그 외에는 유무선 모두 같은 네트워크 컴포넌트를 사용
node-config
* $ns가 앞으로 만들어질 노드에 대한 설정 정보들을 저장, 이후 만들어지는 노드들은 그 설정 정보들로부터 생성됨
* -adhocRouting 설정 정보로부터 유선 노드와 무선 노드 구별
* node-config를 이용해서 노드 설정을 바뀌었다면 바뀐 설정은 새로 만들어지는 노드부터 적용
Topography
* 지형도
* 영역을 만듦 ->무선 환경에서는 위치가 중요 정보
* set topo [new Topography]
* $topo load_flatgrid <x축 크기> <y축 크기>
God 객체
* Simulater와 마찬가지로 단 하나의 인스턴스만 존재, 없다면 에러
* 노드간 연결(라우팅 가능한지) 정보 제공
* 예) set god_ [create-god <모바일 노드 개수>]
* God 인스턴스 이름은 god_로 해야함 (일부 $god_로 사용)
- -adhocRouting : 라우팅 프로토콜 설정
- DSDV, AODV, TORA,, FLOODING,...
- -llType : 링크 레이어 설정
- LL
- -macType : 맥프로토콜 설정
- Mac/802_11, Mac/SMAC
- -propType : 경로손실타입
- Propagation/twoRayGround, Propagation/FreeSpace, Propagation/Shadowing,...
- -ifqType : 큐타입
- Queue/DropTail/PriQueue,...
- 애드혹라우팅 프로토콜이 DSR인 경우 반드시 CMUPriQueue로 해야 함
- -ifqLen : 큐길이
- 패킷 개수
- -phyType : 피지컬레이어타입
- Phy/WirelessPhy,...
- -antType : 안테나 타입
- Antenna/OmniAntenna
- -channel : 현재는 없어짐
- Channel/WirelssChannel
- -topoInstance : 전체 영역
- $topo
- -agentTrace : 트레이스 설정
- ON or OFF
- -routerTrace : 트레이스 설정
- ON or OFF
- -macTrace : 트레이스 설정
- ON or OFF
- -movementTrace : 트레이스 설정
- ON or OFF
NS2 무선환경 시뮬레이션 스크립터
$ns trace-all $trfd
$ns namtrace-all-wireless $namfd 1000 1000
$topo load_flatgrid 1000 1000
-llType LL \
-macType Mac/802_11 \
-propType Propagation/TwoRayGround \
-ifqType Queue/DropTail/PriQueue \
-ifqLen 50 \
-phyType Phy/WirelessPhy \
-antType Antenna/OmniAntenna \
-channel [new Channel/WirelessChannel] \
-topoInstance $topo \
-agentTrace ON \
-routerTrace ON \
-macTrace ON \
-movementTrace ON
set node_($i) [$ns node]
$node_($i) set Y_ [expr $i / 5 * 200]
$node_($i) set Z_ 0
}
$ns attach-agent $node_(0) $udp
$cbr set packetSize_ 500
$cbr set interval_ 0.1
$cbr attach-agent $udp
$ns attach-agent $node_(24) $null
$ns attach-agent $node_(20) $tcp
$ftp attach-agent $tcp
$ns attach-agent $node_(4) $tcpSink
$ns at 5.0 "$cbr stop"
$ns at 4.0 "$ftp stop"
$ns run
Max/802_11 Bandwidth
- basic rate, data rate 두가지 존재
- basic reate : RTS, CTS, ACK 을 전송하는 속도
- data rate : 실제 데이터를 전송하는 속도
- 설정하는 방법
- Mac/802_11 set basicRate_ 1Mb
- Mac/802_11 set dataRate_ 1Mb
- 기본값은 둘다 1Mbps
범위 설정
- 전송 범위 : 데이터가 성공적으로 수신되는 범위
- 캐리어 감지 범위 : 데이터를 성공적으로 수신하지는 못하지만 신호만 감지하는 범위 -> CSMA/CA 프로토콜의 CA
- 전송 범위와 캐리어 감지 범위는 수신 노드에서 받는 전파세기와 쓰레쉬홀드에 의해서 결정
- $ns/tcl/lib/ns-default.tcl
Phy/WirelessPhy set CSThresh_ 1.559e-11 # 수신한 전파의 세기가 이 값 이상이면 감지
Phy/WirelessPhy set RXThresh_ 3.652e-10 # 수신한 전파의 세기가 이 값 이상이면 성공적인 수신
Phy/WirelessPhy set bandwidth_ 2e6
Phy/WirelessPhy set Pt_ 0.28183815
Phy/WirelessPhy set freq_ 914e+6
Phy/WirelessPhy set L_ 1.0
- 다른 설정은 변경하지 않고 위 두개의 threshold만 변화시켜 범위 조절 가능
- $ns/indep-utils/propagation/threshold.cc
- 컴파일 후 threshold -m <경로손실모델> <범위> ->threshold
'Computer_language > Comfile' 카테고리의 다른 글
[Tip] win32k.sys 덤프가 뜰 경우..(메모리 테스트 프로그램들) [출처] [Tip] win32k.sys 덤프가 뜰 경우..(메모리 테스트 프로그램들) (0) | 2009.01.12 |
---|---|
프로그램 덤프 뜨기... (0) | 2009.01.12 |
[디버깅] core dump file을 분석해 보자 (0) | 2009.01.12 |
[EJB] 객체지향과 컴포넌트 프로그래밍 [출처] [EJB] 객체지향과 컴포넌트 프로그래밍|작성자 젠센쭈 (0) | 2009.01.12 |
[EJB] 객체지향과 컴포넌트 프로그래밍 [출처] [EJB] 객체지향과 컴포넌트 프로그래밍|작성자 젠센쭈
| Computer_language/Comfile 2009. 1. 12. 02:26우리나라에서도 컴포넌트에 대한 관심이 많이 높아지고 있습니다. 이것은 객체지향과 더불어 하나의 새로운 패러다임이라고도 합니다. 컴포넌트는 소프트웨어를 이제까지처럼 계획, 설계, 분석, 구현, 테스트하는 순차적인 개발 과정으로 보는 것이 아니라 레고 블럭이나 자동차 부품처럼 조립하는 개념으로 간주하기 때문에 현재 IT 산업을 이루고 있는 기존 틀과 구조를 가내 수공업 형태에서 ‘표준화’하고 ‘산업화’하는 데 그 의미가 있다고 하겠습니다.
이러한 컴포넌트는 인터넷이라는 환경의 부상으로 더욱 강력한 위치를 차지하게 됐습니다. 그것은 개발자에게도 새로운 개발 환경을 이해하도록 요구하고 있습니다. 컴포넌트 프로그래밍에서는 특정한 환경의 국소적인 이해보다는 시스템에 대해 전체적으로 이해할 수 있어야만 좋은 프로그램을 제작할 수 있습니다. 하지만 컴포넌트를 쉽게 이해할 수 있는 방법이 마땅히 있지 않습니다. 이번 연재에서는 객체지향과 컴포넌트를 연계해서 이해하고 간단하게 컴포넌트 환경을 살펴보겠습니다.
컴포넌트의 등장
컴포넌트라 함은 말 그대로 서로의 인터페이스를 연결하면 하나의 시스템으로 동작할 수 있는 환경의 구성 요소를 의미합니다. 몇 가지 컴포넌트의 결합으로 새로운 소프트웨어를 만들 수 있다는 생각은 그리 새로운 것은 아닙니다. 실제 우리 생활에서도 뮤직 컴포넌트처럼 서로 공통의 인터페이스로 연결해 새로운 시스템을 만드는 경우가 많습니다. 어릴 적 즐겨 가지고 놀았던 합체 로봇도 컴포넌트 시스템입니다. 그리고 비디오, 오디오, TV로 만드는 AV 시스템 역시 훌륭한 컴포넌트 시스템의 예입니다. 서로 다른 기능을 하는 두 요소를 결합해 새로운 기능을 만든다면 그것을 컴포넌트 시스템이라고 말할 수 있습니다.
우리가 사용하는 컴퓨터 시스템도 또 다른 컴포넌트 시스템의 예입니다. 컴퓨터 시스템은 컴퓨터 본체, 모니터, 키보드, 마우스, 스피커로 구성되고 사전에 규정된 모니터 케이블, PS/2 마우스, 키보드 포트, 오디오 잭 등을 통해 컴포넌트의 결합을 이룹니다. 하드웨어적인 컴포넌트는 표준화를 통해 산업화하는 하나의 전형적인 메커니즘입니다.
소프트웨어에서도 컴포넌트라고 하면 마찬가지 개념으로 생각해 볼 수 있습니다. 소프트웨어에 있어서 컴포넌트라는 개념은 RAD 툴의 등장과 더불어 탄생했다고 할 수 있습니다. RAD 툴의 등장 자체가 프로그래밍의 산업화 과정이라고 할 수 있습니다. 물론 소프트웨어 컴포넌트라는 개념이 갑자기 만들어진 것은 아닙니다. 이미 컴포넌트 이전에 라이브러리가 그러한 기능을 하고 있었습니다. 사전에 필요한 함수들을 만들어 놓고 프로그래밍에서 활용할 수 있도록 만들어 두는 것이 라이브러리인데, 컴포넌트를 이해하기에 앞서 우선 라이브러리를 이해하는 것이 좋습니다.
소프트웨어 라이브러리
소프트웨어 라이브러리는 매우 중요한 프로그래밍 자원으로 프로그래밍에 자주 쓰이는 함수나 클래스를 함께 묶어놓은 것입니다. 라이브러리 안에 있는 코드를 사용하기 위해서는 필요한 함수나 클래스의 사용법을 미리 숙지하고, 정의된 인터페이스를 통해 프로그래밍 모듈을 작성하고, 컴파일 과정에서 라이브러리와 작성한 모듈을 링크하는 작업이 필요합니다.
라이브러리를 많이 가지고 있는 친구는 빠르게 프로그램을 완성할 수 있는 반면에 라이브러리를 가지고 있지 않거나 기본적으로 언어 개발 툴에서 제공하는 라이브러리를 잘 이해하지 못하는 경우에는 이미 라이브러리에 있는, 그러나 본인은 알지 못하는, 함수를 직접 구현하기 위해 많은 시간을 소비하면서도 프로그램을 완성하지 못하기도 합니다.
기껏 만들고 있으면, 다른 친구가 “야, 이건 이미 기본 라이브러리에 있는 기능이야”라고 말해 당사자를 실망하게 만듭니다. 상황이 이렇다 보니, 한때는 소프트웨어 개발자들이 가지고 있는 소프트웨어 라이브러리의 양이 좋은 개발자와 나쁜 개발자로 나누는 기준이 되기도 했습니다.
일부 개발자 중에서는 편집광적으로 소프트웨어 라이브러리를 모으는 경우도 쉽게 찾아볼 수 있었습니다. 하지만, 개발 툴이 커지고 대규모가 되면서 대부분의 필요한 라이브러리들은 개발 툴에 포함되어 제공됐습니다. 최근에는 개발 툴이 제공하지 않는 추가적인 라이브러리를 이용하는 비중은 틈새시장 정도로 무척이나 작아졌습니다. 그만큼 소프트웨어 라이브러리가 정형화됐다고 할 수 있습니다. 하지만, 여전히 라이브러리에 대한 충분한 사전 지식 없이 소프트웨어 라이브러리를 쉽게 사용한다는 것은 어려운 일입니다.
컴포넌트와 라이브러리
인터넷의 보급과 더불어 누구나 쉽게 라이브러리를 인터넷에서 찾아 사용할 수 있게 됐고 부담 없는 수준에서 라이브러리를 구입할 수 있습니다. 그리고 오픈 소스 정책으로 인해 많은 라이브러리 소스가 공개되면서 라이브러리의 가치는 지속적으로 떨어졌습니다. 하지만 이것은 다른 한편으로 게으른 개발자를 양산했습니다. 그냥 모든 것은 인터넷에 있다고 생각하는 나머지 라이브러리 사용법조차 알지 못하는 개발자가 많아진 것입니다.
이러한 문제점을 새롭게 해결하고자 나온 것이 바로 컴포넌트입니다. 컴포넌트는 컴포넌트 스스로가 어떤 인터페이스를 가지고 있는지 개발자에게 알려줄 수 있습니다. 그리고 속성을 변경해 자신의 초기값을 조정할 수 있기 때문에 커스터마이징이 쉽습니다. 이러한 사용자 환경이 만들어낸 것이 애플리케이션을 빠르게 제작할 수 있는 RAD 툴입니다. RAD 툴 안에서는 미리 작성되어 있는 컴포넌트들을 통해 애플리케이션을 쉽게 작성할 수 있습니다.
컴포넌트의 기본적인 개념은 소프트웨어 라이브러리와 유사합니다. 라이브러리가 사전에 필요한 코드를 작성해놓고 나중에 컴파일 과정에서 연결해 사용하는 것이라면, 컴포넌트는 사전에 정의된 컴포넌트 인터페이스를 만족하도록 작성되고, 이를 통해 프로그래밍 과정에서 연결해 사용할 수 있게 되어 있습니다. 따라서 컴포넌트의 동작 상황을 개발 당시에 확인할 수 있다는 장점이 있습니다. 그리고 대부분 비주얼한 컴포넌트를 제공하기 때문에 GUI까지 한꺼번에 해결해주기도 합니다.
최근에 나온 개발 툴은 대부분 자신들의 컴포넌트를 제공합니다. 하지만 컴포넌트가 단지 최신 라이브러리라는 의미는 아닙니다. 그것은 현재 시스템이 점점 복잡해지면서 시스템을 구축할 때 모든 기능을 새롭게 구축하면 비용이 많이 들기 때문에 필수적이고 복잡한 환경은 사전에 만들어 놓고 적용하려는 시스템에 따라 변화되는 부분만을 새롭게 작성하여 동작할 수 있도록 하는 데 사용하는 것입니다. 아마도 이것은 뮤직 컴포넌트 개념보다는 DVD 플레이어와 DVD의 관계라고 말할 수 있을 것입니다.
컴포넌트의 구성
그렇다면 소프트웨어 컴포넌트는 무엇으로 구성될까요? 컴포넌트는 우선 서로 다른 컴포넌트를 연결하는 입출력 인터페이스가 필요합니다. 그리고 기본적인 상태를 정의할 수 있는 프로퍼티가 있습니다. 컴포넌트는 잘 정의된 인터페이스를 통해 사전에 구현한 소프트웨어 모듈입니다. 예전에는 특정한 툴 환경에서만 의미 있는 컴포넌트들이 있었는데, 지금은 특정한 언어와 상관없이 사용할 수 있는 컴포넌트 구조들도 있습니다.
대표적으로 COM(Common Object Model)은 윈도우 환경에서 빼놓을 수 없는 핵심적인 컴포넌트 구조를 제공합니다. COM은 윈도우의 핵심 커널을 제외하고는 대부분의 환경에서 사용되는 모델입니다.
그리고 EJB(Enterprise Java Beans)는 자바 프로그래밍 언어를 통해 미들웨어를 구현할 수 있도록 제공하는 모델입니다. 트랜잭션, 보안, 데이터베이스 접속 등을 쉽게 이용할 수 있도록 하는 환경을 제공하고, 이를 컴포넌트화해 소프트웨어 모듈을 개발할 수 있게 하는 것입니다.
객체지향과 컴포넌트
객체지향은 소프트웨어를 행동과 상태 기반의 객체로 정의해 재사용성을 높이는 것이 목표입니다. 컴포넌트는 사전에 정의된 인터페이스를 통해 즉각 실행할 수 있는 컴포넌트로 생산하여 재사용성을 높이는 것입니다. 재새용성을 높인다는 것에 대해서는 그 목적이 동일하지만 접근 방법의 차이가 있다고 할 수 있습니다. 객체지향에서는 새로운 데이터 형을 작성하는 것부터 출발하는데, 컴포넌트는 잘 짜여진 인터페이스를 사전에 정의하고, 이를 통해 필요한 동작을 구현하는 것부터 출발합니다.
◆ 클래스 = 데이터 + 메쏘드
◆ 컴포넌트 = 특성 + 인터페이스 + 로직 + 이벤트
이와 같이 컴포넌트는 서로의 기능을 쉽게 연결할 수 있는 인터페이스가 가장 중요한 위치를 차지합니다. 객체지향과 컴포넌트가 만나는 위치는 인터페이스입니다. 컴포넌트의 인터페이스는 객체지향의 메쏘드와 유사합니다. 물론 객체지향 언어에서 메쏘드와 인터페이스는 엄밀한 의미에서 구별되지만 실제로는 그 기능이 비슷하다고 할 수 있습니다.
차이점은 인터페이스가 아니라 접근 방법에 있습니다. 컴포넌트는 컨테이너라는 컴포넌트가 동작할 수 있는 환경을 제공하고, 이 구조에 맞는 다른 컴포넌트들이 서로 연결되어 동작할 수 있게 해주는 개발 환경이라면, 객체지향의 기본 개념은 메쏘드 재정의나 클래스 확장을 통해 기존 클래스를 재사용할 수 있도록 하는 것입니다.
컴포넌트 소프트웨어 환경
컴포넌트는 크게 비주얼 컴포넌트와 미들웨어 컴포넌트로 나눌 수 있습니다. 비주얼 컴포넌트는 대부분의 RAD 툴이 제공하는 각종 UI와 이를 이용한 기능성 컴포넌트입니다. 반면에 미들웨어 컴포넌트는 미들웨어 위에서 동작하는 컴포넌트로 특별한 UI없이 동작할 수 있습니다. 최근 웹 환경 개발이 강화되면서 중요한 컴포넌트로 자리를 잡았습니다. 여기서 중요한 것은 비주얼 컴포넌트와 미들웨어 컴포넌트는 개념상 비슷하지만 그 내용은 크게 다르다는 것입니다.
비주얼 컴포넌트
비주얼 컴포넌트는 말 그대로 시각적인 컴포넌트입니다. 비주얼 컴포넌트 소프트웨어로는 델파이, 비주얼 베이직, 비주얼 에이지 등이 대표적입니다. 이들은 대부분 비슷한 GUI를 가지고 컴포넌트를 마우스를 통해 소프트웨어 폼에 쉽게 부착하고, 프로퍼티를 조절하고, 다른 컴포넌트와 연결해 새로운 소프트웨어를 만들 수 있습니다. 비주얼 컴포넌트는 대부분 사용자 인터페이스와 관련이 있습니다. 여기서는 이에 대해 구체적으로 다루는 것은 생략하겠습니다.
미들웨어 컴포넌트
미들웨어 컴포넌트는 시각적인 인터페이스를 제공하지 않는 컴포넌트입니다. 미들웨어 컴포넌트는 컴포넌트 환경이 제공하는 다양한 기능을 이용해 실제 데이터의 동작에 대한 로직만을 제공해 소프트웨어가 완성될 수 있게 합니다. 미들웨어 컴포넌트는 대부분 웹 인터페이스를 통해 사용자와 인터페이스하기 때문에 사용자는 웹 브라우저로 웹 서버에 접속하면 내부적인 미들웨어 컴포넌트에 의해 동작되는 결과들을 확인할 수 있습니다. 아마도 최근에 비주얼 컴포넌트보다 미들웨어 컴포넌트가 더 강화되는 이유가 이 때문이 아닐까 생각합니다. 미들웨어 컴포넌트의 대표적인 두 가지가 COM+와 EJB입니다.
COM+
COM+는 마이크로소프트의 MTS(Microsoft Transaction Server)의 최신 버전입니다. 1999년에 발표됐으므로 약 3년 정도의 시간이 지났습니다. COM+는 닷넷 기반의 애플리케이션과 COM을 하나로 묶는 것으로 관리 기능, JITA(Just-In-Time Activation), 객체 풀링, 트랜잭션 처리, 동기화, 보안, 컴포넌트 큐 관리, 이벤트 처리 등 다양한 기능을 제공합니다. COM+에는 다음과 같은 구성 요소가 있습니다.
◆ COM+ 대리 실행 모듈(dllhost.exe)
◆ COM+ 클래스 로딩 및 리모트 프레임워크(ole32.dll)
◆ 컨텍스트 오브젝트와 랩퍼 프록시
◆ COM+ 서버 컴포넌트
◆ COM+ 클라이언트
◆ COM+ 런타임, 서비스 컨트롤 관리자(SCM), 분산 트랜잭션 관리자(MS-DTC), 메시지큐(MSMQ), 트랜잭션 통합 관리자(COM-TI)
COM+는 조금 복잡한 동작을 요구합니다. 기본적으로 COM+ 서버 컴포넌트는 OLE32.DLL 및 DLLHOST.EXE로 구성된 컨테이너에 의해 호출되고, 다시 컨텍스트 객체에 의해 처리되도록 고안됐습니다. 이것은 COM+가 기존 MTS 및 다른 환경도 함께 수용할 수 있는 환경을 만들다 보니 더 복잡한 환경을 제공하는 것으로 보이지만 실제로는 기존 COM 환경에서 그리 많은 변화가 있던 것은 아닙니다.
COM+의 특징 중 하나는 스스로 자신을 설명할 수 있는 컴포넌트라는 점입니다. 이것은 프로퍼티와 달리 애트리뷰트를 제공합니다. 애트리뷰트는 컴포넌트에 런타임 특성을 설정할 수 있는 것을 의미합니다. 이것은 특정한 기능이 작동하도록 컴포넌트를 조절할 수 있는 기능입니다. 예를 들어, 데이터베이스 연결에 사용하는 문자열을 런타임 환경에서는 관리자에 의해 변화할 수 있는 값이 되는데 이것은 자바 환경에서 상태 저장·복원과 관련이 있는 것입니다.
COM+는 또한 큐 컴포넌트 기능을 제공합니다. 큐 컴포넌트는 컴포넌트와 애플리케이션의 상호작용이 실시간에 이루어지지 않더라도 큐를 이용해 컴포넌트가 다시 기동했을 때 상호작용이 다시 일어날 수 있게 하는 것입니다. 이벤트 메커니즘은 자바의 이벤트 리스너 모델처럼 다양한 이벤트 채널을 통해 이벤트를 전달할 수 있게 되어 있습니다. 이 밖의 다른 기능은 COM+의 참고자료를 이용하기 바랍니다.
EJB
EJB는 자바 표준 미들웨어 컴포넌트 구조입니다. EJB는 다음과 같은 구성요소로 이루어져 있습니다.
◆ EJB 서버
◆ EJB 컨테이너(EJB 서버 위에서 동작)
◆ EJB(EJB 컨테이너 위에서 동작)
◆ EJB 클라이언트
◆ 기타 구성 요소 : JNDI(Java Naming and Directory Inter face), JTS(Java Transaction Service)
이를 그림으로 표현하면 <그림 4>와 같습니다. EJB 서버는 CORBA의 ORB(Object Request Broker)와 비슷한 기능을 제공합니다. 시스템 실행환경을 제공하고, 멀티프로세싱, 부하분산, 장치제어, 네이밍 및 트랜잭션 처리 등을 제공하며, EJB 컨테이너를 올릴 수 있게 해줍니다. EJB 컨테이너는 EJB와 외부 세계의 인터페이스를 제공합니다. EJB 클라이언트는 결코 직접 EJB와 연결되지 않습니다. EJB를 연결할 수 있는 메쏘드를 EJB 클라이언트에 제공하는 것이 바로 EJB 컨테이너입니다.
EJB는 크게 두 종류가 있습니다. EJB의 상태가 지속적으로 유지되는 경우와 매번 초기화되는 경우가 있습니다. EJB의 상태가 유지되려면 가장 최근의 EJB 속성을 저장하거나 복구하는 기능을 제공해야 합니다. 이러한 기능은 EJB 컨테이너 인터페이스를 통해 EJB 서버가 제공합니다. EJB 클라이언트는 컴포넌트를 이용하는 주체이며, EJB는 컴포넌트 자체입니다. 이러한 구조는 대부분의 컴포넌트 구조의 특징입니다.
EJB는 EJB 클라이언트의 요청에 의해 그때마다 생성되는 세션 빈과 상태를 공유하는 엔티티 빈으로 나눌 수 있습니다. 엔티티 빈은 항상 상태를 가지고 있으며, 시스템이 동작하는 한 계속 살아있는 상태가 됩니다. 세션 빈은 상태를 가지고 있을 수도 있고, 상태가 없을 수도 있습니다. 이러한 상태 저장 및 복구는 그 주체가 누구이냐에 따라 컨테이너 관리형 상태 유지와 빈 관리형 상태 유지로 나눌 수 있습니다. 쉽게 이야기하면 저장 및 복구를 컨테이너가 하면 컨테이너 관리형 상태 유지이고, 저장 및 복구가 빈에 의해 수행되면 빈 관리형 상태 유지입니다. EJB는 *.ser 파일에 의해 동작 가능하도록 배치(deploy)할 수 있습니다. 이 파일은 다음과 같은 엔트리로 지정되어 동작합니다.
Name: ~bean/CompanyAccssRight.ser
Enterprise-Bean: True
컴포넌트의 미래
정보통신부는 컴포넌트 산업을 육성하기 위해 향후 3년간 공용 컴포넌트 개발은 물론 공용 컴포넌트 뱅크 마련, 컴포넌트 유통 시스템 구축, 컴포넌트 품질 평가 및 인증제도 확립, 컴포넌트 가격 산정 및 라이선스 규정 수립, 관련 인력 양성 등에 박차를 가할 계획이라고 합니다.
현재 국내 시장에 나와 있는 컴포넌트는 약 150종에 불과하지만 올해 말이면 1000개 가량의 컴포넌트가 개발될 것이라고 예견하기도 합니다. 현재 국내 신생 업체들을 중심으로 자바 컴포넌트 기술을 이용해 상용 애플리케이션을 개발하는 사례가 늘고 있으며 특히 전사적자원관리 시스템부터 개발 툴, XML 솔루션, 검색엔진, 통신용 소프트웨어, 인터넷 구축 툴, 언어처리 모듈, 지식관리, 고객관리 등의 분야에 이르기까지 다양한 분야에서 개발이 진행되고 있다고 합니다.
하지만 컴포넌트가 일반적인 개발 환경이 되기 위해서는 넘어야 할 과정이 많이 있습니다. 아직 교육 환경이 컴포넌트 개발 환경에 맞게 빠르게 제공되지 못하는 실정입니다. 대부분의 개발자는 전체 컴포넌트 환경을 이해할 수 있는 수준이 되지 못하고 있습니다. 그것은 소프트웨어 시장의 요구를 교육 환경이 미처 뒷받침해줄 수 없을 정도로 빠르게 변화하고 있다는 것을 의미합니다. 필자의 생각으로는 컴포넌트가 일반적인 개발 환경에 되려면 좀더 많은 시간이 필요할 것입니다. 객체지향이 20년이 지나서야 일반적인 개발환경이 되는 것을 보면 새로운 개념이 쉽게 보편화되지는 않기 때문입니다. 하지만 컴포넌트가 일반화되는 데 20년이 걸릴 것이라는 것은 아닙니다. 그보다 훨씬 빠른 시간에 도달할 것입니다. 하지만 이 자리에서 그 시기가 언제라고 언급하는 것은 별 의미가 없다고 생각합니다.
컴포넌트에 대한 깊은 이해와 적용 필요
컴포넌트와 객체지향은 밀접한 관계가 있다고 말할 수 없지만, 그 목적이 비슷하기 때문에 객체지향과 컴포넌트가 연결되는 다양한 시도가 있었습니다. 대부분의 개발 툴이 객체지향 언어를 지원하고 컴포넌트 구조를 제공함으로써 더욱 편리하게 프로그래밍이 가능하도록 하고 있습니다. 비주얼 컴포넌트는 대부분의 개발 툴이 제공하는 요소가 됐습니다. 하지만 이것은 특정한 개발 환경에서만 사용할 수 있는 경우가 많고, 대부분 웹 인터페이스를 사용하기 때문에 미들웨어 컴포넌트의 중요성이 더 커지고 있습니다. 미들웨어 컴포넌트는 윈도우 기반의 COM 계열, 자바 기반의 EJB 계열, OMG의 CORBA 계열이 있습니다.
이들을 간략하게 살펴보았는데, 실제 체계적인 학습 없이 빠른 시간에 컴포넌트 환경을 이해한다는 것은 매우 어려운 일입니다. 개발자들이 컴포넌트 환경을 이해하고 업무에 활용하기 위해서는 앞으로 많은 교육 기회가 주어져야 할 것으로 보입니다. 그런 의미에서 서로 다른 컴포넌트 환경은 경쟁자라기보다는 컴포넌트라는 하나의 거대한 목표를 향해 달리는 협력 주자라고 할 수 있습니다.
정리 : 송우일 wooil@sbmedia.co.kr
출처 : http://www.imaso.co.kr/
'Computer_language > Comfile' 카테고리의 다른 글
[Tip] win32k.sys 덤프가 뜰 경우..(메모리 테스트 프로그램들) [출처] [Tip] win32k.sys 덤프가 뜰 경우..(메모리 테스트 프로그램들) (0) | 2009.01.12 |
---|---|
프로그램 덤프 뜨기... (0) | 2009.01.12 |
[디버깅] core dump file을 분석해 보자 (0) | 2009.01.12 |
NS2 - 무선환경 시뮬레이션 (0) | 2009.01.12 |
1. 자바 애플릿.클래스 정보
class파일이란?
확장자가 class인 파일로 파일형식은 "파일이름.class" 입니다.
(예: lake.class, snow.class )
이 파일은 애플릿 효과를 구사하는데 있어서 가장 중요한 파일로 일반인들은 만들기 어렵고 프로그래머들이 개발해 놓은 것을 애플릿을 구사할 때 code로 사용하게 됩니다. 예를 들면 눈오는 효과를 구사하고 싶으면 snow.class를 code로, 물결 효과를 구사하고 싶다면 lake.class를 code로 (참고: anfy사에서 개발한 눈 내리는 효과 클래스 파일은 ansnow.class, 물결 효과는 anlake.class.) 사용하면 됩니다.
애플릿의 실행 방법
애플릿이 실행 되려면 기본적으로 세 개의 파일이 있어야 합니다.
위에서 말씀드린 class 파일과 이미지 파일(보통jpg,gif파일을사용함), 그리고 매개변수를 설정한 html(웹페이지형식)파일 입니다.
위 세 개의 파일이 같은 디렉토리(경로) 즉, 같은 폴더 내에 있어야 실행이 됩니다.
홈페이지를 가지신 분들은 알겠지만 ftp나 기타 홈계정에서 제공하는 홈피 관리프로그램을 실행해보시면 윈도우 탐색기처럼 디렉토리가 형성되어 있을 것입니다.
자신의 컴퓨터에서 애플릿 작업을 하고 자신의 홈피에 업로드할 때 위의 세 파일을 같은 장소(폴더)에 올려야 되지요--->'중요'
그렇다면 class 파일은 어디서 구해오고, html파일을 어떻게 만드느냐...
html 파일을 직접 만들기란 시간적 낭비일 뿐만 아니라 용어까지 모두 알아야 합니다. 그렇기 때문에 이미 만들어진 HTML 파일을 권해보도록 하겠습니다. 우선 아래 사이트에 가셔서 애플릿마법사 Anfy 1.4.5 를 다운받으셔서 사용해 보세요.
http://www.anfyteam.com/
단계별로 자신이 원하는 그림을 넣을 수도 있고 매개변수도 설정할 수 있습니다.
한글도 지원되기 때문에 글을 넣을 수 있는 애플릿에서는 글도 넣을 수 있답니다.
좋은 효과를 보실려면 매개변수를 바꿔가면서 많이 연습해 보시는 것이 좋겠죠?
설정이 다 끝나면 복사탭을 클릭하시고 자신의 컴퓨터 일정한 폴더에 붙여넣기를 하시면
필요한 모든 파일이 생기게 됩니다.
(사용이미지가 들어있는 폴더에 붙여 넣으세요.)
여기에 생긴 파일들(이미지파일포함)을 모두 홈피계정에 올리시면 됩니다.(같은 디렉토리에)
html 파일은 실행 파일이므로 애플릿을 보실려면 그 파일에다 링크를 걸어야겠죠?
그럼 codebase란 무엇일까?
인터넷 여기 저기를 다니다 멋진 애플릿을 보면 어떻게 내 홈에 올려 놓을 수는 없을까? 또는 자신이 애플릿을 아주 멋지게 만들었는데 다른 게시판에 올릴 수는 없을까 하는 생각을 하시게 될 겁니다.
그런데 애플릿은 같은 디렉토리 내에서만 실행이 되기 때문에 html 문서를 다른 곳으로 옮기면 class파일이나 이미지 파일을 읽어올 수 없게 되지요.
(유리꽃 Hous에 있는 애플릿은 모두 절대 경로를 사용했기 때문에 다른 곳에서도 실행이 됨.)
그래서 필요한 것이 codebase(클래스파일과 이미지파일이 들어있는장소) 입니다.
즉 codebase는 class파일이 업로드된 폴더 주소(경로)를 말하는 것이죠.
* codebase="해당애플릿 class파일과 이미지가들어있는 경로"
위와 같은 형식으로 실행 html 소스에서 클래스 파일 경로 를 수정해 주시면 되지요.
이상 웹사이트에서 애플릿 실행 방법을 알려드렸는데 이해가 가시는지 모르겠습니다.
아래 클래스 파일을 다운받을 수 있는 곳에 가셔서 더 많은 것을 살펴보시기 바랍니다.
class파일을 다운 받을 수 있는 곳
<환상여행>
Coowild.class 를 다운받을수 있는곳입니다..
* http://chunma.yu.ac.kr/~fworkers/test_cw.htm
* http://www.coolshare.com/ftp/adware/java/coowild.zip
* http://www.winsite.com/info/pc/win95/netutil/coowild.zip
* http://www.winsite.com/info/pc/winnt/netutil/coowild.zip
* ftp://ftp.simtel.net/pub/simtelnet/win95/java/coowild.zip
<픽쳐메뉴 홈페이지>
각종 픽쳐메뉴를 제공해 주는 외국 싸이트 입니다.
* http://www.javabase.fsnet.co.uk/
Anfy 프로그램을 내 컴퓨터에 다운받아
설치한후에 애플릿 효과를 직접 만들수 있는 싸이트 입니다.
외국싸이트이지만 한국어를 지원해 주고 있답니다..
* http://www.anfyteam.com/
이 외에 자바 애플릿의 자료를 구하시려면 검색엔진에서 각종 클래스의 이름만 넣고 검색을 하셔도 수백개의 사이트를 찾을 수 있을 것입니다. 많은 참고 바랍니다.
'Web > Info' 카테고리의 다른 글
온라인 쇼핑몰 웹 디자인 동향 2009 (0) | 2009.02.17 |
---|---|
서블릿 (0) | 2009.01.12 |
HTML, ASP, PHP, JAVASC (지식카페 퍼옴) (0) | 2009.01.12 |
Servlet(http://kmh.ync.ac.kr/encycl/terms/termsJ/jsp2.htm) (0) | 2009.01.12 |
무료 웹호스팅 000webhost.com (1.5GB 용량, 100GB 트래픽) 웹사이트 소개 & 활용 (0) | 2009.01.12 |
각 회사의 영업 부서와 마케팅 부서에서 자사의 기술을 더 강조하기 위해 조장하는 과대 광고나 홍보에 신물이 났는가? 자바 기술은 언론에서 긍정적으로 평가받기도 하고 부정적으로 평가받기도 했다. 언론은 이 기술에 대해 상반되는 정보를 제공하여 사람들을 혼란스럽게 만들었다. 이 글에서는 자바를 현실적으로 평가하고 "자바를 사용할 때 front end와 관련해서 우리에게는 어떤 옵션이 있는가?" 란 질문에 답을 제공해 볼 생각이다.
서버단 개발에서 자바를 사용할 때 기존의 다른 기술에 비해 자바가 훨씬 많은 이점을 제공하기 때문에 이 부분에 있어서는 확실한 입지를 굳히고 있긴 하다. 그러나, 실질적으로 모든 애플리케이션이 유저 인터페이스와 front-end 프리젠테이션을 어떤 형태로든 가진다. 우리 대부분은 클라이언트단에서의 자바 사용을 언론에서 맹공격하고 있는 것에 대해 익숙하다. (remember how many times we've heard about "nails in the coffin of Java"?) 언론에서는 HTML 기반 front end 를 제외한 그 밖의 다른 기술을 사용하는 것이 제 무덤을 파는 것과 같다고 말하고 있다.
그러나 사실은 기존의 HTML 클라이언트를 사용하는 것 외에도 다른 옵션들이 있다. 필자는 Java 기반 애플리케이션에서 유저 인터페이스를 개발하기 위해 사용할 수 있는 세 가지 주요 솔루션에 대해 설명할 것이다. 우선 JavaServer Pages™ 과 서블릿에서 HTML 을 사용하는 것에 대한 장단점을 살펴볼 것이다. 다음으로, 약간 놀랍게 들릴 수도 있겠지만, 초기 약속 중 하나인 "GUI 애플릿을 통한 인터렉티브 Web"이 가능하다는 점을 증명할 것이다. 끝으로, XML과 이 언어와 함께 출시된 그 밖의 고급 기술들에 대해 설명할 것이다. 이제 여러분이 정말로 알고자 하는 문제로 넘어가자 - 기술적 사실들.
HTML Client with JSP/Servlets
독자들 대부분이 지금쯤이면 몇몇 종류의 서블릿과 JSP 를 개발해 보았을 것이며, HTML 기반 유저 인터페이스의 장단점을 실제로 느껴보았을 것이다. HTML 을 선택해야 하는 가장 중요한 이유중의 하나는 HTML 이 어떠한 플랫폼에서도 다 실행될 수 있다는 점이다. (모든 브라우저가 Java 를 지원한다고 말할 수 있다면 얼마나 좋겠는가?) 기본 HTML 은 손쉽게 표준화되고 너무 복잡해지지 않으면서도 긍정적인 효과를 얻을 수 있다.
또한 HTTP/HTTPS 프로토콜의 단순함을 고려하면 다양한 네트워크 설정이나 방화벽에서 프로그램 했을 때 어떤 일이 일어날 지를 예측할 수 있는 장점이 있다. 그러나 이 지구상의 모든 것이 그러하듯이 이런 장점이 공짜로 얻어지는 것은 아니다. HTML 의 단점은 사용자와의 상호작용이 없으며, 사용자의 리퀘스트에 대한 리스펀스를 보낼 때 마다 서버를 거쳐야 한다는 것이다.
물론 JavaScript도 존재한다. 그러나 여러분이 프로그래머로써 일하면서 강제적인 필드를 enforce 하고 간단한 프롬프트를 생성하며, 또한 이 둘을 모든 브라우저에서 동일한 방식으로 실행되게 하는 것 보다 더 어려운 작업을 해 본 경험이 있는가? 단순함이 늘 좋은 것은 아니다. 간단히 말해서 JavaScript 는 꼬이지 않은 인터렉티브 로직을 static 한HTML 에 추가하기에 적절한 언어이지만 사용자가 놀랄정도로 잘 구성된 고차원의 유저 인터페이스를 만들 능력은 없다.
여러분 스스로가 디지털화되어 사이버공간에서 살고 있지 않는 한, 혹은 집에 T-1 전용선이 설치되어 있지 않는 한, 웹페이지가 로드되기를 기다리거나 서버가 쓸데없는 페이지를 거치게 만드는 답답함을 느껴보았을 것이다. thin 클라이언트가 다수의 인터렉티브 하지 않은 유저 인터페이스의 프리젠테이션을 멋지게 소화할 수 있는 방안을 제시하기 하지만, 기존의 fat 클라이언트가 똑똑함(intelligence)이란 측면에서는 thin 클라이언트를 능가한다. 예를 들어 온라인 브로커는 HTML 클라이언트보다 훨씬 잘 실행되는 애플리케이션 클라이언트를 active trader 에게 제공한다. Netscape™ Communicator 와 MS Outlook 등의 이메일 클라이언트는 웹 기반 이메일 포털에 비해 훨씬 더 사용자 친화적이다.
HTML 프론트 엔드를 개발하기 위해 Java 를 사용하는 것은 현명한 일이다. 왜냐하면 HTML 이 플랫폼에 구애 받지 않으면서 컨텐트를 전달하고 보여줄 수 있듯이 Java 서블릿과 JSP를 사용하면 거의 모든 환경의 운영 체제에서 실행될 수 있는 서버 단 로직을 개발할 수 있다. 풍부한 Java API와 웹 서버 및 애플리케이션 서버 벤더들이 Java 를 지원하고 있다는 점을 고려할 때 Java 는 확장성 있는 (scalable) 웹 싸이트를 구축하기 위한 최상의 선택이다.
요약하자면, 서브릿을 사용하는 HTML 프론트 엔트는 static 컨텐트를 개발하기 위한 아주 좋은 방법이다 (그리고 당부하건데, 페이지 디자인은 제발 전문 디자이너에 맡기도록 하자). 그러나 이 thin 클라이언트는 유저의 액션에 재빨리 리스펀스를 보내야 한다거나 데이터를 빠르게 조작하는 복잡한 로직을 사용할 때는 그리 좋은 성능을 제공하지 못한다.
Swing GUI Client
여러분 중 Java 애플릿을 여러분의 클라이언트로 사용할 자신이 있는 사람이 몇몇이나 되는가? 물론 HTML 기반 유저 인터페이스를 사용하는 것이 확실히 안전하긴 하지만, 그렇다고 이것이 최상의 선택인가?
AT&T 의 자회사인 Telecorp PCS 사는 자사의 점포와 키오스크에서 휴대폰을 구매하고자 하는 고객들이 제공한 정보를 저장하고 이들의 신용 정보를 조회하며, 그 자리에서 휴대폰을 개통해 줄 수 있는 애플리케이션을 개발해야 했다. 이 클라이언트 애플리케이션은 유저 인풋이 정확한지를 검증하는 작업 외에도 분류, 필터링 및 그 밖의 표준 테이블 기능을 가진 인터렉티브 보고서를 만들어 낼 수 있어야 했다. 거기다 고객에게 휴대전화가 개통되었다는 사실을 인스턴트 메시지로 통보하고 이를 디스플레이 해야 했다.
이를 HTML 로 구현할 수 있을까? 가능하긴 하지만, 구현하기가 까다롭고 늘 네트워크를 사용해야 하기 때문에 개발 속도가 느려진다. 그래서 개발 팀은 자바를 사용하여 자바가 원래 의도했던 것 - 인터렉티브 애플릿 - 을 구현해 보기로 했다. 결과는 대성공이었다. 이 애플릿은 Swing 을 사용하여 개발되었고 Java Plugin을 사용해 배포되었다. Swing UI 클래스를 사용하여 유효하지 않은 인풋이 들어오면 그 자리에서 이를 점검하고 사용자가 계속 진행할 수 있거나 진행할 수 없을 때 활성화되고 비활성화 되는 버튼과, 칼럼의 헤더를 클릭하기만 하면 자동으로 분류되는 표(테이블)를 손쉽게 만들 수 있었다. 그리고 인스턴트 메시지는 다이얼로그 창을 생성하는 RMI callback 으로 처리했다. 물론 사용자들은 대단히 만족스러워 했다.
여러분 대부분이 Java 를 처음 배울 당시 애플릿을 사용해 본 경험이 있을 것이다. 우리는 브라우저마다 나타나는 차이와 애플릿 다운로드 시간, 성능 그리고 그 밖의 모든 문제들을 해결하느라 많은 시간과 노력을 허비했었다. 클라이언트 단 자바에 대한 비판은 거의대부분 객관적인 의견들이다. 그렇지만, 확실히 많은 것이 변화했다. 썬 마이크로 시스템즈 사는 자바의 코드와, 더불어 우리의 삶을 향상시키기 위해 많은 노력을 기울였다. 이제부터 Swing UI 를 사용하는 것이 왜 고려해 볼만한 옵션인지 설명하겠다.
Swing and its Deployment Models
Swing 의 내부 아키텍쳐와 Swing 클래스 및 인터페이스를 설계하고 그 디자인 패턴을 구현하는 데 들인 공을 필자가 굳이 칭찬할 필요도 없다. Swing 은 아마도 필자가 본 것 중 가장 깨끗한 (cleanest) 윈도우잉 시스템의 구현이다. Swing 은 컨테이너간, 컴퍼넌트간, 그리고 UI 요소들 간의 관계를 잘 정의된 놓았다. Swing 의 아키텍쳐는 데이터를 프리젠테이션과 그 데이터의 조작에서 분리하는 방식인 Model-View-Controller (MVC) 디자인 패턴에 기반을 두고 설계되었다.
대부분의 Swing 모델은 다양한 UI 요소들에 의해 공유된다; 가령, JTable 은 JList 와 JTree 가 사용하는 것과 동일한 selection 모델을 사용한다. 이런 점 때문에 Swing 은 배우고 사용하기가 쉽다. Command, Observable, Listener 등의 패턴은 유연성과 바람직한 객체 지향 디자인을 제공한다. 아마도 Swing의 유일한 구조상의 단점이라면 모든 이벤트가 하나의 EventDispatch 스레드에 전달되기 때문에 전체 GUI 클라이언트가 단일 스레드로 실행되게 만든다는 점일 것이다. 그렇지만 EventDispatchThread 대신에 다른 스레드를 사용해 유저 명령에 리스펀드하게 만들면 이런 단점도 쉽게 극복할 수 있다.
모든 출시된 JDK 는 Java 와 Swing 을 향상시킨다. JDK 1.3에서 Swing 과 관련해서 의 가장 중요한 개선점은 성능과 메모리 점유 및 인풋 유효성 점검 프레임워크 (input validity framework) 이다. 성능과 메모리의 향상은 놀라울 정도이다. 필자의 회사에서 사용하는 클라이언트를 JDK 1.2.2 에서 1.3으로 변경하고 나서 메모리의 사용이 적어도 30% 이상 감소했다; 몇몇 애플리케이션은 훨씬 더 많은 메모리 절감 효과를 볼 수 있었다. Swing 의 내부 초기화가 최적화되기 때문에 우리가 사용하는 클라이언트가 훨씬 더 빠르게 실행되고 반응할 수 있다. 간략하게 말하자면, anonymous 인터페이스 구현에서 생성한 너무 많은 수의 클래스를 자동으로 로딩하는 것이 속도에 지장을 주는 가장 큰 요소였다. 이에 대한 해결책은 reflection 메커니즘에 의존하는 한 클래스가 적절한 구현 프록시를 생성하도록 만드는 것이었다. 또 한가지 주목할 만한 변화는 GUI drawing 과 클라이언트 단 실행에 최적화되어 있는 HotSpot Client VM이 디폴트 VM 으로 사용된다는 것이다. 명령 프롬프트에서 java -version 을 실행하면 디폴트 JVM 에 대한 정보를 얻을 수 있다.
input validity framework 를 사용하면 mandatory 필드 또는 엔트리 validation 을 손쉽게 프로그램할 수 있다. 과거에는 사용자가 다음 필드로 넘어가기 전에 제대로 값을 입력했는지 확인하기 위해 해당 컴퍼넌트에 listener 를 달아야 했고, and every time that component lost focus you would validate and possibly restore the focus. 처리하기가 번거롭고 따분한 일이었다. 새로이 InputVerifier 클래스가 추가된 덕분으로 이제는 InputVerifier 서브클래스의 인스턴스를 생성하고 validate 가 필요한 JComponent 에 이 인스턴스를 설정함으로써 똑같은 효과를 얻을 수 있다. 이 컴퍼넌트는 focus 가 이동하도록 허가하기 전에 verify() 메서드를 자동으로 호출할 것이다.
Swing은 초기부터 배포시의 속도와 호환 불가능성의 문제를 안고 있었다. 그러나 그간의 현격한 발전 덕분에 이런 문제를 충분히 해결했고 Java 클라이언트는 효과적인 방법으로 다시금 부상했다. CPU 속도가 지난 2~3년간 거의 두 배 이상 증가했다. JDK 1.3 에서 Swing 애플리케이션은 훨씬 더 빨리 실행되고 더 작은 양의 메모리를 소모한다. 그래도 아직 남아 있는 문제가 있는데 이는 바로 배포이다. 배포에 관해서는 세 가지 옵션이 있다.
Java Plugin
<HTML> <HEAD> <TITLE>My traditional applet page</TITLE> </HEAD> <BODY> <APPLET CODE=HelloWorld.class ARCHIVE= HelloWorld.jar> Sorry, looks like I bumped into another browser that doesn't support Java applets </APPLET> </BODY>
이 방식은 HelloWorld 클래스를 로드하고 실행하기 위해 브라우저 JVM 에 의존해야 한다는 문제점이 있다. 시중에 다양한 브라우저가 출시되어 있고 이들이 각기 다른 방식으로 Java 를 구현하기 때문에 애플릿 배포가 매우 까다롭다. 그렇다면 쉬운 해결책은 뭐가 있을까? 우선, 반드시 여러분이 테스트를 해 본 JVM 에서 실행해야 한다. 브라우저가 Java 를 실행하도록 요구하는 대신, 애플릿을 실행할 JVM 을 설치하고 실행하도록 요구해야 한다. Internet Explorer (IE) 에서는 <OBJECT> 태그를 사용하면 되고 그 밖의 브라우저에서는 각기 다양한 태그를 사용하는데, Netscape Navigator의 경우에는 <EMBED> 태그를 사용하면 된다. 이제 수정된 페이지를 살펴보자 :
<HTML> <HEAD> <TITLE>My new applet page</TITLE> </HEAD> <BODY> <OBJECT classid="clsid:8AD9C840-044E-11D1- B3E9-00805F499D93" width=100% height=100 codebase= "./j2re-1_3_0_02-win.exe#Version=1,3,0,2"> <param name= "code" value="HelloWorld.class"> <param name= "archive" value="HelloWorld.jar"> <param name= "cache_archive" value="HelloWorld.jar"> <param name= "cache_option" value="Plugin"> </OBJECT> </BODY>위에 나온 페이지는 IE 에게 주어진 클래스 ID 를 가진 객체가 이미 설치되어 있는지의 여부를 확인하도록 지시한다. 설치되어 있지 않다면 주어진 URL 로부터 JVM 을 다운로드 하고 이를 설치한다 (이 JVM은 IE 의 플러그인으로 등록된다). 다음으로 이 플러그인을 실행하면, 이 플러그인이 애플릿을 로드하고 디스플레이한다. 실제로 어떻게 되는지는 http://192.9.48.9/products/plugin/1.3/d ··· le1.html의 예제를 통해 확인할 수 있을 것이다. 또한 Java 플러그인에 대해 더 자세한 정보는 Sun의 웹싸이트에서 찾아볼 수 있다.
플러그인은 모든 플랫폼에서 모든 브라우저를 지원해야 하는 부담을 덜어준다는 매력이 있다. 거기다 보장된 실행 환경을 얻을 수도 있다. 플러그인은 한번만 설치하면 되고 모든 애플릿을 cache 하기 때문에 재실행 시에 많은 자원을 소모하지 않는다. 이 방식의 가장 큰 담점은 사용자들이 애플릿을 실행하기 전에 5MB 크기의 플러그인을 다운받아야 한다는 것이다. 회선이 느린 사용자들에게는 부담스러울 수도 있다. 여러분이 만든 애플릿이 5KB 크기의 웹페이지 상에 조그맣게 나타나는 시계인데, 그것을 실행하기 위해 5MB 의 플러그인을 다운받는 것이 비합리적으로 느껴질 수도 있기 때문이다.
Java Web Start
Java 애플리케이션을 개발하는 방법 중 최근 부각되는 또 다른 방법으로 썬 사의 Java Web Start 가 있다. 본질적으로 Java Plugin 과 유사하나 첫단계에서 큰 차이점을 보인다. Java WEb Start 는 각 데스크탑 장비에 손수 인스톨해야 할 것을 요구하기 때문에 플러그인이 자동으로 설치되는 것에 비하면 좀 귀찮을 수도 있다. Java Web Start 는 JRE 를 제공하며, 설정하기가 비교적 쉽다. 일단 설정되고 나면 Web Start에 의존하는 애플리케이션이 다운로드되고 설치될 수 있다. 플러그인과 마찬가지로, the application is jarred and published on the Web. HTML페이지는 사용자가 다운로드된 애플리케이션이 아직 사용가능하지 않으면, 이를 사용자 장비에서 launch 할 수 있게 한다. 다운로드된 애플리케이션은 cache 되고 Java Web Start Application Manager를 통해 독립적으로 launch 된다. 이 Manager는 Windows 3.1에서 본 프로그램 관리자와 매우 유사한 모습을 지닌다. 이 기술에 대한 더 자세한 정보는 Resources. 를 참고하기 바란다.
필자의 경험에 의하면 Java Plugin 이 관리자나 사용자를 덜 귀찮게 하기 때문에 Java Web Start 에 비해 설정하기가 더 간단하고 더 사용자 친화적이다. 몇몇 회사에서는 이와 비슷한 일을 하는 (어떤 경우에는 Java Web Start 보다 뛰어난 성능을 제공하는) 배포 툴을 자체적으로 개발하고 있다. 가령, Sitraka의 DeployDirector 는 Java Web Start의 성능을 향상시켜 설치를 보다 간편화했다.
요약하자면 Java Plugin 과 Java Web Start를 사용하면 Swing 애플릿의 배포가 예전보다 훨씬 더 간편하고 안전하게 진행될 수 있지만 JavaScript 가 포함된 HTML 을 클릭하는 것 보다는 더 많이 관여한다. 어떤 사용자들은 컴퓨터에 JVM 을 설피하는데 필요한 과정을 거치는 것이 두려워서 Swing이 제공하는 이점들을 경험하지 못할 수도 있다. 그렇지만 여러분이 사용자에게 유연성을 제공하는 동적 GUI 인터페이스를 만들어야 한다면 Swing 애플릿을사용하는 것 이상의 좋은 방법은 없다.
또한, 전체 배포가 Java 로 되어 있다면 HTML 리퀘스트 데이터와 여러분의 내부 스트럭쳐 관에 mapping이 존재하지 않는다. RMI 는 네이티브 데이터를 옮길 수 있는 빠른 속도의 round-trip 네트워크 call 을 제공한다. 또한 클라이언트에 callback 을 구현하여 서버의 리퀘스트가 있을 때 사용자에게 이를 통보하거나(prompt?) 스크린을 업데이트할 수 있다.
Deploying Swing as Pure HTML
HTML 프론트 엔드와 Swing 클라이언트가 각기 장단점을 가지고 있지만 이상적인 솔루션을 이 둘 모두를 지원하는 것일 것이다. 그렇지만 이 기술이 본질적으로 너무 다르기 때문에 일반적으로 이 둘 중 오직 하나만이 완성된 애플리케이션에서 구현될 수 있다. 대다수의 사용자가 Swing에 기반을 둔 빠른 인터렉티브 클라이언트를 선호할 수도 있겠지만 클라이언트의 장비에 JRE를 설치하는 것이 항상 옵션이 될 수는 없다. 때로는 보안 및 방화벽에서 RMI 를 네트워크 상으로 실행하는 것을 막을 수도 있다. 이런 경우에는 어떤 시스템에서도 실행될 수 있는 인터렉티브 소프트웨어가 필요하다. 비록 의존할 만한 클라이언트 소프트웨어가 웹 브라우저 밖에 없더라도 말이다. CreamTec 의 WebCream - 세번째 배포 옵션 - 은 Swing과 HTML 간의 다리 역할을 한다.
WebCream 은 Java 툴로써 GUI 기반 Java 애플리케이션 및 애플릿에 자동화된 Web-enabling을 제공한다. WebCream 은 AWT와 Swing을 사용하는 GUI front end를 구현하는 동시에 그 애플리케이션으로의 HTML 액세스를 자동으로 얻을 수 있게 해 준다. 어떤 면에서 WebCream 은 Java 플레임과 다이얼로그를 그 즉시 HTML로 변환하는 동적 Java-to-HTML 변환기라고 볼 수도 있다. 다음으로 WebCream 은 애프리케이션의 본래 로직을 유지하기 위해 Webpage 액션을 GUI 이벤트로 emulate 한다. WebCream은 기존의 형식과 비즈니스 로직에 어떠헌 수정도 필요로 하지 않으며 여러분이 새로운 API 를 배워야 할 필요가 전혀 없다. WebCream은 기존의 애플리케이션과 애플릿을 publish할 목적으로 설계되었다; 즉, 여러분이 사용하는 웹 서버와 해당 애플리케이션을 설명하는 프로퍼티 파일을 설정하기만 하면 된다. 나머지는 WebCream이 다 처리한다. 스탠다드 에디션이 모든 기능을 제공하며, 무료로 다운로드 받을 수 있다. WebCream은 클라이언트 장비에 설치할 필요가 없다; 사실 Java 를 지원하기 위한 브라우저 조차도 필요없다. 왜냐하면 브라우저에게는 HTML 밖에 보이지 않기 때문이다.
WebCream 기능은 꽤 독특하다 - 필자가 아는 바에 의하면 아무도 WebCream과 같은 솔루션을 제공하지 않는다. 그렇지만 몇 가지 제품들이 다른 방식을 사용해서 Web 용으로 개발되지 않은 Web-enabling 애플리케이션들에 WebCream 유사한 기능을 제공하기는 한다. Windows 2000 에는 Terminal Server 서비스가 있는데, 이 서비스는 사용자가 마치 로컬에서 로그인 한 것처럼 원격으로 서버에 액세스하도록 해 준다. Citrix Systems' MetaFrame과 마찬가지로 Terminal Server는 원격 터미널에 비디오 스트림을 전송하고 서버에서 실행중인 애플리케이션들에 사용자 액션을 emulate 한다. 상대적으로 빠른 네트워크 상에서 매우 잘 실행되지만 네트워크의 속도가 느리다면 좀 까다로워질 수도 있다. 또한 네이티브 drawing 과 scrolling 루틴을 사용하지 않기 때문에 Java 애플리케이션에서 문제를 야기하기도 한다. 그리고 Terminal Server 는 각 사용자에게 개별 복사본을 제공하는 형태이기 때문에 확장성에서 떨어진다.(Terminal Server is also not very scalable because each user is essentially given an individual copy of the application). WebCream에서 제공하는 애플리케이션은 로컬 장비에서 실행되는 애플리케이션과 형식상 다르지만 사용자가 어떤 페이지를 submit할 때만 서버에 액세스 하기 때문에 훨씬 더 나은 성능을 제공한다. WebCream-enabled 애플리케이션을 사용하는 모든 사용자들은 JVM을 공유할 수 있고 이는 자원의 소비를 크게 줄일 수 있다.
WebCream이 어떻게 실행되는지 보여주기 위해 아래에 나온 도표들은 WebCream이 사용되었을 때 샘픔 GUI 애플리케이션이 HTML 내에서 어떤 모습을 보이는 지를 제시하고 있다. 왼쪽 도표는 실행중인 GUI 애?리케이션 (소스) 를 보여주고, 오른쪽 도표는 WebCream이 똑 같은 애플리케이션을 관리하는 모습을 보여준다. 여기서 각 윈도우는 브라우저 상의 페이지로 나타난다.
![]() |
![]() |
도표 1. 샘플 GUI 애플리케이션 | 도표 2. WebCream과 함께 사용된 샘플 GUI |
이 Swing-HTML bridge 가 모든 클라이언트에게 다 적용되지 않을 수도 있지만, WebCream은 HTML을 통한 액세스를 Swing 기반 프론트 엔드에 제공함으로써 그 가치를 높여준다. 일반적으로 애플리케이션 중 95퍼센트 정도가 HTML로 아무 문제없이 변환되고, 나머지 5퍼센트에 대해서는 데이터가 보여지는 방식이나 처리되는 방식을 수정해야 할 수도 있다. WebCream에 대한 더 자세한 정보는 Resources 를 참고하기 바란다.
Emerging Choice : XML/XSLT-Based Client
여러분이 XML에 대한 기초 지식을 가지고 있다는 가정 하에 XML 애플리케이션의 프론트 엔드 개발 대해서 집중적으로 설명할 것이다. 유저 인터페이스 개발시 XML 관련해서 가장 큰 차이점은 컨텐트를 프리젠테이션으로부터 완전히 분리한다는 것이다. 더 간단히 말하며면 데이터를 XML 문서의 형태로 보관되며 그 데이터가 어떻게 사용될지 그리고 어떻게 디스플레이 될 지에 대해서는 그 어떤 가정도 하지 않는다는 것이다. 각 프리젠테이션 타입 - HTML, WML, XHTML 및 기타 - 은 "스타일쉬트" (XSLT) 를 적용하므로써 가능해 지는데, XSLT 는 데이터가 어떤 식으로 포맷되고 페이지 상에서 어떤 식으로 레이 아웃되는지를 결정한다. 이 방식은 레이어를 서로 독립적으로 유지하여 각 레이어가 맡은 임무를 수행하도록 하게 해 주는 이점이 있다.
XML 이 데이터를 publish하고 서로 다른 프리젠테이션 모델을 생성하는 깔끔한 모델을 여러분에게 제공하기는 하지만 그렇다고 해서 XML 이 만병통치약은 아니다. XML은 디자이너와 아티스트가 프리젠테이션을 처리하는 동안 개발자가 데이터에만 신경을 쓸 수 있도록 해 준면에서는 극찬을 받을 만 하다. 애플리케이션은 메모리에 저장되거나 디스크에 저장되는 XML 데이터 파일을 생성한다. 가령 HTML 과 같은 특정 타입의 프리젠테이션을 제공하기 위해서 적절한 XSLT 스타일쉬트를 사용해 컨텐트를 변형(transform)한다. 스타일쉬트는 XML문서에 적용되어 HTML 문서를 만들어 낸다. 스타일쉬트는 문서로부터 어떤 데이터가 나와서 페이지상에서 어디에 디스플레이 되는 지를 결정한는 템플릿과 유사하다. 스타일쉬트와 템플릿 둘 다 데이터를 변형하고 조건 문을 실행하며 데이터를 manipulate하기 위해 루프를 실행하고 결정을 내린다. 처리하기가 매우 복잡해 질 수도 있다.
만약 동일한 애플리케이션에 휴대폰으로부터의 액세스를 제공해야 할 경우에 여러분은 단지 새로운 WML 스타일쉬트만 만들면 되는 장점이 있다. 이론상으로는 애플리케이션의 그 밖의 다른 부분이 수정될 필요가 없기 때문에 서버단 프로그래밍이 매우 효율적으로 진행될 수 있다. XML을 사용하는 프론트 엔드를 구현하는 것은 branding, personalization 및 customization 등의 작업을 매우 간편하게 만든다. 왜냐하면 디스플레이될 데이터와 이를 처리하는 코드가 수정될 필요가 없기 때문이다. 개발팀의 구성원이 독립적으로 각자 맡은 일에 매달리면 되기 때문에 개발의 속도를 향상시킨다.
그러나 필자는 몇 가지 문제점을 경험한 바 있으며, 이 때문에 XML 기반 클라이언트의 새 버전이 출시되었지만 이를 사용하지 않게 되었다. 두 가지 간과할 수 없는 단점으로는 XML 생성과 스타일쉬트 개발을 돕기 위한 툴이 부족하다는 것과 프로세싱 스피드가 느리다는 것이다. 첫번째 단점은 특히 DreamWeaver 와 FrontPage 등의 visual HTML 툴을 사용하여 HTML 페이지를 디자인하는데 익숙한 이들에게는 큰 문제가 된다. 개인적으로 필자는 아직도 때때로 DreamWeaver로 생성된 코드를 browse through하고 수정하길 좋아한다. (FrontPage는 잘 사용하지 않는다). 그렇지만 필자는 HTML을 텍스트 편집기로 처음부터 코딩하는 것에는 별반 재미를 느낄 수 없다; 어쨌든 지금은 21세기가 아닌가. 이제 간단한 XML 문서를 HTML로 변형하기 위해 사용되는 매우 간단한 XSLT 스타일쉬트를 보여주겠다 :
<xml version="1.0"> <xsl:stylesheet version="1.0" xmlns:xsl= "http://www.w3.org/1999/XSL/Transform"> <xsl:template match="page"> <html> <head> <title><xsl:value-of select= "title"/></title> </head> <body> <xsl:apply-templates/> </body> </html> </xsl:template> <xsl:template match="title"> <h1><xsl :apply-templates/></h1> </xsl:template> </xsl:stylesheet>제대로 된 XSLT 스타일쉬트를 사용했다면 위의 코드는 아래와 같은 HTML 페이지를 생성할 것이다 :
<html> <head> <title>My first page</title> </head> <body> <h1>Hello, world</h1> </body> </html>여러분도 볼 수 있듯이 이 코드는 그다지 정교하지 않으며, 흔히 볼 수 있는 HTML 페이지와는 매우 다른 모습을 보여준다. 안타깝게도 이를 수정하기 위해서는 직접 손으로 편집하고 HTML을 생성하는 툴에서 이를 실행한 다음에 그 문서를 브라우저에서 열어야 한다. 폰트 크기를 수정하려고 하는 경우에 이 모든 과정을 다 거치는 것은 너무 낭비가 크다.
두번째문제는 모든 단계를 런타임에 수행하는 데 시간이 많이 걸린다는 것이다. XML 외의 다른 저장방식 (storage) 을 사용한다면 여러분은 우선 XML 문서를 생성하는 것에서부터 시작할 것이다. 그러면 적절한 스타일쉬트가 적용되어 여러분이 실제 결과물인 HTML 페이지를 생성하기 전에 필요한 모든 변형을 처리할 것이다. 이를 서블릿이나 JSP 내의 메모리 버퍼에 최적화된 방식으로 저장하는 것과 비교해 보면 필자가 무슨 말을 하고자 하는지를 금방 알 수 있을 것이다. 속도와 단순성은 오늘날의 기술의 관점에서 XML 기반 프론트 엔드가 제공할 수 있는 장점이 되지 못한다.
요약하자면 다양한 레이아웃과 form을 사용하는 프리젠테이션을 동적으로 생성하고자 할 때는 XML을 사용하라. 프리테이션 포맷이 자주 변경되거나 또는 유연성을 제공해야 한다면 프리젠테이션 디자이너가 새로운 스타일쉬트를 만들도록 하는 것이 더 쉬울 수 있다; 디자이너는 오직 XML 와 XSLT에 대해서만 알고 있으면 된다는 사실을 기억하자.
여러분의 데이터가 네이티브 Java 타입과 객체, 또는 관계형 데이터베이스의 형태로 오는 것이 아니라 XML의 형태로 오는 경우에도 XML 기반 UI를 잘 활용할 수 있다. XML은 향후의 Web 에서 확실한 자리매김을 할 수 있는 가능성이 큰 신규 기술이다. 그러나 오늘날 프리젠테이션을 위해서는 JSP를 사용하는 HTML을 개발하는 것이 훨씬 간편하다. 특히 여러분이 사용할 수 있는 프론트 엔드가 HTML 밖에 없을 경우에는 더욱 그러하다. JavaBeans 와 JSP 용 태그 라이브러리 등의 잘 알려진 디자인 패턴을 사용하면 컨텐트와 프리젠테이션을 XML/XSLT가 하는 것과 거의 동일한 수준으로 분리해 낼 수 있다. 그리고 훨씬 더 빨리 실행될 수 있다. XML/XSLT 편집을 자동으로 처리하는 기술이 출시되면서 이 기술도 사용하기에 훨씬 더 간편해 질 것이다.
Conclusion
프론트 엔드 기술 각각은 Java 애플리케이션의 인터페이스를 개발할 시에 장단점을 가지고 있다. 이 기술 중 어떤 것도 모든 변에서 다른 기술을 능가하지는 않는다. 각각의 애플리케이션을 개발할 때마다 이 기술을 평가하고 요구사항과 사용자의 기대치를 분석해야 할 것이다. 아래에 일반적으로 사용할 수 있는 규칙을 제시해 놓았다 :
HTML/JSP 를 사용하라 :
- - 그래픽과 예술적인 내용이 많이 들어간 상대적으로 정적인 컨텐트일 때 .
- 인터페이스가 서로 다른 소프트웨어를 실행하는 모든 유저 타입을 지원해야 할 때
- 사용자의 네트워크 속도가 느릴 때
- 그다지 정교하지 않은 애플리케이션을 빠르게 개발해야 할 때
Swing을 사용하라 :
- - built-in, 인터페이스 관련 로직을 가진 매우 인터렉티브한 GUI 일 때
- 네트워크 체증을 줄이고 가능할 때 즉각적인 리스펀스를 제공하고자 할 때
- 사용자가 인터페이스의 품질과 기능에 대한 기대치가 높을 때
- UI의 기능이 보여지는 아름다움(aesthetics) 보다 더 중요할 때
- - 프리젠테이션에서 여러가지 다양한 형태의 자주 변경되는 form을 지원해야 할 때
- 데이터가 XML 내에서 네이티브하게 저장되고 조회될 때 (obtained)
- branding과 정교한 personalization을 지원해야 할 때
- 무선 액세스 등, 다른 방식의 UI 를 제공하려는 계획이 있다면
About the Author
Alex Kalinovsky는 9년 이상 IT 산업에 종사하고 있으며 Windows 상의 C 와 C++ 에서부터 Unix 상의 Java에 이르기 까지 다양한 개발 경험을 보유하고 있다. 1997년부터는 Java로만 작업했으며 자바의 보급에 일익을 담당하였고 이 분야의 전문가 중 한 사람이다. EJB, CORBA, Servlets/JSP, XML. Swing 및 그 밖의 기술을 포함하는 엔터프라이즈 수준의 다양한 프로젝트에서 architect이자 기술부분 리더로 참여했다. 엔터프라이즈 Java 기술에 대해 15개의 다른 수업을 진행했으며 많은 개발 팀에서 지도자로써 역할을 담당했다. Information Week 와 Washington Post 지 등에 글을 기고해 왔다.
Resources
- - Java Plugin 에 대한 정보는 : http://java.sun.com/products/plugin
- Java Web Start Application Manager에 대한 정보는 : http://java.sun.com/products/javawebsta ··· ure.html
- WebCream과 그 기능에 대한 자세한 정보는 : http://www.creamtec.com/webcream
- Citrix Systems의 MetaFrame에 대한 정보는 : http://www.citrix.com/
- - "The Magic of Merlin": Find out how the new JDK 1.4 -- code-named Merlin -- levitates its functionality, Vinay Aggarwal (March 16, 2001)
- "Jato: The New Kid on the Open Source Block, Part 1": Discover a new library for converting between Java and XML, Andy Krumel (March 16, 2001)
- "Jato: The New Kid on the Open Source Block, Part 2": Look in-depth at Java-to-XML translation, Andy Krumel (April 13, 2001)
- "Java Tip 109: Display Images Using JEditorPane": Modify the JEditorPane component to display images without a document base, Rob Kenworthy (March 16, 2001)
- "Dodge the Traps Hiding in the URLConnection Class": Alleviate snags caused by the URLConnection class design, Michael C. Daconta (March 23, 2001)
- JavaWorld를 주제별로 보려면 :
http://www.javaworld.com/javaworld/topi ··· dex.html
- ITworld.com의 자바 포럼에 의견을 개진하려면 :
http://www.itworld.com/jump/jw-0420-swi ··· .ee6b802
- JavaWorld This Week 및 그 밖의 무료 Java 뉴스레터를 구독하려면 :
'Web > Info' 카테고리의 다른 글
온라인 쇼핑몰 웹 디자인 동향 2009 (0) | 2009.02.17 |
---|---|
애플릿이란? [출처] 애플릿이란?|작성자 희정 (0) | 2009.01.12 |
HTML, ASP, PHP, JAVASC (지식카페 퍼옴) (0) | 2009.01.12 |
Servlet(http://kmh.ync.ac.kr/encycl/terms/termsJ/jsp2.htm) (0) | 2009.01.12 |
무료 웹호스팅 000webhost.com (1.5GB 용량, 100GB 트래픽) 웹사이트 소개 & 활용 (0) | 2009.01.12 |