Hayden's Archive

[Servlet] 웹 서버 및 WAS 매커니즘 순서 / 컨테이너 / CGI / pre-loading 본문

Study/Java & Kotlin

[Servlet] 웹 서버 및 WAS 매커니즘 순서 / 컨테이너 / CGI / pre-loading

_hayden 2020. 6. 9. 19:34
 * 컨테이너 = WAS 
컨테이너는 본질적으로 메모리 공간.
- 컨테이너는 JVM 위에 탑재됨. JVM보다 훨씬 광범위하고 파워풀하고 다채로움. 서블릿들이 컨테이너에서 만들어지고 요청을 받고 뭔가가 만들어지고 뭔가가 많이 없어지고 이런 것들이 메모리.
- 컨테이너 = 서블릿들이 생성되고 실행되는 제반적인 환경 그 자체.
 * CGI = Common Gateway Interface 
CGI는 서버 사이드에서 돌아가는 전반적인 프로그램. 자바 기반은 스레딩 방식으로 돌아가고 자바 기반이 아닌 것은 프로세스로 일일이 요청에 수행.
CGI 기술
=> 컨테이너(=WAS) 상에서 실행하는 프로그램을 통칭. 서버상에서 돌아가는 다이나믹한 기술을 CGI 기술이라고 한다. 
ASP, PHP, Pearl, JSP, Survlet,... => 이것들을 한꺼번에 CGI 프로그램이라고 한다.

 * 서블릿 
- 서블릿은 ASP, PHP와 달리 요청이 들어오기 전에 서버가 가동되자마자 xml을 읽어서 서버 내 서블릿 인스턴스가 이미 만들어져있음. 그리고 나서 요청을 받음.  
- 즉, 서블릿 인스턴스는 WAS 가동하고 만들어짐만들어놓고 초기화함. 서블릿은 서버 꺼야 죽는데 destroy는 서버 stop할 때 호출됨. 서버 stop하기 전까지 호출 안 됨.

 

< 전체적인 순서 > ( Servlet의 Life Cycle 관련 메소드 3가지 / Attribute 3가지  )

 클라이언트(브라우저)로부터 요청을 받기 전 

1. DD 파일(web.xml)을 읽어들인다. (서블릿 정보와 초기화(Initialization) 정보가 담겨 있다.)

2. DD 파일을 읽자마자 가장 글로벌한 객체인 ServletContext 객체가 생성된다.

3. 서블릿 매핑 정보에 맞게 WAS가 기본 생성자를 호출해서 서블릿을 생성한다.(개발자가 만들지 않고 WAS가 만들기 때문에 명시적 생성자는 호출될 수 없다.)

4. 서블릿 생성 직후에 ServletConfig 객체가 생성된다.

5. init()이 호출되는데 ServletConfig 객체를 인자값으로 받는다.(개발자가 명시적 생성자를 호출 못하니까 개발자는 init() 메소드로 필드 초기화(field initialization)를 할 수 있음. / Servlet을 상속받은 GenericServlet은 메소드 오버로딩해서 인자값을 받지 않는 init()도 가지고 있다.)

※ 주의
- 최초의 클라이언트가 요청할 때 1~5번까지 다 하고 요청받음. 그렇다 보니 최초의 클라이언트는 딜레이 시간이 길다.
- 그런데 서버는 요청과 상관 없이 Ready-On 상태가 되어있어야 하는데, 디폴트 값은 lazy loading이다. 
- 그러므로 web.xtml에서 </servlet> 바로 앞에 <load-on-startup>1</load-on-startup>라고 써줘서 pre-loading으로 만들어준다.
- 위 태그의 사이에 있는 숫자는 순번을 뜻한다. 서블릿 하나 만들고 1로 해주고, 서블릿 하나 더 만들면 2로 해주고, 그 다음에 서블릿 또 만들면 3으로 해주고... 이렇게! 서로 다른 인스턴스이므로 숫자 중복 안됨!

--------여기까지가 요청을 받을 준비를 마친 Ready-On 상태---------

 클라이언트(브라우저)로부터 요청을 받은 후 

6. 웹 서버가 요청을 받는다.(모든 요청과 응답은 반드시 웹 서버를 통과해야 한다.) 

7. 요청이 Static한 요청인지 Dynamic한 요청인지 판단한다. Static한 요청일 경우, Context Path 밑에 있는 Static한 문서로 응답한다.

8. Dynamic한 요청일 경우, 웹 서버가 처리할 수 없으므로 웹 서버 아래에 있는 컨테이너(WAS)에게로 요청을 보낸다.(이 때, WEB-INF 폴더가 Static과 Dynamic을 나누는 기준이 되는 디렉토리가 된다. 관련 포스팅 : https://hayden-archive.tistory.com/195#server )

9. 클라이언트가 요청을 하면 ServletRequest, ServletResponse, HttpSession 객체가 만들어진다. 또 요청이 들어올 때마다 스레드가 만들어지면서 ServletRequest와 ServletResponse를 인자값으로 받는 service() 메소드가 호출된다. 그리고 나서 doGet() 메소드와 doPost() 메소드가 재호출된다. 

10. service() 메소드를 실행하고 실행이 끝나면 웹 서버를 통해 클라이언트에게 응답한다.

MVC(Model-View-Controller) 패턴 : Model(DAO와 VO) & View(JSP) & Controller(Servlet)
서블릿은 앞에서는 화면과 손 잡고, 뒤에서는 DAO와 손 잡는다. 
1. 서블릿이 제일 먼저 클라이언트로부터 폼값을 받는다.
2. 폼값을 바탕으로 VO 객체를 생성한다.
   - 폼값 3개면 VO의 필드 3개, DB 테이블 컬럼 3개.
   - id로 회원 검색하는 경우 id 하나 밖에 없으니까 이 과정 패스. 경우에 따라 다름.
3. DAO(이 때 DAO는 싱글톤) 리턴 받고 Business Logic을 호출 → DAO가 DB의 데이터를 조작하거나 DB로부터 데이터를 받아온다.
   - 예: registerMember(vo), getMember(id)
   - 이에 따라 DAO가 DB 가서 한줄 추가 / DAO가 DB 가서 찾음
4. 받아온 데이터가 있을 경우, 이 데이터를 Attribute에 바인딩한다.
5. 서블릿이 페이지 이동(forward/redirect)하고 JSP를 통해 출력한다.

11. ServletRequest, ServletResponse, 스레드가 메모리(여기서는 컨테이너)에서 unbound 되어지면서 죽고 Servlet 인스턴스만 덩그라니 남겨진다.

12. 6~11번 반복. (같은 클라이언트가 요청하더라도 새로 들어온 요청은 전혀 다른 요청으로 인식함)

 

----------------------------------------------------

13. 서버를 Stop 시키면 Servlet 인스턴스의 destroy() 메소드가 호출되고 Servlet 인스턴스도 죽는다.