'Web'에 해당되는 글 74건

  1. 2007.10.26 자바 기반의 웹 개발 소개 (1)
  2. 2007.10.26 JSP 맛보기
  3. 2007.10.26 JSP에서의 include
  4. 2007.10.07 YUI 라이브러리

자바 기반의 웹 개발 소개

김세곤 <sehkone@bawi.org>

1999년 12월 19일

개발자의 고민

프로그래밍을 공부하고 싶은 사람이나 프로젝트를 목전에 두고 있는 개발자 모두가 고민하고 있는 것은 과연 어떤 개발 방법이 가장 적합할 것인가 하는 문제이다. 큰 범주로는 어떤 OS를 택할 것인가하는 것에서부터 작게는 어떤 에디터를 사용할 것인가에 이르기까지 고민거리는 널려있다. 문제는 개발 방향 선정 과정에서의 고민으로 그치는 것이 아니다. 우여곡절끝에 한번 개발 방향이 잡혀서 상당 기간 동안 관련 자료를 수집, 학습하고 개발을 진행시키게 되면 다른 가능성을 고려해 보기란 쉽지 않다. 리눅스에 대한 이해가 없는 직장 상사때문에 윈도우즈에서 개발을 착수해 놓고나서 중간에 리눅스로 전환한다는 것은 상상하기 어려운 일이다. 오랫동안 C/C++을 공부하여 CGI 기법을 득도했다고 해도 보다 진보된 방법들로 여겨지는 Server-side Script 방식을 새로이 공부하여 사용하기란 만만치 않은 일이다. 따라서, 개발 과정에서의 후회를 최소화하기 위해서라도, 더 나아가서는 향후 프로젝트에도 유용하게 써먹을 수 있도록 하기 위해서, 초기 개발 방향 선정에 보다 혜안을 갖고 신중을 기해야 한다.

그러나, 어떤 개발 방향이 현재의 요건과 향후의 비전을 동시에 만족시켜줄 수 있는지를 찾아내는 것도 쉽지 않다. 진보적인 방법으로 보이는 것들은 진행 상태가 베타 정도인 경우가 많고 심지어는 스펙만 있고 관련 툴을 찾기 어려울 때도 있다. 그렇다고, 막상 손에 익은 개발 방법은 뭔가 향후 비전이 없어 보이고, 벤치마크 테스트에서 새로운 개념에 비해 못 미치기도 한다. 여기저기 관련 사이트를 뒤져가면서 비교적 그럴싸한 개발 방법 몇 가지를 압축해 놓고 나서도, 조언을 해 주는 개발자마다 딱히 어떤 개발 방법이 최선이라는 답을 내 주지 못 한다. 그도 그럴 것이, 이런 저런 방법을 모두 학습하고 실제에서 다 적용시켜 본 개발자는 거의 없기 때문이다. 인터넷에 널려 있는 벤치마크 테스트 자료도 내가 알고 싶은 것만 꼭 빠져있기 일쑤고, 어쩌다 나와 있는 정말 궁금한 정보는 테스트 자료마다 다르다. 설상가상으로 좀 좋은 툴이다 싶은 것은 열심히 다운로드 받으려고 보면 트라이얼 버전이고, 상업적으로는 절대 이용하지 말란다.

현재까지의 경험들과 산더미같은 관련 자료를 바탕으로하여 기도하는 심정으로 개발 방향을 잡았다고 하자. 그것으로 해결되는가? 문제는 이제부터 시작이라고 보면 된다. 돈 싸 들고 문제를 해결하려고 하면 간단하겠지만, 오픈 소스 진영의 개발자들의 자존심으로 상업용을 쓸 수 있겠는가. 자존심은 둘째로 쳐도 돈이 없는데 어쩌겠는가. 다행히도 절망에서 건져주는 것은 어딘가에 숨어있는 자유로이 배포가능한 소프트웨어! 중요 기능을 비교적 다 갖추고 있는 그래도 쓸만한 툴이 숨어 있기 마련이다. 그러나, 반가움도 잠깐, 설치해서 운영해 보려고 하면 어딘지 찜찜하다. 개발자야 열심히 노력해서 만들었겠지만, 그 양반이 언제까지 업그레이드 해 줄지 의문이 생기기도 하고, 어딘가에 심각한 버그 있을지 알 길 없음이다. 다시 여기 저기 뒤져보다 보면 내가 찾아낸 소프트웨어가 비교적 안정적으로 여러 사람의 지지를 받고 있는 것이 확인된다. 그렇다면 역시 이것을 찾아낸 나의 혜안에 놀라게 되며 설치를 시도해 보게 된다. 이제 본격적인 문제가 발생한다. 전세계의 많은 사람들이 좋다고 지지를 보낸 소프트웨어가 왜 나의 컴퓨터에서는 설치가 안 되는 문제가 발생한단 말인가. 싼 맛에 조립한 나의 펜티엄은 역시 비지떡이었단 말인가. 나랑 설치를 같이 시작한 다른 개발자가 7000만원짜리 컴팩 서버에서 잘 돌리고 있는 모양을 보면 열이 받기까지 한다. 이틀을 고민하고 머리를 쥐어 뜯고 나니 어느 순간 꿈쩍도 않던 소프트웨어가 돌아가고 문제는 디렉토리에 쓰기 퍼미션을 안 열어 놓았기 때문이라는 사실을 깨닫게 된다. 겨우 퍼미션 따위로 이틀을! 그러나, 기쁨도 잠시, 설치만 하면 무엇하겠는가. 개발하려고 모니터 앞에 앉으면 손에 쥐게 되는 자료라고는 README나 API를 줄줄이 설명해 놓은 정도이다. 튜토리얼을 열심히 읽어도 겨우 입문 정도지 본격적인 개발에 도움이 크게 되기 어렵다. 결정적으로 그 놈의 문서들은 죄다 영어로 씌여 있는 통에 해독하는데만 해도 한숨 나온다.

이 모든 어려운 과정을 헤치고 개발에 착수해서 프로젝트가 완수될 무렵, 개발자의 가슴을 찧는 것은 더욱 진보적인 방법이 수없이 생겨나고 내가 열심히 쌓은 기술이 오래가지 못 할지도 모른다는 불안감이다.

웹 개발의 역사와 추세

정적인 HTML에서 동적인 CGI로

초기에는 HTML만으로도 놀라운 인터넷의 세계라고 여길 수 있었다. 그러나, 곧 정적인 문서에 식상하게 되고 뭔가 방문자와 호흡할 수 있는 동적인 사이트를 만들 필요성이 생겨나기 시작했다. 사실 지금은 전세계의 모든 사이트가 정적인 HTML문서만으로 움직이지 않는다. 끊임없이 데이터베이스와 연동하여 방문자에게 맞는 맞춤 정보를 제공하고 있다.

초기 HTML의 정적인 자료를 동적으로 움직이게 하기 위해서 등장한 방법이 CGI(Common Gateway Interface)이다. 초기 한동안은 많은 개발자에게 쉽게 전달되지 않아서 특별하고 대단한 기법쯤으로 여겨지기도 했는데, 그 메카니즘은 매우 간단하다. 별도로 만들어 놓은 프로그램에 HTML의 GET이나 POST의 방법을 통해 클라이언트의 데이터를 환경 변수로 전달하고 프로그램의 표준 출력 결과를 그대로 클라이언트에 되돌려 주는 형식이다. CGI는 특별한 라이브러리나 개발 툴을 지칭하는 것이 아니고 웹 서버와 별도로 만들어 놓은 프로그램 간의 데이터 교환 방식을 일컫는 것으로서 어떤 프로그래밍 언어로도 구현이 가능하다. 초기에는 C, C++, Perl, Visual Basic(물론 윈도그에서만) 등이 주류를 이루었다.

데이터베이스와 연동하기 위해서는 개별 데이터베이스가 제공하는 해당 언어의 라이브러리를 이용하는 방식을 취하였다. 예를 들어 postgreSQL을 웹과 연동시키기 위해서는 postgreSQL이 제공하는 C라이브러리를 이용한다든지 하는 식이었다.

CGI의 문제점

작성과 유지의 한계

구동 메카니즘의 취약성을 차치하고서라도 CGI 방법에서 표준 출력으로 HTML문서 양식을 만들어야 한다는 것이 개발자에게 가장 번잡스러운 문제로 등장하였다. 예를 들어, C로 CGI 프로그램을 만들었다고 하자. 간단한 HTML문서를 출력하기 위해서도 다음과 같은 C코드를 써야 했다.

...
printf("<HTML><HEAD><TITLE>CGI결과물</TITLE></HEAD>");
printf("\n<BODY>");
printf("\n난 \"멋진 넘\"이야");
...

HTML 문서 양식이 한눈에 들어오는가? 절대 그럴 수 없다. 겨우 한 줄의 HTML 코드를 쓰려고 해도 표준 출력 함수를 불러야 하고, 줄 넘김을 위해서 \n을 남발해야 하며, 큰 따옴표를 쓰려고 하면 앞에 \(backslash)를 붙여주어야만 한다. 매번 printf 함수가 호출되는 것도 달갑지 않다. HTML 문서의 한계상 문서 체계를 코드만으로 이해하는 것이 쉬운 일은 아니지만, C 코드와 섞여 있으니 어디가 어딘지 도통 감이 서지 않는다.

천신만고 끝에, 절대 직관적으로 눈에 들어오지 않는 HTML 코드에서 헤매다가 간신히 프로그램을 작성하고, 작성한 CGI 프로그램을 웹에서 동작하게 하려면 컴파일러로 컴파일을 우선 해야 한다. 그리고, 브라우저를 띄운다. 테스트를 했더니, "멋진 놈"이라고 나와야 할 것이 "멋진 넘"으로 오타가 나고 있다. 단 한 글자를 수정하기 위해 해야 할 일은 작성한 C 프로그램 코드의 "멋진 넘" 부분을 열심히 찾아서 한 글자 고치고 다시 컴파일을 하고 브라우저의 다시 읽기 버튼을 누르는 것이다. 상상해보자. 조금 긴 문서, 테이블이 복잡하게 들어간 문서를 고치려고 하면 과연 쉬울까? 그래도 디자인과 CGI를 함께 한다면 작성자 스스로 디자인을 고쳐갈 수 있으니 꺼이꺼이 수정할 수 있다고 치자. 그러나, 디자이너가 별도로 있고 개발자가 이를 CGI로 변환하는 작업만을 한다면? 디자이너가 C 코드를 봐가면서 고칠리 만무다. 예를 들어, 홈페이지의 대대적인 개선 작업의 일환으로 게시판의 디자인이 확 바뀌었다고 하자. 디자이너는 바뀐 게시판의 샘플 디자인을 CGI 작업자에게 던져 준다. 프로그래머는 이를 COPY-PASTE로 C 에디터로 가져 와서 열심히 표준 출력 함수로 우겨 넣어야 한다. 예전에 작업했던 것은 다 필요 없이 새 부대에 담아야 한다. 이제, 웹 개발자는 노가다 인력으로 전락하고 만다.

메카니즘의 한계

CGI의 결정적인 한계는 성능에 있다. 간략한 페이지를 CGI를 통해 보여 주려고 해도 웹 서버는 별도의 프로그램을 실행시켜야 한다. 프로그램 실행이 뭐 대수냐고? OS가 프로그램을 실행하는 단계를 잠깐 생각해 보자. 각각의 프로그램은 실행되면서 하나의 프로세스가 되는데, 개별 프로세스를 제어하기 위해 OS는 PCB(Process Control Block)를 사용한다. PCB에는 각 프로세스의 상태, 프로그램 카운터, CPU 레지스터, 스케줄링 정보, 메모리 정보, I/O 정보 등등등이 저장되고 이 PCB는 메모리에 저장된다. 더불어, 코드 내용이 메모리에 적재되는데, 프로그램 코드를 모두 메모리에 저장하는 것은 무리이므로 필요한 부분만을 찾아서 메모리에 싣는다. 프로세스가 하나만 도는 것이 아니므로 CPU는 현재 진행 중인 프로세스를 적절하게 스케줄링하여 동시에 수행되고 있는 효과를 내도록 한다. 위에서 언급한 프로그램이 실행되면서 OS가 처리해야 하는 일련의 일과 동시에 여러 작업을 수행하기 위해 프로세스를 전환하는 과정 등은 OS의 관점에서 보면 매우 Heavy한 일이다. 뿐만아니라, CGI는 클라이언트의 요청이 같은 URL, 즉 같은 CGI 프로그램을 실행시키는 것이라고 해도, 각각의 요청을 모두 개별 프로세스로 처리한다. 1000명이 카운터 CGI를 요청했다고 하면 1000개의 프로세스가 생긴다는 말이다. 몇 줄의 HTML 문서 결과를 보여 주기 위해 위에서 언급한 일들을 매번 수행한다는 것은 어딘지 효율적이지 못하다.

Server-side Script 방식의 도래

프로그램 코드 속에 HTML 문서를 우겨 넣는 방식은 디자인과 개발을 별도의 작업으로 분리시키지 못 하고 유지, 보수에 많은 시간을 들게 하는 등의 단점이 있었다. 이를 개선하는 방법들이 등장하기 시작했는데, 뭔고하니, HTML 문서 안에 우아하게 프로그램 코드를 넣는 방식이다. 대표적인 것이 ASP(물론 윈도그에서만), PHP 등이다. 이 중 근래에 사용의 편리성으로 인해 주목받고 있는 방법이 PHP이다.

PHP를 생각해 보자. PHP는 C 코드와 비슷해 보이지만 절대 C가 아닌 새로운 언어 스펙을 사용하고 있다. 기존 언어처럼 복잡하지 않고, 사용하기 간편하다. 뿐만아니라, 온갖 종류의 데이터베이스를 제어할 수 있는 함수도 제공되고 있으며, 기타 웹 개발에 필요하다 싶은 함수들은 잔뜩 들어가 있다. 그러나 PHP 한계는 여기에 있다. 모든 필요한 것은 PHP가 해결을 해 주어야 한다. PHP가 제공하지 않는 방법으로는 해결책을 찾을 수 없다는 말이다. PHP는 기존 언어를 사용하는 것이 아닌 새로운 언어이므로, 기존의 수많은 라이브러리, 소프트웨어와 연동시킬 수 없는 한계가 있다. 더욱이, PHP는 웹 서버에 모듈로 포함되어 있어서, 이런 온갖 기능이 웹 서버에 상당한 부하를 주게 된다. 구동 방식을 생각해 보자. 웹 서버에 PHP 문서가 요구되면 웹 서버는 PHP 모듈로 그 제어권을 넘긴다. PHP 모듈은 PHP 문서를 문법적으로 해독하면서 관련 함수들을 구동하여 결과물을 브라우저에 보내게 된다. 언어를 문법적으로 해독하는 과정은 아무리 간단한 문법의 언어라고 해도 일정 수준의 시간이 필요하다. 함수가 많아지고 기능이 복잡해질 수록 요구되는 시간은 늘어난다. 뿐만아니라, 한번 실행한 문서의 해독 정보를 저장하는 것이 아니라 매번 그 문서가 요구될 때마다, 같은 작업을 수행해야 한다. PHP 모듈은 웹 서버에 들어가는 다른 모듈에 비해 매우 큰 규모로 웹 서버 수행에 부담을 가중시킨다. 이런 이유로 성능 향상을 위해 구문을 최소화하느라 객체지향 등의 최신 언어 기법을 구사할 수 없다. 때문에, C++이나 Java처럼 한번 사용한 소스 코드를 재사용하기 어렵다.

웹 개발 최후의 솔루션 - 자바

자바란?

자바는 Sun이 개발한 객체지향 언어로서 플랫폼에 구애 받지 않는 장점때문에 급속히 확산되고 있다. 최신 프로그램 언어 개념인 객체지향, 멀티쓰레드, Garbage Collection, Exception Handling 등을 복합시킨 언어로서 기반이 매우 훌륭하다. 그동안 등장했던 Lisp, C, C++ 등 모든 언어의 장점을 절묘하게 복합시켰으며 C에서 사용해온 포인터와 동적 메모리 관리 등을 아예 없애 개발자의 부담을 덜어주었다. 자바 코드는 어느 OS에서도 JVM(Java Virtual Machine)만 있다면 단 한 줄의 코드 수정 없이 똑같이 가동시킬 수 있다. 자바 소스를 자바 컴파일러로 컴파일 하면 Bytescode가 생성이 되고, 이 Bytescode는 어떤 OS의 JVM에서도 동등하게 실행된다. 그러나, 초기엔 자바의 개념적 우월성에도 불구하고 JVM의 수행 속도가 매우 느려 실제 개발 현장에서 채택하기에는 무리였다. 그러나, 하드웨어 사양의 발전과 JVM의 성능 향상으로 초기의 느리다는 지적은 점차 사라지고 있다.

웹과 자바

Applet : 클라이언트

초기에 자바는 애플릿 작성에 많이 이용되었다. 애플릿은 HTML 코드안에 포함되는 독립적 프로그램으로 브라우저가 이를 받아서 수행한다. 넷스케이프와 익스플로러 모두 브라우저 안에 자바를 수행할 수 있는 JVM을 내장하고 있으므로 OS와 독립적으로 동등하게 실행시킬 수 있다. 애플릿은 서버측에서 동적으로 생성되는 것이 아니라 클라이언트(브라우저)에게 보내져 클라이언트 환경에서 수행된다. 자바 Bytescode는 소스를 자바 컴파일러로 컴파일한 결과물로서 HTML 문서에 비해 크기가 매우 크며 웹 서버에서 브라우저로 전송되기까지가 많은 시간이 걸린다. 일단 전송된 애플릿은 브라우저가 수행시키므로 그 속도는 클라이언트의 시스템 환경과 브라우저가 내장하고 있는 JVM의 성능에 따라 좌우된다. 28.8K 정도의 모뎀 환경이라면 그럴듯한 애플릿을 다운 받아서 수행하는데는 많은 인내심이 필요하게 된다. 그러나, 점차 인터넷 통신 환경이 좋아지고 있으며 가정집을 제외한 대부분의 사무실과 학교 등에서는 전용 회선이 깔려 있고, 넉넉한 환경의 전용선이라면 애플릿을 구동하는데 무리가 없다. 근래에는 가정에서도 초고속 통신 환경을 싼 값에 구축할 수 있으므로 점차적으로 인터넷 환경에서 애플릿의 전송은 부담이 되지 않을 것이다. JVM도 기술적으로 많이 향상되었고, Sun뿐 아니라, IBM과 같은 매머드급 회사들이 뛰어들어 개발하고 있어 초기 지적받았던 JVM의 구동 속도는 점차 문제가 되지 않는 상황이다.

Servlet과 JSP : 서버

오늘날의 많은 개발은 웹과의 연동을 염두에 두고 있다. 자바 진영도 예외는 아니어서, 근래의 발전 방향은 인터넷에 초점이 맞추어져 있다. 지금까지 등장한 웹 개발 방법들은 페이지 생산에 비해 보수가 매우 어렵다는 점과, 동시 접속자가 많아지면 성능이 저하된다는 점, 기존에 산재해 있는 많은 개발 방법들과 연계가 번거롭다는 점 등이라고 말하였다. 이를 개선하려는 노력이 반영되어 자바 진영에서는 이러한 단점을 극복해 줄 수 있는 방법을 제시하고 있다. 뿐만 아니라, 대규모 프로젝트에서 적합한 훌륭한 아키텍쳐를 제공하고 있다.

보통 웹 개발이라면 단순히 방문자에게 효과적인 화면을 제공하는 것 쯤으로 생각하기 쉬운데, 내부적으로는 끊임없이 데이터베이스와 연동하기도 하고 각종 미들웨어를 사용하여 효율을 증대하기도 한다. 이 중에서 웹은 클라이언트와의 접점이며 인터페이스이다. 자바에서는 웹 인터페이스로서 서블릿과 자바 서버 페이지의 두 가지 방법을 제공한다.

서블릿과 JSP 엿보기

서블릿

우선 서블릿에 대해서 간략히 소개하겠다. 서블릿은 일종의 CGI이다. 그러나, 그 구동 방식은 여러가지 점에서 다른데 가장 큰 장점은 클라이언트가 요청하는 서블릿이 개별적인 프로세스로 실행되는 것이 아니고 서블릿을 제어하는 모듈 내에서 실행된다는 것이다. 아파치와 JServ를 사용했다고 하면 쉽게 ps를 통해 java 프로세스가 하나만 돌고 있는 것을 확인할 수 있다. 이것은 클라이언트들이 같은 서블릿을 요청하면 이 서블릿이 메모리에 개별적으로 올라오는 것이 아니라 하나만 메모리에 적재된다는 뜻이고 이는 엄청난 퍼포먼스 향상을 가져온다. 뿐만 아니라, 모든 실행되는 서블릿은 이를 제어하는 모듈의 통제하에 놓이게 되므로 서블릿끼리의 자유로운 통신이 가능하고 쓰레드를 사용한다면 멀티쓰레드 프로그래밍이 가능해진다. 일반적인 CGI의 큰 단점 중에 하나인 보안 문제도 서블릿을 사용하면 걱정할 필요가 없다.

또 하나의 장점은 서블릿이 자바를 사용하기 때문에 자바가 제공하는 수많은 기능을 제한없이 사용할 수 있다는 것이다. 예를 들면 자바가 제공하는 2D, 3D 그래픽 툴을 이용해서 동적인 이미지를 생산할 수 있고, 자바가 제공하는 메일 클래스들을 이용하면 효과적으로 메일 전송 및 관리를 할 수 있다.

또, 자바를 기반 언어로 사용하기 때문에 자연스럽게 얻어지는 장점이 있는데 이것은 코드의 손쉬운 재사용, 플랫폼 독립성, JDBC 사용 등이다. 코드의 재사용은 객체지향언어의 중요한 개념으로 잘 만들어 놓은 구조의 클래스라면 어느 코드에서도 쉽게 사용할 수 있고 계승 등을 이용하여 기능을 추가할 수 있다. 플랫폼 독립성도 역시 자바의 중요한 장점인데 만일 서블릿으로 웹을 구축하였다면 어떤 OS, 어떤 기계라도 그 플랫폼이 자바를 지원하기만 하면 한 줄의 코드 바꿈없이 개발해 놓은 코드를 그대로 이식할 수 있다. 자바는 리눅스, 유닉스를 비롯하여 심지어 윈도그에서도 무리없이 돌아가며, 서블릿 환경도 어떤 플랫폼이라도 쉽게 구축할 수 있다. JDBC를 사용하면 어떤 데이터베이스와도 똑같은 인터페이스로 연동할 수 있으므로, 데이터베이스를 다른 기종으로 교체한다고 해도 서블릿 소스 코드를 거의 수정할 필요가 없다.

서블릿 코드를 잠깐 소개하겠다.

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class CMemberTest extends HttpServlet {
    
    public void doGet(HttpServletRequest request,
		       HttpServletResponse response)
	throws ServletException, IOException {
	
	response.setContentType("text/html; charset=EUC_KR");
	PrintWriter out = response.getWriter();

	out.println("<HTML><HEAD><TITLE>세션 테스트</TITLE></HEAD></HTML>");
	out.println("<BODY>");

	Cookie[] cookies = request.getCookies();
	boolean pass = false;
	String email = "";

	for (int i = 0; i < cookies.length; i++) {
	    Cookie thisCookie = cookies[i];
	    out.println(thisCookie.getName() + ":" + thisCookie.getValue());
	    if (thisCookie.getName().equals("pass") &&
		thisCookie.getValue().equals("yes")) pass = true;
	    if (thisCookie.getName().equals("email")) 
		email = new String(thisCookie.getValue().getBytes(), "EUC_KR");
	}

	try {
	    if (pass) {
		out.println("인증 통과된 아이디임" + " : " + email);
	    } else {
		out.println("인증 통과되지 않았음");
	    } 
	} catch (NullPointerException e) {
		out.println("인증 과정을 거치지 않았음");
	}
	out.println("</BODY></HTML>");
    }
}

위의 예에서는 쿠키를 이용하여 인증 여부를 확인시켜 주는 간단한 방법을 보여준다. 쿠키를 이용하는 인증은 보안 측면에서는 빈약하여 WebDox가 제공하는 아파치에 추가 되는 postgreSQL 인증 모듈을 쓰는 방법이 훌륭하지만, 우선 위의 방식은 쿠키 사용예를 보여주며 보안이 크게 필요하지 않는 수준이라면 사용할 수 있다.

JSP

서블릿은 CGI와는 비교할 수 없는 수준의 좋은 아키텍처를 갖고 있고 다양한 장점들이 있다. 그러나 역시 자바 코드 속에 HTML 코드를 넣어야 한다는 단점이 있는데, 이를 극복한 것이 JSP(Java Server Page)이다. JSP는 HTML문서 안에 자바 코드를 넣는 형식으로 PHP, ASP와 같이 Server-side script 방식이다. 그러나, JSP는 소스 수정 시 자동적으로 서블릿으로 전환되어 구동되며 이점에서 완전히 서블릿과 동등하다. JSP의 코드를 잠시 살펴보자.

<%@ page import="java.sql.*" contentType="text/html; charset=EUC_KR" %>

<%
String userId = request.getParameter("userid");

Connection db;
ResultSet rs;
Statement stmt;

try {
   Class.forName("postgresql.Driver");
} catch (java.lang.ClassNotFoundException e) {
   System.err.println(e.getMessage());
}
%>

<HTML>
<HEAD><TITLE>JSP Sample page</TITLE></HEAD>
<BODY>
<TABLE>
<TR>

<%
try {
    db = DriverManager.getConnection("jdbc:postgresql:dbname", "dbowner", "password");
    stmt = db.createStatement("SELECT name FROM member WHERE userid = " + userId);
    rs = stmt.executeQuery();

    while (rs.next()) {
%>

<tr>
<td><%= rs.getString("name") %><td>
</tr>

<%
    }
%>

</TABLE>
</BODY>
</HTML>

<%
} catch (SQLException e) {
%>
    <%= e.getMessage() %>
<%
}
%>

HTML 문서 안에 자바 코드가 들어가는 모습과 JDBC를 이용하여 postgreSQL과 연동되는 모습을 볼 수 있다. <% %> 태그 안에는 자바 코드를 아무런 제한 없이 써 넣으면 되고, <%= %> 태그 안의 자바 코드 결과는 화면에 그 결과가 보여지게 된다. Post나 Get으로 전달받는 값들은 request.getParameter() 함수를 이용하면 쉽게 제어할 수 있다.

다른 개발 방법과의 비교

많은 개발자들이 가장 궁금해 하는 것이 역시 여러 개발 방법들 중 어떤 것이 더 나은가 하는 점일 것이다. 지금까지 여러가지 방법들의 장단점을 언급했는데 정리해 보기로 하자. 비교 대상은 일반 CGI, Server-side scripts(PHP, ASP), Servlet+JSP 등이다.

성능면

ASP는 스크립트로 씌여 졌지만 일단 컴파일 되면 CGI로 바뀌므로 CGI가 갖고 있는 여러가지 문제점을 그대로 지니게 된다. 따라서, ASP와 CGI가 성능면에서 가장 취약하다. PHP의 경우는 대체적으로 매우 뛰어난 속도를 보여 준다. Servlet과 JSP는 JVM에 그 성능이 의존적이다. 현재는 ASP나 CGI보다는 빠르지만 PHP보다는 약간 느리다는 평을 얻고 있다. 그러나, 여러 미들웨어를 사용하거나 DB와의 많은 트랜잭션이 있는 경우는 PHP에 앞선다고 보고되고 있으며, JVM의 성능 향상에 따라 꾸준한 성능 향상을 기대할 수 있다.

확장성면

단연, Servlet+JSP 방식이 우월하다. 자바가 제공하는 모든 기능을 자유롭게 사용할 수 있으며 코드의 재사용 등에서 탁월하다. JDBC를 사용하여 모든 데이터베이스와 똑같은 인터페이스로 데이터 교환이 가능한 점에서도 Servlet+JSP 방식이 뛰어난 확장성을 갖고 있다.

난이도

ASP나 PHP는 간단한 문법이므로 초보자도 쉽게 사용할 수 있다. 그러나 Servlet과 JSP는 자바를 알아야 한다는 전제 때문에 쉽게 다가서기 어려운 면이 있다. 하지만, 개발자는 간단한 웹 인터페이스만을 작업하는 것이 아니기 때문에 제대로 한 언어를 알아두면 어느 때고 약이 된다. 간단한 작업을 위해서라면 자바를 전부 익혀야 하는 부담없이 손쉽게 작업할 수 있기도 하다.

결론

향후 웹 개발에서 자바를 이용한 솔루션은 큰 몫을 차지할 것이며, 큰 프로젝트일수록 그 사용 비중은 높아질 것이다. webdox는 웹 개발에 있어서의 자바의 비전을 인식하여 지속적으로 자바를 이용한 웹 개발 방법에 대한 자세한 글을 게재할 예정이다.

Posted
Posted by 행복한 프로그래머 궁금쟁이박
TAG JSP

댓글을 달아 주세요

  1. BlogIcon Nike Air Max Shoes 2012.05.04 16:37  댓글주소  수정/삭제  댓글쓰기

    http://www.nikejordanairmaxshoes.com/ Nike Air Max Shoes http://www.nikejordanairmaxshoes.com/ Air Max Shoes http://www.nikejordanairmaxshoes.com/ Nike Air Max http://www.nikejordanairmaxshoes.com/ nike jordan air max http://www.nikejordanairmaxshoes.com/ nike air jordon http://www.nikejordanairmaxshoes.com/cheap-Barefoot-Nike-Free-Run-sale-id-187.html Barefoot Nike Free Run http://www.nikejordanairmaxshoes.com/cheap-Barefoot-Nike-Free-Run--2-sale-id-321.html Barefoot Nike Free Run+ 2 http://www.nikejordanairmaxshoes.com/cheap-Barefoot-Nike-Free-Run--3-sale-id-322.html Barefoot Nike Free Run+ 3 http://www.nikejordanairmaxshoes.com/cheap-Barefoot-Nike-Free-Run-sale-id-323.html Barefoot Nike Free Run http://www.nikejordanairmaxshoes.com/cheap-Barefoot-Free-Run-3-0-V2-sale-id-324.html Barefoot Free Run 3.0 V2 http://www.nikejordanairmaxshoes.com/cheap-Barefoot-Free-Run-3-0-V3-sale-id-325.html Barefoot Free Run 3.0 V3 http://www.nikejordanairmaxshoes.com/cheap-Barefoot-Nike-Free-5-0-V4-sale-id-326.html Barefoot Nike Free 5.0 V4 http://www.nikejordanairmaxshoes.com/cheap-Barefoot-Nike-Free-7-0-sale-id-327.html Barefoot Nike Free 7.0 http://www.nikejordanairmaxshoes.com/cheap-Barefoot-Nike-Free-Tr-Fit-sale-id-328.html Barefoot Nike Free Tr Fit http://www.nikejordanairmaxshoes.com/cheap-Dual-Fusion-St-2-sale-id-329.html Dual Fusion St 2 http://www.nikejordanairmaxshoes.com/cheap-Air-Max-sale-id-330.html Air Max http://www.nikejordanairmaxshoes.com/cheap-Nike-Air-Max-2009-sale-id-331.html Nike Air Max 2009 http://www.nikejordanairmaxshoes.com/cheap-Nike-Air-Max-2011-sale-id-332.html Nike Air Max 2011 http://www.nikejordanairmaxshoes.com/cheap-Nike-Air-Max-2012-sale-id-333.html Nike Air Max 2012 http://www.nikejordanairmaxshoes.com/cheap-Nike-Air-Max-24-7-sale-id-334.html Nike Air Max 24-7 http://www.nikejordanairmaxshoes.com/cheap-Nike-Air-Max-87-sale-id-335.html Nike Air Max 87 http://www.nikejordanairmaxshoes.com/cheap-Nike-Air-Max-89-sale-id-336.html Nike Air Max 89 http://www.nikejordanairmaxshoes.com/cheap-Nike-Air-Max-90-sale-id-337.html Nike Air Max 90 http://www.nikejordanairmaxshoes.com/cheap-Nike-Air-Max-91-sale-id-338.html Nike Air Max 91 http://www.nikejordanairmaxshoes.com/cheap-Nike-Air-Max-93-sale-id-339.html Nike Air Max 93 http://www.nikejordanairmaxshoes.com/cheap-Nike-Air-Max-95-sale-id-340.html Nike Air Max 95 http://www.nikejordanairmaxshoes.com/cheap-Nike-Air-Max-180-sale-id-341.html Nike Air Max 180 http://www.nikejordanairmaxshoes.com/cheap-Nike-Air-Max-360-sale-id-342.html Nike Air Max 360 http://www.nikejordanairmaxshoes.com/cheap-Nike-Air-Max-2010-sale-id-343.html Nike Air Max 2010 http://www.nikejordanairmaxshoes.com/cheap-Nike-Max-Alpha-2012-sale-id-344.html Nike Max Alpha 2012 http://www.nikejordanairmaxshoes.com/cheap-Nike-Air-Max-ACG-sale-id-345.html Nike Air Max ACG http://www.nikejordanairmaxshoes.com/cheap-Air-Max-Tailwind--4-sale-id-346.html Air Max Tailwind +4 http://www.nikejordanairmaxshoes.com/cheap-Air-Max-Classic-BW-sale-id-347.html Air Max Classic BW http://www.nikejordanairmaxshoes.com/cheap-Air-Max-Griffey-sale-id-348.html Air Max Griffey http://www.nikejordanairmaxshoes.com/cheap-Air-Max-LTD-sale-id-349.html Air Max LTD http://www.nikejordanairmaxshoes.com/cheap-Air-Max-Skyline-sale-id-350.html Air Max Skyline http://www.nikejordanairmaxshoes.com/cheap-Air-Max-Terra-Ninety-sale-id-351.html Air Max Terra Ninety http://www.nikejordanairmaxshoes.com/cheap-Nike-Air-Max-Tn-sale-id-352.html Nike Air Max Tn http://www.nikejordanairmaxshoes.com/cheap-Air-Max-Zenyth-sale-id-353.html Air Max Zenyth http://www.nikejordanairmaxshoes.com/cheap-Air-Max-2009-Heels-sale-id-354.html Air Max 2009 Heels http://www.nikejordanairmaxshoes.com/cheap-Nike-Air-Max-Barkley-sale-id-355.html Nike Air Max Barkley http://www.nikejordanairmaxshoes.com/cheap-Nike-Lunar-sale-id-356.html Nike Lunar http://www.nikejordanairmaxshoes.com/cheap-Nike-LunarGlide--3-sale-id-367.html Nike LunarGlide+ 3 http://www.nikejordanairmaxshoes.com/cheap-Nike-LunarGlide--2-sale-id-368.html Nike LunarGlide +2 http://www.nikejordanairmaxshoes.com/cheap-Nike-LunarGlide---sale-id-369.html Nike LunarGlide + http://www.nikejordanairmaxshoes.com/cheap-Nike-LunarElite--sale-id-370.html Nike LunarElite+ http://www.nikejordanairmaxshoes.com/cheap-LunarEclipse--2-sale-id-371.html LunarEclipse+ 2 http://www.nikejordanairmaxshoes.com/cheap-Nike-LunarEclipse--sale-id-372.html Nike LunarEclipse+ http://www.nikejordanairmaxshoes.com/cheap-Nike-LunarMX--sale-id-373.html Nike LunarMX+ http://www.nikejordanairmaxshoes.com/cheap-Nike-LunarSwift-sale-id-374.html Nike LunarSwift http://www.nikejordanairmaxshoes.com/cheap-Nike-LunarHaze-sale-id-375.html Nike LunarHaze http://www.nikejordanairmaxshoes.com/cheap-Nike-LunarFly--2-sale-id-376.html Nike LunarFly+ 2 http://www.nikejordanairmaxshoes.com/cheap-Nike-Lunaracer--2-sale-id-377.html Nike Lunaracer+ 2 http://www.nikejordanairmaxshoes.com/cheap-Lunar-Orbit-Nd-sale-id-378.html Lunar Orbit Nd http://www.nikejordanairmaxshoes.com/cheap-Lunar-Rejven8-Mid-sale-id-379.html Lunar Rejven8 Mid http://www.nikejordanairmaxshoes.com/cheap-Nike-LunarElite--2-sale-id-380.html Nike LunarElite+ 2 http://www.nikejordanairmaxshoes.com/cheap-Air-Jordan-sale-id-357.html Air Jordan http://www.nikejordanairmaxshoes.com/cheap-Air-Jordan-2012-sale-id-381.html Air Jordan 2012 http://www.nikejordanairmaxshoes.com/cheap-Air-Jordan-2011-sale-id-382.html Air Jordan 2011 http://www.nikejordanairmaxshoes.com/cheap-Jordan-Melo-M7-sale-id-383.html Jordan Melo M7 http://www.nikejordanairmaxshoes.com/cheap-Jordan-Fly-Wade-II-sale-id-384.html Jordan Fly Wade II http://www.nikejordanairmaxshoes.com/cheap-Jordan-Alpha-Trunmer-sale-id-385.html Jordan Alpha Trunmer http://www.nikejordanairmaxshoes.com/cheap-Jordan-Heels-sale-id-386.html Jordan Heels http://www.nikejordanairmaxshoes.com/cheap-Air-Jordan-III-3--sale-id-387.html Air Jordan III(3) http://www.nikejordanairmaxshoes.com/cheap-Air-Jordan-V-5--sale-id-388.html Air Jordan V(5) http://www.nikejordanairmaxshoes.com/cheap-Air-Jordan-IV-4--sale-id-389.html Air Jordan IV(4) http://www.nikejordanairmaxshoes.com/cheap-Jordan-Retro-XI-11--sale-id-390.html Jordan Retro XI(11) http://www.nikejordanairmaxshoes.com/cheap-Jordan-3-5-Spiziker-sale-id-391.html Jordan 3.5 Spiziker http://www.nikejordanairmaxshoes.com/cheap-Nike-Shox-sale-id-358.html Nike Shox http://www.nikejordanairmaxshoes.com/cheap-Nike-Shox-R4-sale-id-392.html Nike Shox R4 http://www.nikejordanairmaxshoes.com/cheap-Nike-Shox-NZ-sale-id-393.html Nike Shox NZ http://www.nikejordanairmaxshoes.com/cheap-Nike-Shox-Turbo-sale-id-394.html Nike Shox Turbo http://www.nikejordanairmaxshoes.com/cheap-Air-Force-1-sale-id-359.html Air Force 1 http://www.nikejordanairmaxshoes.com/cheap-Air-Force-1-Heels-Hi-Top-sale-id-395.html Air Force 1 Heels Hi-Top http://www.nikejordanairmaxshoes.com/cheap-Nike-Dunk-SB-sale-id-360.html Nike Dunk SB http://www.nikejordanairmaxshoes.com/cheap-Nike-Dunk-Heels-Lo-Top-sale-id-396.html Nike Dunk Heels Lo-Top http://www.nikejordanairmaxshoes.com/cheap-Nike-Dunk-Heels-Hi-Top-sale-id-397.html Nike Dunk Heels Hi-Top http://www.nikejordanairmaxshoes.com/cheap-Nike-Dunk-Block-Heels-sale-id-398.html Nike Dunk Block Heels http://www.nikejordanairmaxshoes.com/cheap-Nike-Dunk-Block-Heels-Hi-Top-sale-id-399.html Nike Dunk Block Heels Hi-Top http://www.nikejordanairmaxshoes.com/cheap-Nike-Zoom-sale-id-361.html Nike Zoom http://www.nikejordanairmaxshoes.com/cheap-Hyperdunk-2011-Low-sale-id-400.html Hyperdunk 2011 Low http://www.nikejordanairmaxshoes.com/cheap-Zoom-Kobe-VI-sale-id-401.html Zoom Kobe VI http://www.nikejordanairmaxshoes.com/cheap-Zoom-Rookie-sale-id-402.html Zoom Rookie http://www.nikejordanairmaxshoes.com/cheap-Lebron-VIIII-9-sale-id-403.html Lebron VIIII 9 http://www.nikejordanairmaxshoes.com/cheap-Zoom-Kobe-VII-sale-id-404.html Zoom Kobe VII http://www.nikejordanairmaxshoes.com/cheap-Air-GO-LWP-sale-id-405.html Air GO LWP http://www.nikejordanairmaxshoes.com/cheap-Zoom-Lebron-VII-sale-id-406.html Zoom Lebron VII http://www.nikejordanairmaxshoes.com/cheap-Football-Soccoer-sale-id-363.html Football Soccoer http://www.nikejordanairmaxshoes.com/cheap-Tiempo-Legend-IV-sale-id-365.html Tiempo Legend IV http://www.nikejordanairmaxshoes.com/cheap-Nike-MERCURIAL-sale-id-366.html Nike MERCURIAL http://www.nikejordanairmaxshoes.com/cheap-Nike-Trail-Blazer-sale-id-364.html Nike Trail Blazer

JSP 맛보기

Web/JSP 2007. 10. 26. 10:30

김세곤 <sehkone@bawi.org>

1999년 12월 19일

이번 글은 JSP를 어떻게 쉽게 사용해 볼 수 있는지, 그 사용 방법에 대한 일종의 간단한 튜토리얼이다. 메카니즘에 대한 이해와 높은 난이도의 JSP 사용에 대한 글을 계속적으로 연재할 예정이다.

JSP의 문서 구성

JSP는 HTML문서안에 자바 코드를 써 넣는 방법으로 동적 문서를 생산한다. HTML안에 써 놓은 자바 코드는 웹 서버가 가동한 JVM을 통해 알맞는 HTML 문서로 동적 생산되어 브라우저로 보내진다. 정확하게 말하면 웹 서버의 여러 모듈 중 JSP를 담당하는 모듈이 이 일을 하게 된다. 메카니즘에 대한 소개는 뒤로 미루고, 우선 JSP 문서가 어떻게 구성되는지 살펴 보자. JSP 문서 내에 JSP를 위한 태그는 <% %>, <%= %>, <%@ %>, <%! %>, <jsp: /> 등이 있다(태그는 기본적으로 XML 체계를 따르고 있다). 먼저, <%@ %>, <% %>, <%= %> 태그를 살펴보자. 이것만으로도 어지간한 웹 문서는 모두 만들 수 있으며, <jsp: />는 1.0 이상에서만 가능하므로 간혹 지원을 제대로 하지 못 하는 환경이 있을 수도 있다. JSP문서의 기본 구성을 보자.

<%@ page contentType="text/html; charset=EUC-KR" %>
<HTML>
<HEAD><TITLE>JSP 문서</TITLE></HEAD>
<BODY>
<% 
    String email = 
"sehkone@bawi.org";

%> 저에게 연락을 하시고 싶으시면 <ahref="mailto:<%= email %>">여기를</a> 클릭하세요.

</BODY>
</HTML>

JSP의 구성은 매우 간단하다. 우선 맨 위의 <%@ page contentType="text/html; charset=EUC-KR" %>는 브라우저가 전송받는 문서가 HTML이고 한글 문서라는 사실을 알도록 하기 위한 것이다. 쉽게 생각해서, 이 줄은 공통적으로 모든 JSP파일의 첫머리에 들어가는 것으로 보면 된다. <% %>안에는 자바 코드가 들어간다. 위의 예에서는 String 클래스로 email 인스턴스(변수)를 만든 것이 전부이지만, <% %>안에는 코드의 분량에 구애됨이 없이 자유롭게 자바 코드를 써 넣을 수 있다. <% 로 시작한 자바 코드는 %>로 끝나며 다시 HTML 문서가 등장한다. 위의 예에서 "저에게...클릭하세요" 가운데를 살펴보면 <%= %> 태그를 볼 수 있는데, <%= %> 태그 안의 자바 코드 결과는 그대로 HTML 문서내에 보여지게 된다. 따라서, 위의 예는 다음의 HTML 문서가 되어 브라우저로 보내지게 된다.
<HTML>
<HEAD><TITLE>JSP 문서</TITLE></HEAD>
<BODY>

저에게 연락을 하시고 싶으시면 <a href="mailto:sehkone@bawi.org">여기를</a> 클릭하세요.

</BODY>
</HTML>

간단하지 않은가? 이제 여러분은 JSP 문서의 대체적인 골격은 이해하였다.

다음으로 넘어가기 전에 한 가지만 더 알아둘 것이 있다. 첫번째 줄 <%@ page ... %> 안에는 import 변수가 들어가는 경우가 많은데, java.io.*와 java.lang.*, javax.servlet.*, javax.servlet.http.*, javax.servlet.jsp.* 클래스는 JSP 문서에 기본적으로 import 되므로 굳이 import 변수에 명시할 필요가 없으나, 그 외의 클래스를 쓰고 싶다면 import 변수에 써 주어야 한다. JDBC를 쓴다면 java.sql.* 클래스를 포함시켜야 하고 자바 메일 클래스를 이용하려면 javax.mail.*, javax.mail.internet.* 등을 포함시켜야 하는데 이 경우는 다음처럼 쓰면 된다.

<%@ page import="java.sql.*, javax.mail.*,javax.mail.internet.*" contentType="text/html; charset=EUC-KR" %>

import의 값으로 포함시키고자 하는 클래스를 콤마로 구분하여 나열하기만 하면 되는 것이다.

GET, POST도 간편하게 - getParameter() 이용하기

동적인 문서 생산하기 위해서는 사용자와 호흡해야 하고, 이를 위해서는 브라우저 내에 사용자가 정보를 입력하는 일이 많다. 이 정보를 처리하기 위해서 JSP는 getParameter() 메쏘드를 제공한다. getParameter 메쏘드는 ServletRequest 인터페이스의 메쏘드로서 GET이나 POST로 넘어온 값들을 얻을 수 있도록 해 준다. ServletRequest는 HttpServletRequest가 계승하는데 JSP 표준 스펙에서는 HttpServletRequest 클래스 타입으로 request 인스턴스(변수)를 만든다. 따라서, JSP 문서에서 getParameter 메쏘드를 사용하려면 다음처럼,

String name = request.getParameter("name");

사용해야 한다. 다시 말하면, JSP는 컴파일되면 정상적인 자바 코드로 만들어진 서블릿이 되는데, 이 서블릿 코드 내에서 request는 내부적으로 사용되는 변수라는 말이다. 즉, JSP 문서 내에서는 request라는 이름의 인스턴스(변수)를 어떤 형태로든 사용할 수 없고, 프로그래머는 이미 만들어지는 request 인스턴스를 이용하여 getParameter(나중에 설명하겠지만, 쿠키를 얻기 위한 getCookies() 등과 같은 메쏘드도 포함된다) 메쏘드를 사용하면 된다. JSP가 서블릿으로 변환되면서 내부적으로 정의되는 인스턴스는 몇 가지가 더 있는데, 이는 추후에 차차 알아나가기로 하자. GET이나 POST로 전달되는 값을 처리하는 방법을 좀 더 자세히 코드를 봐 가면서 알아보자. 사용자의 이름과 비밀번호를 입력받아서 이를 확인하는 JSP를 예로 들겠다. 우선, 사용자의 이름과 비밀번호를 입력받는 Form을 사용한 HTML 문서를 만들어야 한다.
....
<form method="post" action="member.jsp">
이름 : <input type="text" name="username"><br>
비밀번호 : <input type="password" name="userpasswd"><br>
<input type="submit">
</form>
....

이 HTML문서의 이름, 비밀번호 필드에 적당한 값을 입력하고 submit 버튼을 누르면 이 값들이 member.jsp로 전달될 것이다. 이제, POST로 전달되는 값을 member.jsp에서 어떻게 받는지를 살펴보자.
<%@ page contentType="text/html; charset=EUC-KR" %>
<%
String name = request.getParameter("username");
String password = request.getParameter("userpasswd");
%>
<HTML>
<HEAD>
<TITLE>회원인가?</TITLE>
</HEAD>
<BODY>
이름은 <%= name %>이고, 비밀번호는 <%= password %>라고 입력하였습니다.
</BODY>
</HTML>

GET으로 전달받는 값들도 POST와 같은 방법으로 request.getParameter()를 사용하면 된다.

쿠키를 사용하자

웹 개발을 하다보면 쿠키를 사용할 일이 종종 있다. 쿠키에 대한 자세한 이야기는 필자가 따로이 글을 준비 중이므로 많은 기대 부탁드리며, 여기서는 간략하게 JSP에서 쿠키를 다루는 법만 소개하겠다.

먼저, 쿠키를 세팅하는 코드를 보기로 하자.

<%@ page contentType="text/html; charset=EUC-KR" %>
<%
String myEmail = "sehkone@bawi.org";
Cookie cookieEmail = new Cookie("email", myEmail);
cookieEmail.setMaxAge(-1);
response.addCookie(cookieEmail);
%>
<HTML>
<HEAD>
<TITLE>쿠키 세팅</TITLE>
</HEAD>
<BODY>
별로 하는 일은 없는 JSP 문서지만 쿠키를 세팅하는 예를 보여줍니다.
</BODY>
</HTML>

여기서, 새로운 인스턴스(변수)인 response를 만나게 된다. response는 JSP문서가 서블릿으로 변환될 때 내부적으로 사용하는 HttpServletResponse 클래스의 인스턴스(변수)로서, JSP 문서 내에서 자유롭게 사용할 수 있다. 앞서 언급한 request가 사용자의 요청에 관한 것을 다룬다면, 이 response는 사용자의 요청에 대한 JSP 문서의 응답에 관한 것을 다룬다. 초보 단계에서는 역시 자세한 메카니즘에 대한 이해는 뒤로 미루어 두고, 쿠키를 사용하기 위해서는 response 변수를 사용하여 addCookie() 메쏘드를 호출해야 한다는 사실을 알아두자. 염두에 둘 것은 request, response가 인스터스들이므로 이와 같은 이름의 다른 인스턴스를 정의하면 안 된다는 사실이다.

한 줄 한 줄 살펴보자. 자바 코드 부분의 첫번째 줄에서는 이메일 주소를 스트링 인스턴스에 넣었다. 두번째 줄은 Cookie 클래스 타입으로 새로운 쿠키를 만드는데, 그 이름은 email이고 값은 myEmail 인스턴스 값으로 한다는 뜻이다. 세번째 줄에서는 이 쿠키의 유효 기간을 설정하는 것인데, -1처럼 음의 값은 브라우저 종료 시까지 이 쿠키가 유효하도록 하는 설정이다. 0은 이 쿠키를 없애라는 설정이며, 특별히 유효 기간을 명시하고 싶으면 setMaxAge 메쏘드의 인자로 초 단위 값을 써 주면 된다.

브라우저에 쿠키를 세팅하는 방법을 살폈고, 이제 브라우저로부터 쿠키를 얻는 방법을 알아보자. JSP나 서블릿에서 쿠키를 얻을 때는 쿠키 이름을 명시하여 얻을 수 있는 방법은 없고 모든 쿠키를 다 받아서 각각의 쿠키의 이름과 값을 검사하는 방법을 사용해야 한다. 다음의 예는 쿠키 중에서 그 이름의 "id"인 것을 찾아서 그 값을 출력하는 JSP이다.

<%@ page contentType="text/html; charset=EUC-KR" %>
<HTML>
<HEAD><TITLE>id 쿠키 값 검사</TITLE></HEAD>
<BODY>
<%
Cookie[] cookies = request.getCookies();
for (int i = 0; i < cookies.length; i++) {
   Cookie thisCookie = cookies[i];
   if ("id".equals(thisCookie.getName())) {  // if문 시작
%>
아이디는 <%= thisCookie.getValue() %> 입니다.<BR>
이 부분에는 자유로운 HTML 코드가 들어갈 수 있습니다.
<%
   }  // if문의 끝
%>
</BODY>
</HTML>

for 문 두 줄 아래의 if문 내의 JSP 형태를 주의깊게 보도록 하자. <% } %>로 if 문을 닫아 주는 일을 종종 잊는 경우가 많은데 항상 신경을 쓰도록 하자.

이제, 특정한 쿠키를 찾아서 그 쿠키를 없애는 방법을 알아보자. 바로 위의 코드에 몇 줄만 추가하면 id 쿠키를 없앨 수 있다. 다음을 보자.

<%@ page contentType="text/html; charset=EUC-KR" %>
<HTML>
<HEAD><TITLE>id 쿠키 값 없애기</TITLE></HEAD>
<BODY>
<%
Cookie[] cookies = request.getCookies();
for (int i = 0; i < cookies.length; i++) {
   Cookie thisCookie = cookies[i];
   if ("id".equals(thisCookie.getName())) {  // if문 시작
%>
아이디는 <%= thisCookie.getValue() %> 입니다.<BR>
이 부분에는 자유로운 HTML 코드가 들어갈 수 있습니다.
<%
        thisCookie.setMaxAge(0);   // 쿠키를 없애라는 유효기간 설정
        response.addCookie(thisCookie);   // 다시 쿠키를 세팅
   }  // if문의 끝
%>
이제 id 쿠키는 없어졌습니다.
</BODY>
</HTML>

데이터베이스를 맘대로 - JDBC

웹 개발에서 역시 가장 중요한 부분은 데이터베이스와의 연동이다. JDBC는 필자가 별도의 쓰레드로 연재할 생각이며, 여기서는 역시 맛만 보도록 하자.

JDBC를 사용하기 위해서는 사용하는 데이터베이스의 JDBC 드라이버를 설치하여야 한다. postgreSQL의 경우는 http://www.retep.org.uk/postgres/에서 JDK 버전에 따른 드라이버를 구할 수 있다.

역시, 예제부터 보자.

<%@ page import="java.sql.*" contentType="text/html; charset=EUC-KR" %>
<%
    String userId = request.getParameter("userid");
    Connection db;
    ResultSet rs;
    PreparedStatement stmt;

    try {
        Class.forName("postgresql.Driver");
    } catch (java.lang.ClassNotFoundException e) {
        System.err.println(e.getMessage());
    }

    try {
        db = DriverManager.getConnection("jdbc:postgresql:dbname", "dbuser", "password");
        stmt = db.prepareStatement("SELECT id, name FROM member WHERE id = ?");
        stmt.setString(1, userId);
        rs = stmt.executeQuery();       
        rs.next();

        String resultId = rs.getString("id");
        String resultName = rs.getString("name");
        
        stmt.close();
        rs.close();
        db.close();
    } catch (SQLException e) {
    }
%>
<HTML>
<HEAD>
<TITLE>
JDBC 사용
</TITLE>
</HEAD>
<BODY>
<%= resultId %>의 이름은 <%= resultName %> 입니다.
</BODY>
</HTML>

JDBC를 사용하기 위해서는 JDBC 드라이버를 로드해야 하는데, 이를 위해서 다음처럼 한다.
try {
    Class.forName("postgresql.Driver");
} catch (java.lang.ClassNotFoundException e) {
    System.err.println(e.getMessage());
}

쉽게 생각하여 이 부분은 모든 JSP 문서에서 DB에 연결하기 전 공통적으로 들어간다고 보면 된다. 다음으로 DB와 연결해야 하는데, 이를 위해서 다음처럼 한다.
db = DriverManager.getConnection("jdbc:postgresql:dbname", "dbuser", "password");

첫번째 인자는 접속하고자 하는 DB 이름을 알려주는 것인데, 앞의 jdbc:postgresql은 사용되는 드라이버 이름이다. 이 부분은 개별 DBMS에 따라 다른데, 드라이버 설치 문서에 나와 있으므로 참고하여 명시하면 된다. jdbc:postgresql: 다음에는 접속하고자 하는 DB이름을 그대로 쓰면 된다. 두번째, 세번째 인자는 접속하고자 하는 DB의 사용자 아이디와 비밀번호를 써 넣으면 된다.

JDBC는 DB에 질의를 던지는 방법으로 두 가지를 제공하고 있다. Statement와 PreparedStatement 클래스가 그 두 가지 방법인데, 여기서는 PreparedStatement에 대해서 간단히 설명하겠다. 먼저, DB에 묻고자 하는 질의를 다음과 같은 방법으로 생성한다. stmt는 PreparedStatement 클래스의 인스턴스여야 하며, prepareStatement의 인자로는 SQL 구문이 들어간다.

stmt = db.prepareStatement("SELECT id, name FROM member WHERE id = ?");

여기서, ?는 정해지지 않은 값으로서 다음처럼 세팅한다.
stmt.setString(1, userId);

다음으로, 이 질의를 DB에 던지고 결과를 받는다.
rs = stmt.executeQuery();       
rs.next();

rs는 ResultSet 클래스의 인스턴스이며, next 메쏘드는 질의 결과로 얻어진 릴레이션에서 튜플 포인터를 하나씩 증가시키는 일을 한다. 쉽게 말해서, 얻어진 질의 결과를 한 줄씩 넘기는 것이라 보면 된다. 현재 가리키고 있는 튜플의 필드 값을 읽기 위해서는 getXXX 메쏘드를 사용하는데 필드의 타입이 문자열이라면 getString을 쓰면 된다.
String resultId = rs.getString("id");
String resultName = rs.getString("name");

위와 같이 하면 id, name 필드 값이 각각 resultId와 resultName 스트링에 저장되게 된다. 마지막으로 PreparesStatement, ResultSet, Connection 인스턴스들을 없애는 일을 해야 한다.
stmt.close();
rs.close();
db.close();

사실, Java는 Garbage Collection 기능이 있으므로 불필요한데, Sun에서는 외부 클래스를 사용할 경우 이 기능이 제대로 수행되지 못 할 가능성 때문에, close 메쏘드를 사용하기를 권장하고 있다.

마치며

이번 글에서는 JSP와 JDBC를 맛 보았다.

사실, 위에서 설명한 request.getParameter() 메쏘드는 beans를 사용하면 거의 사용할 일이 없다. 초기에는 beans를 지원하지 못하는 환경이 많았으나 요새는 대부분 지원이 가능하므로, 독자 여러분은 우아한 beans를 사용하여 JSP 문서를 개발하도록 하자. Beans에 대해서는 WebDox의 JSP에서 Beans 사용하기를 참고하면 자세한 사용법을 알 수 있다. Beans가 없는 JSP는 생각하기 어려우므로 꼭 살펴본다.

JDBC에 대해서는 좀 더 상세한 용법이 WebDox의 JDBC를 익히자에 있으므로 참고하면 좋겠다.

Posted by 행복한 프로그래머 궁금쟁이박
TAG JSP

댓글을 달아 주세요

JSP에서의 include

Web/JSP 2007. 10. 26. 10:29
★ JSP에서의 include

Last Modified 2003/06/06
Written by hsboy
ReadCount 10276


JSP 에서는 두가지 방법으로 다른 문서를 현재의 문서에 포함 시킬수 있습니다. 이번 강좌에서는 이러한 두가지 include 문에 대해서 알아 봅니다.

* include 란?

다른 웹 언어(PHP or ASP등)를 프로그래밍 해본 경험이 있으신 분들은 include 가 무었인지 잘 알고 있을 것입니다.
include 란 현재의 문서에 다른 문서, 즉 다른 파일의 내용을 포함시켜 출력하는 것을 말합니다. 예를 들어 doc1.jsp 라는 문서의 내용이 아래와 같다고 합시다.

doc1.jsp
<%@ page contentType="text/html;charset=euc-kr"%>
<%
    out.print("<h2>이것은 doc1.jsp의 내용입니다.</h2>");
%>

그리고 doc2.jsp 의 내용이 아래와 같을때

doc2.jsp
<%
    out.print("<h2>이것은 doc2.jsp의 내용입니다.</h2>"); 
%>

위의 두개 문서의 출력을 한번에 보고자 할 때 include를 사용합니다.

doc3.jsp
<%@ page contentType="text/html;charset=euc-kr"%>

<jsp:include page="doc1.jsp" flush="true" />

<%@include file="doc2.jsp" %>

위의 doc3.jsp 를 출력하면 아래와 같은 화면이 출력됩니다.

doc3.jsp 실행화면


위의 소스에서 눈여겨 볼 부분이 doc2.jsp 의 상단 부분인데, doc2.jsp에는 page Directive가 생략 되어 있습니다. 이것은 두가지 include 방식의 차이 때문인데, 자세한 설명은 아래에서 하도록 하겠습니다.
또한 이러한 기능을 SSI(Server Side Include)를 이용해서 구현할수도 있는데 이것은 apache웹서버에서 지원하는 내용 이므로 여기에서는 다루지 않도록 하겠습니다. 자세한 내용이 궁금하신분은 여기를 참고 하시기 바랍니다.


* JSP Action - <jsp:include page="URI" flush="true" />

[syntax]
1). body 구문이 없는 경우
<jsp:include page="URI" flush="true" />

2). body 구문이 있는 경우
<jsp:include page="URI" flush="true">
<jsp:param name="파라메터이름" value="파라메터값" /> /* xxx.jsp?파라메터이름=파라메터값 */
</jsp:include>  

위와 같이 두가지 사용 용법이 있으며, 두번째 방법을 사용하면 해당 jsp파일에 파라메터값도 넘겨 줄수가 있습니다.
JSP Action 구문의 include 는 include되는 파일과 include 시키는 파일(doc1.jsp와 doc3.jsp)를 각각 컴파일 한후 두 파일의 실행 결과를 한곳에 합쳐서 출력을 하게 됩니다. 즉, 완전히 "별도로" 동작하게 됩니다.
여기에서 flush="true" 문장은 true나 false 가 들어 갈수 있는 부분으로써 include를 실행하기 전에 out.flush()를 실행할지 여부를 결정하는 것입니다. 물론 true일때 out.flush()를 실행하겠지요. JSP 스펙 1.1 까지는 반드시 true로 설정이 되어 있어야만 했으니, 1.2 부터는 true/false중 원하는것을 선택하면 됩니다.


* include 지시어 - <%@ include file="URI" %>

include 지시어 와 Action 구문과의 가장 큰 차이점은 include 지시어는 컴파일 되기전에 파일이 내용이 합쳐진다는 것입니다. 즉, doc3.jsp 는 doc2.jsp의 내용을 자신의 문서내에 포함하여 하나의 파일로 인식한다는 것입니다. doc2.jsp 에 보면 page Directive 가 생략이 되어 있는데, 그것이 바로 이러한 이유 때문입니다.

doc2.jsp에도 page Directive를 설정해 주었다면 에러가 발생할 것입니다. 하나의 페이지에 두번 선언을 하는 꼴이 되어 버릴테니까 말이죠.


* Action 구문과 include 지시어의 중요한 차이점

JSP프로그래밍을 조금이라도 접해 보신 분들이라면 누구나 아는 대로 JSP는 먼저 servlet 으로 변환되고, 그 다음 servlet 이 컴파일 되어 그결과를 화면에 출력해 주게 되어 있습니다.
그런데, Action 구문을 사용 하였을 때에는 두개의 파일 각각 다른 파일처리 되어 두개의 servlet 파일 생성하게 됩니다. 따라서 어느 한 파일이 수정되면 곧바로 적용되어 화면에 출력이 되게 됩니다.

하지만 include 지시어 문을 사용하게 되면 하나의 servlet 파일이 생성되게 됩니다. 이로 인해 엄청난 차이점이 발생하게 되는데, JSP의 특성상 JSP파일이 조금이라도 수정이 되어 있으면 servlet 으로 재 변경되어 다시 컴파일이 이루어 지게 됩니다. 그런데, doc2.jsp 파일을 내용을 수정하고, doc3.jsp 파일을 부르게 되면 수정되기 전의 doc2.jsp 파일의 내용이 출력됩니다.

또다시 doc3.jsp 파일을 살짝 고치고 doc3.jsp 을 부르게 되면 이제서야 수정된 doc2.jsp파일의 내용이 화면에 출력 되게 될 것입니다. 눈치 빠르신 분들은 알아 차리셨으리라 생각됩니다만..
이렇게 된 원인은 아무리 doc2.jsp의 내용이 수정된다 하더라도 JSP엔진에서는 doc3.jsp가 수정이 되지 않아 JSP 엔진에서는 수정되지 않은 같은 파일로 인식하여, servlet 파일을 다시 생성하지 않았기 때문입니다.

따라서, include 지시어 문을 사용하셨을 경우에는 두개의 파일 모두 수정해 주어야(doc3.jsp는 공백하나가 추가 되더라도 수정되어야 합니다) 원하는 결과를 얻을수가 있게 됩니다.
이경우 하나의 파일을 여러개의 파일에서 include 지시어 로 include 하였다면 이것은 치명적일수도 있습니다. 예를 들어 dbcon 같은 내용을 만들어 include 해서 사용하는 경우 상당히 많은데, 이럴때 큰 문제 거리가 될수도 있습니다.
이러한 문제점을 한번에 해결하는 방법이 있는데, ...tomcat/ 디렉토리에 보면 work 라는 디렉토리가 있습니다. 이곳이 바로 변환된 servlet 파일들이 저장되어 있는 곳인데, 이 디렉토리를 완전 삭제 한후에 tomcat을 재시작 시키면, 변경된 내용들이 한번에 적용이 될것입니다.(모든 servlet 파일이 재작성되니 당연한 결과 이겠지요)
그런데 이러한 특징은 tomcat 5 버젼대부터 달라지게 되었는데, include되는 파일을 수정하더라도 서블릿 컨테이너가 알아서 모두 재 컴파일 해준다는 것입니다. 필자가 확인한 바로는 OC4J 최신 버젼에서도 tomcat 5와 같이 자동으로 처리되었습니다.


저자 : 이선재(hsboy)
http://www.aboutjsp.com
다른곳에 올리실 때는 반드시 출처를 명시해 주시기 바라며 되도록 이면 링크를 걸어 주시기 바랍니다.
Posted by 행복한 프로그래머 궁금쟁이박
TAG JSP

댓글을 달아 주세요

YUI 라이브러리

Web/JavaScript 2007. 10. 7. 00:45

http://developer.yahoo.com/yui/

YUI 라이브러리

Posted by 행복한 프로그래머 궁금쟁이박

댓글을 달아 주세요