서블릿의 요청 처리 과정
현재 우아한테크코스에서는 톰캣구현하기 미션을 진행중이다. 해당 미션을 진행하면서 서블릿에 대해 정리를 해보려고 한다.
서블릿
특정 비즈니스 로직을 처리하는 서블릿 객체를 개발자가 만들어놓음. 각 로직마다 하나의 서블릿 객체만 생성.
- 싱글톤이 아니다!: 싱글톤 패턴의 경우 객체로 딱 한 번만 생성할 수 있도록 클래스 내부적으로 처리해놓음.
- 톰캣이 구조상 서블릿을 한번만 생성할 뿐임.
HandlerAdapter와 HandlerMapping으로 나눈 이유
어댑터 패턴이 무엇인가 하면
• 현재 사용하고 있는 라이브러리가 더 이상 요구에 부합하지 않아 재 작성하거나, 다른 라이브러리를 사용해야 할 때가 있다. 다른 라이브러리를 사용하는 경우 Adapter 패턴을 이용해 기존 코드를 가능한 적게 변경하면서 새로운 라이브러리로 교체할 수 있다.
따라서, 기존의 인터페이스 기반의 Controller를 제거하고 어노테이션기반 Controller로 동작하게 만들 때 사용할 수 있다.
- 애노테이션 기반인 @Controller를 통해서 구현한다.
- HttpRequestHandler를 사용한다.
- Controller인터페이스를 사용한다.(2.5 버전까지만 사용하고 더 이상 사용하지 않는다.)
즉, Controller 인터페이스를 사용하는 방식에서 변환이 되면서 해당 코드를 어노테이션기반과 RequestHandler기반으로 바꾸기 위해서이다.
다이어그램 분석
HandlerAdapterRegistry는 객체를 반환하지만 HadnlerMappingRegistry은 Optional을 반환한다. 둘다 내부에서 예외처리를 하고 객체를 반환하지 않고 각각 다르게 반환하는 이유가 궁금했다.
해당 궁금증을 "존재하지 않는 리소스에 접근할경우 404를 반환해주세요~"라는 리뷰를 받고 해결한것 같다.
필자가 생각하기에 이러한 이유는 HandlerMappingRegistry는 핸들러가 없다면 예외 페이지를 보여주는 것과 같이 예외처리를 해줘야 한다. 따라서 Optional로 반환해서 Handler가 있는지 없는지를 dispatcherServlet에게 알려야 한다고 생각했다.
아래 코드처럼 redirect시키려면 dispatcher의 service에서 실행해야 하므로 Optional을 반환한다.
물론 HandlerMappingRegistry가 response까지 매개변수로 받아서 처리할 수 있다. 대신 이러면 객체의 책임이 너무 HandlerMappingRegistry로 넘어간다고 볼 수 있다. HandlerMappingRegistry는 핸들러를 찾는 역할만 하고 없다면 disptcherServlet에서 service에서 페이지를 반환하도록 처리했다.
요청 처리 과정
서블릿과 서블릿 컨테이너 요청 처리
톰캣: 서블릿 컨테이너 or WAS
- 클라이언트로부터 요청이 들어오면 웹 컨테이너(톰캣)이 요청을 받는다.
- 로그인을 처리하는 서블릿을 개발자가 작성했으면, 컴파일 후 만들어진 클래스파일을 웹 컨테이너(WAS)가 서블릿 객체로 만들어 논다.
- 로그인을 처리하는 서블릿은 하나만 만들어진다.
- 로그아웃을 처리하는 서블릿은 하나만 만들어진다.
- 하지만 싱글톤은 아니다. 내부가 싱글톤 구조가 아니다. 구조상 한 번만 만들 뿐
- 요청을 가지고 Request, Response 객체를 만든다.
- URL에 맞춰 적절한 서블릿을 찾아서 service()메서드를 실행한다. 파라미터로 Request, Response를 보내준다.
- 서블릿 객체는 하나지만 여러 스레드가 작동하므로 가능하다.
- response객체로 컨테이너에게 돌려주면 컨테이너는 클라이언트에게 준다.
- 서블릿 객체는 유지되지만, 쓰레드는 반납하고 Request, Response객체는 JVM에 반환한다.
디스패처 서블릿의 흐름은 아래 링크에 있다.