스프링은 내장 톰캣을 가진다
서버내 저장소에 저장된 특정 정적인 문서나 자원의 제공을 목적으로 하는 웹서버는 Static하다고 말할 수 있다. 아파치는 이러한 작업을 수행하는 정적인 웹서버이다.
클라이언트가 사용하는 웹브라우저는 .html파일을 사용자 인터페이스의 형태로 변환하여 여러 기능을 제공해주는 탬플릿이나 문서 역할을 한다. 만약 html형식이 아닌 다른 형태의 문서를 넘겨주게 된다면, 웹브라우저는 정상적으로 인식하지 못할것이다.
아파치 내에 내장할 수 있는 톰캣은 사용자에게 응답되는 .jsp와 같은 탬플릿 문서를 컴파일하여 .html형식의 문서로 변환해주는 역할을 한다. 아파치는 웹서버의 역할을 수행하고, 톰캣은 웹서버 내부에서 정적이지 않은 문서를 생성하여 아파치에게 돌려주는 역할을 한다. 동적인 문서를 제공하는 아파치 톰캣 서버는 웹 애플리케이션 서버라 말할 수 있다.
스프링은 서블릿 컨테이너(톰캣)를 가진다
서버에 요청을 할 때 클라이언트는 특정 자원 식별자(Uniform Resource Identifier)를 사용하여 자신이 원하는 문서나 정보를 특정한다.
스프링은 기본적으로 URL로의 접근을 막아놓았다. 클라이언트의 요청은 특정한 정적 파일에 대한 요청이 될 수 없고, 무조건 자바를 통한 검증과정을 거쳐야 한다. 웹서버의 역할을 하는 아파치가 요청을 받지만, 자바로 컴파일을 진행하는 내부의 톰캣을 무조건 거쳐야한다는 뜻이 된다.
이러한 자바 프로그램의 과정을 수행하는 자바 내에 속한 서블릿 클래스를 서블릿이라 부르고, 서블릿 컨테이너는 서블릿 객체들의 생성, 실행, 소멸을 담당하는 컨테이너를 뜻한다. 스프링에선 톰캣이 서블릿 컨테이너의 역할을 수행한다.
서블릿 컨테이너의 작업 과정
톰캣은 요청을 받은 후, 요청에 대한 스레드를 각 기능마다 싱글톤 패턴으로 생성된 서블릿 객체위에 생성한다. 많은 요청이 들어온다면 서블릿 객체 위에 사전에 설정된 스레드의 개수만큼 생성한 후, 요청을 대기시킨다. 작업이 끝난 스레드가 있다면 대기하는 요청이 없어질때까지 순차적으로 할당시킨다. 대기하는 요청이 없다면 스레드를 소멸시킨다.
상세한 과정을 위의 그림과 함께 나타내면,
1.
웹서버로 부터 요청이 들어오면 제일 먼저 컨테이너가 이를 알맞게 처리한다.
2.
컨테이너는 배포서술자(web.xml)를 참조하여 해당 서블릿에 대한 스레드를 생성하고 요청(httpServletRequest) 및 응답(httpServeletResponse) 객체를 생성하여 전달한다.
3.
다음으로 컨테이너는 서블릿을 호출(service(httpServletRequest, httpServeletResponse))한다.
4.
호출된 서블릿의 작업을 담당하게 된 스레드(미리 생성된 스레드)는 요청에 따라 doPost() 또는 doGet()을 호출한다.
5.
호출된 doPost() 또는 doGet() 메소드는 생성된 동적페이지를 Response객체에 실어서 컨테이너에 전달한다.
6.
컨테이너는 전달받은 Response객체를 HTTPResponse형태로 전환하여 웹서버에 전달하고 생성되었던 스레드를 종료하고 요청(httpServletRequest) 및 응답(httpServeletResponse) 객체를 소멸시킨다.
스프링은 web.xml를 가진다(WAR / Without Tomcat일때)
web.xml이 담는 설정은 다음과 같다.
ServletContext의 초기 파라미터 설정
Session의 유효시간 설정
인증과정을 거쳐 신원이 확인되면 세션에 인증되었음을 증명하는 데이터들을 저장한다. 이 데이터들에 대해 유효시간을 설정하여 보안을 관리한다.
Servlet/JSP에 대한 정의 및 매핑
요청자가 칮는 자원을 정의하고, 어디 위치해있는지 매핑해준다.
Mime Type 매핑
Mime 타입의 종류를 알아내고, 타입에 맞는 파싱 전략을 사용할 수 있도록 매핑해준다.
Welcome File list
사용자가 루트 디렉토리나 특정 디렉토리 까지만 접근 했을때, 반환할 디렉토리 내의 default 페이지 파일을 반환하게 해주는 리스트 설정이다. 사용자가 들어온 디렉토리의 하위 전범위에서 검색을 하여 list에 등록된 파일 중 존재하는 파일을 반환한다.
Error Pages 처리
사용자가 존재하지 않는 파일에 접근할 때 에러페이지를 반환한다.
리스너/필터 설정
보안
스프링은 DispatcherServlet을 가진다
FrontController 패턴
요청이 들어오면 Tomcat이 자동적으로 Request와 Response객체를 생성해준다. Request 객체엔 사용자의 요청에 대한 모든 정보가 담겨있고, Response 객체는 이 요청 정보를 기반으로 응답에 필요한 정보를 담는다.
스프링은 기본적으로 URL로의 접근(자원에 대한 직접적 접근)을 막는다. 자원에 접근하기 위해선 서버 내부의 FrontController가 자원을 요청해야한다.
이때 새로운 요청이 생성되어 톰캣이 메모리상에 가지고 있던 request 객체를 덮어씌우게 되는데, 최초 요청자의 정보가 소실될 가능성이 있다. 이를 방지하기 위해 기존의 Request를 보존하는 RequestDispatcher이 필요하다.
RequestDispatcher 패턴
redirect 대신 forward를 실행하는 RequestDispatcher 패턴은 내부적으로 생성되는 request 뿐만 아니라, 사용자의 연속적인 요청(ex. 페이지 이동)에서도 request 정보를 유지한다. 이전 페이지를 응답받기 위해 사용자가 요청했던 데이터를 재사용 하여 다음 요청할 페이지 내에서도 사용할 수 있다.
DispatcherServlet
앞서 언급된 FrontController와 RequestDispatcher 두가지 패턴을 구현한것이 바로 DispatcherServlet이다. DIspatcherServlet이 자동 생성될 때 컴포넌트 스캔을 수행하여 수많은 객체들이 생성(IoC)되며, 보통 필터들이다.
요청이 들어오면 필터를 거친 후에 DIspatcherServlet에 도착하게 된다. DIspatcherServlet은 요청의 정보에 따라 특정 클래스로 데이터를 보낸다. 이 때, 클래스가 메모리에 할당 되어있지 않는다면 요청을 처리할 수 없을것이다.
DIspatcherServlet은 애플리케이션 시작시 모든 경로에서 컴포넌트 스캔을 수행하여 서블릿에 필요한 객체들을 메모리상에 미리 띄운 뒤 역할을 수행한다.
스프링은ApplicationContext를 가진다
web.xml과 DispatcherServlet의 과정 사이, ContextLoaderListener라는것이 존재한다.
이는 DB connection과 같이 전 프로젝트에 걸쳐 공용되는 설정과 객체들을 생성(IoC)하는 역할을 한다. 이 객체들이 생성되어 이룬 컨텍스트는 root 컨텍스트가 되고, 이후 DispatcherServlet에서 생성한 스레드별 객체들이 속한 root 컨텍스트를 부모로 상속받은 컨텍스트가 된다.
BeanFactory
@Bean으로 등록한 객체는 초기 컴포넌트 스캔에서 메모리에 로드되지 않고 필요할 때 호출되어 lazy-loadng사용이 가능하다.
스프링은ViewResolver를 가진다
컨트롤러가 Data를 반환할 때엔 반환값 그대로 MessageConverter가 response의 http body에 넣어 응답을 하게된다. 이 떄 기본 전략은 JSON이다.
만약 html 파일을 반환하게 될 경우, ViewResolver가 String 반환값에 prefix와 suffix를 이어 특정 경로의 파일을 반환한다.