저번 시간까지는 JSP 웹 프로그래밍을 시작하기에 앞서 기본적인 요소들을 알아보고 자바 기초 문법까지 간단하게 살펴보았다.
이번 시간에는 JSP 에서 필수적으로 이해해야 할 요소들에 대해 알아보려한다.
JSP 소스코드가 어떤 과정을 거쳐서 웹 브라우저의 서비스 요청에 응답하는지, 출력 버퍼에 응답 과정에서 어떻게 동작하는지에 대해서 알아볼 것이다. 하나씩 알아보자!
JSP의 처리과정
우선 처리과정을 그림으로 살펴보면 다음과 같다.
두 가지 경우로 나눠지는 걸 알 수 있는데 하나씩 알아보자.
웹 컨테이너는 클라이언트로 부터 요청이 들어오면 다음과 같이 처리를 한다.
▶ JSP에 해당하는 서블릿이 존재하지 않는 경우
→ JSP페이지를 컴파일하여 서블릿을 생성.
→ 생성된 서블릿을 사용하여 요청 처리
좀 더 자세하게 과정을 살펴보면 다음과 같다.
JSP페이지에서 자바 코드로 변환 → 자바 코드를 컴파일하여 클래스파일 생성(이것이 바로 서블릿!) → 웹 컨테이너에 결과 전송
▶ JSP에 해당하는 서블릿이 존재하는 경우
→ 바로 서블릿을 사용하여 요청 처리
* JSP 페이지를 변경하면 위의 그림처럼 처리과정을 다시 거쳐서 새롭게 생성한 서블릿을 실행한다!
또한, JSP를 실행한다는 것은 JSP 페이지를 컴파일한 결과인 서블릿 클래스를 실행한다는 의미이다.
출력 버퍼와 응답
JSP 페이지는 생성 결과를 웹 브라우저에 바로 전송하지 않고, 출력 버퍼가 불리는 곳에 임시로 저장했다가 한번에 전송한다. 아래 그림을 보자.
그림 설명을 보면 출력 버퍼를 통해 결과를 전송하는 것을 알 수 있다.
그렇다면 버퍼를 사용하는 이유는 무엇일까. 다음과 같은 이유로 버퍼를 사용한다.
버퍼의 장점
* 데이터 전송 성능 향상
▶ 한 번에 큰 단위로 데이터를 전송하는 것이 가능하다.
(네크워크 상에선 큰 단위로 한 번에 보내는 것이 더 높은 성능을 발휘한다)
* 실행 도중에 버퍼를 비우고 새로운 내용을 입력하는 것이 가능하다.
▶ <jsp:forward> 기능이 사용 가능하고 실행 과정에서 에러가 발생한 경우, 기존의 생성 내용을 버퍼에서 지우고 에러 화면을 출력하는 것이 가능하다.
* 버퍼가 다 차기 전에 헤더 변경이 가능하다.
▶ 헤더 정보는 가장 먼저 웹 브라우저에 전송되는 정보이다. 이 말은 버퍼에 있는 내용보다 먼저 전송된다는 것을 의미한다. 즉, 버퍼 내용이 전송되기 전까지는 헤더 정보를 얼마든지 변경할 수 있다는 것이다. 그러나 전송이 된 이후에는 변경이 불가능하다.
page 디렉티브에서 버퍼 설정하기
버퍼 속성을 통해 JSP 페이지가 사용할 버퍼를 설정 할 수 있다. 킬로바이트 단위로 버퍼의 크기를 지정한다.
▶ <%@ page buffer="4kb"%>
버퍼 속성에서 'kb' 를 붙이지 않으면 변환시 에러가 발생하므로 꼭 붙여줘야 한다!
* JSP 규약은 버퍼의 속성을 지정하지 않을 경우 기본적으로 8kb 이상의 크기를 갖는 버퍼를 지정한다. 이유는 출력결과가 대부분 8kb 이며 8kb 일때 성능이 가장 높기 때문이다.
버퍼 속성을 사용하지 않을 경우 속성값을 none 으로 지정해주면 된다. 이렇게 할 경우 다음과 같은 특징이 나타난다.
* JSP 페이지가 출력하는 내용을 곧바로 브라우저에 전송한다.
* <jsp:forward> 기능을 사용할 수 없다.
* 곧바로 전송되므로 출력한 내용을 취소할 수 없다.
플러시(flush)
: 버퍼가 다 찼을 때, 버퍼에 쌓인 데이터를 전송하고 버퍼를 비우는 것을 의미한다. (위의 그림에서 3번 과정이 플러시 하는 것을 나타내고 있다)
오토플러시(autoFlush)
: page 디렉티브가 제공하는 속성이다. 버퍼가 다 찼을 경우 어떻게 처리할지를 true/false 값으로 정할 수 있다.
* true : 버퍼가 다 찼을 경우 버퍼를 플러시하고 계속 작업을 진행
* false : 버퍼가 다 찼을 경우 예외를 발생하고 작업을 중지.
웹 어플리케이션 디렉터리 구성과 URL 매핑
웹 어플리케이션 디렉터리는 웹 어플리케이션이 위치하는 디렉터리이다. webapps에 위치한 test, ROOT 등의 디렉터리가 이에 해당한다. 또한 다음과 같은 하위디렉터리를 포함하고 있다.
* WEB-INF : 설정 정보를 담고 있는 web.xml 파일이 위치한다.
(web.xml 파일은 전체 JSP 파일의 공통적인 속성을 가지고 있다)
* WEB-INF\classes : 사용할 클래스 파일이 위치한다. (컴파일된 클래스파일들이 위치)
* WEB-INF\lib : 사용할 jar 파일이 위치한다.
나머지 디렉터리에는 JSP, HTML, 이미지 파일 등이 위치한다.
* 서블릿2.5/JSP2.1 부터는 단순 웹 어플리케이션의 경우 web.xml 파일이 존재하지 않아도 잘 동작한다. 하지만 다음의 경우에는 web.xml 파일을 작성해 주어야 한다.
→ 서블릿을 설정할 경우
→ 리스너(Listner)를 설정하는 경우
→ 특정 URL에 속하는 JSP들에 대해 공통 속성값을 설정할 경우
- 웹 어플리케이션 디렉터리와 URL의 관계
: 하나의 웹 어플리케이션은 하나의 디렉터리에 매핑된다.
웹 어플리케이션 디렉터리에 해당하지 않은 URL을 요청하면, 기본적으로 ROOT 웹 어플리케이션을 통하여 요청이 처리된다.
request 기본객체는 웹 어플리케이션의 경로를 알려주는 메서드를 제공하는데, 이 메서드를 사용하면 JSP 페이지와 서블릿이 포함된 웹 어플리케이션의 경로를 읽어올 수 있다.
▶ String request.getContextPath()
예제를 통해 확인해보자.
확인해보면 jsp 파일이 위치한 디렉터리의 경로가 출력되는 것을 확인할 수 있다.
* ROOT 디렉터리에 실행할 경우엔 빈 문자열("")이 출력된다.
- 하위 디렉터리 사용하기
: 기능별로 분류하여 사용하면 개발 과정이나 유지 보수 과정에 많은 도움이 된다.
웹 어플리케이션의 배포
실 서버에 배포하는 방법은 크게 다음과 같이 두 가지가 있다.
* 대상 디렉터리에 파일 직접 복사
* war 파일로 묶어서 배포
- 파일 직접 복사
: 간단한 방법이다. 실 서버의 웹 어플리케이션 디렉터리에 FTP나 Rsync 등을 이용하여 개발 서버에 있는 JSP/클래스/jar 파일 등을 복사하면 된다.
- war 파일을 이용한 배포
: war(Web Application Archive)의 약자로서 웹 어플리케이션의 구성 요소를 묶은 파일이다.
jar 명령어를 사용하여 다음과 같이 묶어주면 된다. (cvf 옵션 사용)
jar 명령어로 cvf 옵션을 사용하여 war파일을 생성한다. 뒤에 붙은 '*' 은 디렉터리내의 모든 파일을 포함한다는 것을 의미한다.
다음과 같이 war 파일이 정상적으로 생성되는 것을 확인할 수 있다.
이 파일을 실 서버의 webapps 디렉터리에 복사해주면 된다.
* 웹 로직 같은 상용 소프트웨어의 경우에는 웹 어플리케이션을 배포, 관리 할 수 있는 웹 기반 콘솔 프로그램을 제공한다. 제공된 프로그램을 이용하여 war 파일을 배포하고 관리할 수 있다.
우리가 쓰는 톰캣의 경우 웹 기반 콘솔을 통하여 war 파일을 배포할 수 있는 기능을 제공하지만, 널리 사용하지는 않는다.
톰캣같은 컨테이너에 war 파일을 배포하거나 개별 파일을 복사할 때는 이 작업을 담당자가 직접 하기보다는 Ant / Maven 같은 빌드 도구를 이용하여 자동화 하는 것이 일반적이다.
이상으로 JSP 의 처리과정과 버퍼 디렉터리의 특징 및 배포에 관하여 알아보았다.
이 부분도 역시나 잘 알아두어야할 내용 들이다. 다음 시간에는 좀 더 심화된 내용으로 포스팅을 이어가도록 하겠다.