-
JSP lifecycle & JSP에서 Servlet으로 변환하기language/Servlet&JSP 2019. 3. 4. 17:42반응형
클라이언트 요청을 받은 컨테이너가 매핑된 서블릿을 찾아서 service() 메소드를 실행시키는 것, 그리고 서블릿이 존재하지 않으면 클래스를 로드해서 인스턴스를 생성하고 초기화 시킨다는 것 까지 지난시간에 살펴 본 내용입니다.
컨테이너가 하는 일 중 또 다른 한 가지는 JSP 요청을 처리하는 것입니다.
JSP는 HTML 코드 안에 JAVA 코드가 포함된 형태를 가지고 있습니다. 하지만 일단 객체가 만들어지면 동작하는 방식은 servlet과 똑같습니다. 쉽게 말하자면 JSP는 포장된 servlet이라고 할 수 있습니다.
컨테이너가 서블릿 객체를 이용하고 싶으면 일단 jsp의 겉포장을 벗겨 내야 합니다. 이렇게 번거로운 작업을 하게 된 것은 코드 작성의 편의성을 위한 것입니다.
포장을 벗겨낸다는 것은 결국 JSP를 다시 java 코드로 변환하는 것입니다. 그래서 결과적으로는 jsp에서 다시 servlet 코드를 얻게 되는 것이죠.
이렇게 servlet 코드로 전환되게 되면 그 다음 부터는 일반적인 servlet과 똑같은 과정을 거치게 됩니다.
클래스가 로드되고 객체가 생성되고 초기화까지 다른 servlet과 똑같습니다. 그리고 컨테이너는 요청이 올 때 마다 해당하는 인스턴스의 service() method를 호출하게 되겠죠.
jsp에 대한 요청은 클라이언트에서 바로 들어올 수도 있고 다른 servlet에서 넘어올 수도 있습니다. (forward, include) 배포서술자를 통해 jsp를 매핑하는 것도 가능합니다.
jsp 파일에 대한 요청이 오면 컨테이너는 jsp의 서블릿 객체가 존재하는지를 확인합니다. 만약 아직 servlet이 생성되지 않은 상태라면 jsp를 servlet 으로 변환해서 객체화 하는 과정을 거치게 되고
이미 servlet 객체가 존재한다면 해당 객체의 service() method를 실행하게 됩니다.
그렇다면 컨테이너는 JSP를 어떻게 servlet으로 바꾸게 되는 걸까요? 컨테이너가 compile한 servlet 코드를 알아보기 전에 변환되기 전의 jsp 코드를 보겠습니다.
먼저 지시자가 등장합니다. 지시자(directive)는 컨테이너가 페이지를 자바 코드로 변환할 때 어떤 지시를 내릴 수 있도록 고안된 것입니다.
page(페이지 관련 환경 정의), include(포함할 코드나 문서를 정의), taglib(태그 라이브러리 정의) 지시자 등이 있습니다.
일단 우리는 page 지시자만 사용한다고 생각해 보겠습니다. page 지시자에 import 타입을 이용해서 실제 자바코드에 import 시킬 클래스를 정의할 수 있습니다.
자바코드를 이런식으로 태그안에 삽입하게 되는데 이 것을 스크립틀릿이라고 합니다. 이 스크립틀릿 안에 들어가는 코드들은 모두 생성되는 서블릿의 service() 메소드 안에 포함되게 됩니다.
여기서 일반적인 servlet과 차이를 알 수 있습니다. 일반적인 servlet이라면 service() 메소드에서 요청 받은 HTTP method를 파악해서 doGet(), doPost(), doPut(), doDelete() 등의 메소드를 호출하게 됩니다.
하지만 JPS 안에 들어있는 코드들은 일단 모두 service() 메소드에 들어가기 때문에 HTTP method를 구분해서 해당하는 메소드를 호출하는 과정이 servlet에서 일어나지 않습니다.
그리고 특이점은 선언되지도 않은 out이라는 변수를 그냥 쓰고 있다는 것입니다. out이라는 변수를 그냥 쓸 수 있는 것은 이 것이 JSP 컨테이너에서 제공하는 내장객체이기 때문입니다.
jsp는 어차피 servlet로 변환되게 됩니다. 그렇다면 servlet에서 사용하는 여러가지 객체들에 접근할 수 있어야 할 것입니다.
jsp에는 사용할 수 있는 내장객체가 9가지가 있습니다.
servlet으로 변환될 때 해당하는 객체 변수를 컨테이너가 선언해 주게 됩니다.
그런데 다른 객체는 모두 servlet에서 다뤘던 것들인데 한 가지 처음 보는 것이 등장합니다. pageContext인데요.
이름처럼 jsp 페이지에 필요한 정보를 가지고 있고 해당하는 jsp에서만 접근이 가능합니다. pageContext에 대해서는 잠시 뒤에 다시 살펴보도록 하겠습니다.
page는 this, 자기 자신을 가리키는 객체
컨테이너는 내장객체를 이런식으로 선언해서 사용합니다. 여기서 보면 servletConfig나 servletContext에 접근할 때도 pageContext를 이용하는 것을 볼 수 있습니다.
물론 service 메소드가 실행되는 시점에서는 초기화가 된 상태기 때문에 getServletContext()나 getServletConfig() 같은 메소드를 바로 사용할 수 있습니다.
그러나 pageContext 객체를 사용해서도 servletContext나 servletConfig에 접근할 수 있습니다. 또 pageContext에는 forward와 include 메소드가 있습니다.
그러면 jsp 내에는 servlet에서도 존재했던 세 가지에 pageContext 까지 더해 총 네가지의 속성범위가 존재하는 것을 알 수 있습니다.
이 때 page 속성은 해당하는 jsp 페이지 에서만 접근이 가능하고 페이지를 이동하면 사라지게 됩니다.
앞서서 소개했던 내장객체 중에 out이 있었는데요. 그런데 out 객체는 조금 쉽게 쓸 수 있는 방법이 존재합니다. 바로 표현식을 사용하는 거는 것입니다.
컨테이너는 왼쪽과 같은 표현식 코드를 만나면 오른쪽과 같은 코드로 변환합니다. 이렇게 표현식을 사용하게 되면 코드를 조금 더 간단하게 만들 수 있겠죠?
스크립틀릿 안에 들어가는 코드는 모두 service() method 안에 들어가는데 서비스 메소드 바깥에 쓰여지는 코드는 어떻게 표현할까요? 그럴 때는 선언문(declaration)을 사용합니다.
선언문은 서블릿의 멤버를 선언합니다. 컨테이너는 왼쪽에 있는 코드를 오른쪽과 같이 변환시킵니다. 클래스의 멤버변수로 number가 선언되고 add method가 만들어진 것을 볼 수 있습니다.
이게 servlet으로 모두 변환 된 이후 코드입니다. 특이점은 역시 service 메소드 안에서 http 요청 메소드에 대한 구분 없이 요청을처리하게 된다는 것입니다.
jsp를 통해 생성된 서블릿도 역시 초기화 메서드가 있습니다.jspInit() 메서드를 선언문 안에 재정의 하는 것으로 사용할 수 있습니다. 이 메소드는 서블릿의 init() 메소드에서 호출됩니다. 따라서 초기화가 끝난 다음에 호출됩니다.
역시 destroy method 도 존재합니다. 이 메소드 역시 서블릿의 destroy 메소드에서 호출됩니다.
jsp는 그림처럼 servlet으로 변환된 후 다른 서블릿들 처럼 클래스가 로드 되고 초기화 메서드가 실행된 후 service메소드에서 요청을 처리하고 destroy메소드를 실행 한 후 소멸하게 됩니다.
이렇게 jsp가 servlet으로 변환되는 과정을 모두 살펴봤습니다.
반응형'language > Servlet&JSP' 카테고리의 다른 글
Expression Language 표현식 언어 (0) 2019.03.04 표준 액션 태그 (0) 2019.03.04 HTML (0) 2019.03.04 ExecutorService (0) 2019.02.22 세션(Session) (0) 2019.02.22