• Home
  • About
    • on Weekend photo

      on Weekend

      𝙎𝙩𝙪𝙙𝙮𝙞𝙣𝙜

    • Learn More
    • Instagram
    • Github
  • Archive
    • All Posts
    • All Tags
    • All Categories
  • Categories
    • Problem Solving
    • TIL
    • Study
    • Etc
    • 필사
  • Projects

서블릿과 스프링

03 Feb 2021

서블릿과 스프링

서블릿이란?

  • 클라이언트 요청에 대해 동적으로 작동하는 웹 어플리케이션 컴포넌트이다.
  • Java Thread를 이용하여 동작 -> 요청 당 쓰레드를 만들거나, 풀에서 가져다가 사용한다
  • MVC 패턴에서 Controller로 이용된다.
  • javax.servlet.http.HttpServlet 클래스를 상속받는다. HTML 변경 시 Servlet을 재컴파일해야 하는 단점이 있다.

동적 작동

왜 동적이라고 하는걸까? 미리 만들어둔 페이지를 그대로 보여주는게 아니라, 사용자(클라이언트)의 요청에 따라 다른 페이지를 제공해주고, 필요한 응답을 해주는 까닭이다.

  • 서블릿 : 웹 서버가 동적인 페이지를 제공할 수 있도록 도와주는 어플리케이션
    • 플랫폼 독립적
    • 요청 당 쓰레드 생성
  • CGI(Common Gateway Interface) : 동적인 페이지를 생성해줌
    • 웹서버와 프로그램의 교환방식
    • 서블릿 등장 이전에는 CGI만을 사용했다. 서블릿이 요청 당 쓰레드를 만들어 반환하는 대신, 서블릿은 요청 당 프로세스를 만들어 사용한다.

서블릿의 동작

image-20210203204154875

사용자가 특정 요청을 보냄, URL을 입력해서 -> 서블릿 컨테이너(ex. 톰캣)가 객체(HttpServletRequest, HttpServletResponse)를 생성한다. -> web.xml을 기반으로 이 URL이 어느 서블릿에 대한 요청인지 찾는다. -> 해당 서블릿을 찾아서 service 호출 -> doGet() 또는 doPost() 호출 -> doGet() 또는 doPost() : CGI를 이용해 동적페이지 생성 후 HttpServletResponse 객체에 응답을 보냄 -> 응답 종료 후 HttpServletRequest, HttpServletResponse는 서블릿 컨테이너가 소멸시킨다 (서블릿 컨테이너는 서블릿 생명주기 관리를 해준다)

서블릿 리스너

서블릿 컨테이너에서 발생하는 주요 이벤트를 감지하고, 각 이벤트에 특별한 작업이 필요한 경우에 사용한다.

implements ServletContextListener를 사용해 오버라이딩받아 사용할 수 있다. 서블릿 리스너는

1. 서블릿 컨텍스트 수준의 이벤트
 	2. 세션 수준의 이벤트

에 대한 작업을 수행할 수 있다. 가령 컨텍스트의 라이프 사이클을 감지하여, Context가 시작되면 ServletContext에 setAttribute를 해주어 ServletContextEvent에 넘겨줄 수 있다.

리스너를 구현, 등록한 후에는 서블릿에서 리스너에서 등록해준 ServletContext의 Atrribute를 받아오면 된다. 가령 여러개의 서블릿들이 공통적으로 사용할 객체들을 넣어두는 등의 작업에 리스너를 사용할 수 있을 것이다.

리스너 등록

<listener>
    <listener-class>...</listener-class>
</listener>

web.xml에 등록해주면 된다.

서블릿 필터

들어온 요청을 서블릿으로 보내고, 작성한 응답을 클라이언트로 보내기 전에 특별한 처리가 필요한 경우에 사용할 수 있다.

리스너는 서블릿 컨텍스트 위에 있는 개념이다. 서블릿 컨테이너가 요청을 받으면, 필터를 거쳐서 서블릿으로 보내준다. implements Filter를 해주면 상속받아 자신의 필터를 만들 수 있다.

doFilter에서는 무엇을 할까?

Filter chain이라는 인자가 들어오는데, 이를 이용해 다음 필터로 연결해주어야한다. chain.doFilter(request, response) 로 작성을 하여 보내주면 된다.

필터 등록

web.xml에서 필터를 등록할 수 있다. 서블릿 등록과 유사하다.

<filter>
    <filter-name>myFilter</filter-name>
    <filter-class>...</filter-class>
</filter>
<filter-mapping>
        <filter-name>myFilter</filter-name>
        <servlet-name>hello</servlet-name>
</filter-mapping>

돌려보면 서블릿 init() -> Filter에 도착해서 -> chaining을 거쳐서 서블릿으로 넘어가게 된다.

종료하면 서블릿 destroy() -> Filter destroy -> listener destroy() 된다.

스프링과의 연결

스프링을 사용한다

1. 스프링의 **IoC 컨테이너**를 활용한다
 	2. **스프링 MVC**를 사용하겠다

는 의미가 있다.

스프링 IoC 컨테이너 활용

Context Loader Listener

서블릿 리스너 구현체인 ContextLoaderListener을 사용할 수 있다. 이는 스프링의 ApplicationContext를 서블릿 생명주기에 맞추어 사용할 수 있도록 하는 것이다. 가령 서블릿이 종료될 시점에 ApplicationContext를 종료해준다.

스프링 MVC 연동

DispatcherServlet

요청 하나당 서블릿을 만들면 설정 파일이 너무 길어질 것이다. 또한, 여러 서블릿에서 공통적으로 사용하고 싶은 기능이 있다면, (물론 Filter를 사용할 수도 있지만) 이 역시 번거로울 것이다.

이를 위한 디자인 패턴으로 Front Controller가 있는데, 이는 컨트롤러 하나가 모든 요청을 받아서 분배해주고, 해당 요청을 처리할 핸들러들에게 Dispatch해준다.

image-20210203213329067

스프링은 이러한 프론트 컨트롤러의 역할을 하는 서블릿을 미리 구현해두었다. 그것이 스프링 MVC의 가장 핵심적인 클래스인 DispatcherServlet이다. 이는 ServletContext에 등록되어있는 ApplicationContext를 부모로 삼아서 Root WebApplicationContext를 만든다. 그리고 이를 여러 다른 서블릿에서도 공유해서 쓸 수 있다.

Dispatcher Servlet의 흐름

img

dispatcher Servlet은 web.xml의 역할을 자동으로 도맡아서 해주게 됩니다.

  1. 클라이언트는 URL로 접근하여 정보를 요청합니다.
  2. FrontController인 DispatcherServlet은 는 해당 요청을 받아, 매핑한 컨트롤러가 있는지 검색합니다.
  3. HandlerMapping은 Controller에 처리요청을 보냅니다.
  4. Controller는 클라이언트의 요청을 처리한 후, 결과를 출력할 View의 이름을 리턴해줍니다.
  5. DispatcherServlet은 컨트롤러에서 보내온 View 이름을 토대로 처리 View를 검색합니다.
  6. ViewResolver는 View에 대한 처리 결과를 View에 송신해줍니다.
  7. 처리 결과가 포함된 View는 다시 DispatcherServlet으로 송신됩니다.
  8. DispatcherServlet은 이를 받아, 클라이언트로 최종 결과를 출력해줍니다.

Ref

  • JSP 서블릿이란
  • Web Application Structure 이해하기
  • Dispatcher Servlet이란
  • 백기선님의 스프링 웹 MVC 강의


springbackendweb Share Tweet +1