💡이 포스팅은 토비님의 인프런 강의인 토비의 스프링 부트 - 이해와 원리를 수강하고 학습한 내용을 정리한 포스팅입니다.
토비님의 강의를 수강하며 정리한 GitHub Repository 입니다.
이번 챕터에서는 Spring Boot의 기술을 사용하지 않고 Servlet
을 사용하여 서블릿 컨테이너를 구성하는 방식을 학습합니다.
Spring에서는 기본적으로 DispatcherServlet
이 있지만 Spring이 없던 Java EE 시절에는 직접 서블릿을 하나씩 등록하는 방식과, 이 방식을 Front Controller
패턴을 사용하여 조금 더 개선한 방식 총 2가지의 방식이 있습니다.
그래서 정리하자면 아래와 같은 순서로 기술이 발전된 것을 확인할 수 있습니다.
직접 서블릿 등록 → Front Controller 패턴 사용 → DispatcherServlet
이번 포스팅에서는 직접 서블릿을 등록하는 방식, Front Controller 패턴을 사용하는 방식의 특징과 단점들에 대해 정리해 보겠습니다.
직접 서블릿 등록
@WebServlet("/hello") <-- 요청 받을 url 작성
public class HelloServlet extends HttpServlet {
public void init(ServletConfig config) throws ServletException {
System.out.println("init() 실행");
}
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
System.out.println("service() 실행");
// do business login
}
}
서블릿을 직접 등록하는 방법은 위와 같이 @WebServlet + HttpServlet
을 사용하는 방식이 있고
토비님이 강의에서 사용하신 방법이 있습니다. (❗자세한 내용은 강의 참고❗)
이 방식을 사용했을 때의 단점은 서블릿의 단위가 Class이기 때문에 새로운 요청(url)을 추가할 때마다 매번 서블릿을 추가해야 합니다.
따라서 각 요청(url) 별로 서블릿이 존재하기 때문에 관리해야 할 서블릿이 너무 많아지게 됩니다.
그리고 서블릿 또한 Class로 작성돼야 하기 때문에 naming에도 신경 써야 하는 단점이 있습니다.
마지막으로 같은 카테고리, 범주에 속한 요청(url)들이더라도 Class naming에 따라 다른 곳에 위치할 수 있기 때문에 관리도 매우 불편해집니다.
그래서 선배 개발자들은 이러한 단점들을 해결하기 위해 아래와 같은 고민을 하게 됩니다.
- 단순히 요청에 따라 비즈니스 로직(Java Code)을 처리하는 경우가 많은데 이런 경우 굳이 서블릿일 필요가 있을까?
- 같은 카테고리, 범주에 속한 요청들을 상위로 묶어서 관리할 수는 없을까?
위 고민들 끝에 나온 방법이 바로 Front Controller 패턴을 사용한 방식입니다.
Front Controller 패턴 사용
Front Controller는 말 그대로 앞에서 요청을 전부 처리할 수 있는 Servlet
을 하나 만들고 Servlet
에서 각 요청에 맞는 로직을 처리하도록 위임을 하는 방식입니다.
이렇게 되면 먼저 첫 번째 고민인 비즈니스 로직만 처리하는데 굳이 서블릿일 필요가 있을까? 가 해결됩니다.
Servlet
은 오로지 FrontController 하나만 존재하며, 나머지는 모두 Java class이기 때문입니다.
그리고 두 번째 고민인 같은 카테고리, 범주에 속한 요청들을 하나의 묶음으로 관리할 수 있게 됩니다.
Front Controller는 여러 개 존재할 수 있습니다.
이를 이용해 같은 카테고리, 범주에 속한 요청들을 각각의 Front Controller로 생성하여 묶을 수 있습니다.
예를 들어
게시판의 경우 BoardFrontController
댓글의 경우 ReplyFrontController
주문의 경우 OrderFrontController...
이렇게 되면 개발자 입장에서 비슷한 요청들이 한 곳에 모여있기 때문에 관리도 수월해질뿐더러 불필요한 서블릿이 등록되는 것을 방지할 수 있게 됩니다.
그리고 이 방식을 사용했을 때 추가로 얻는 장점은 Servlet 영역(프레젠테이션 영역)과 Java Code 영역(비즈니스 영역)이 분리되어 Spring의 레이어드 아키텍처의 구조를 비슷하게나마 따라 할 수 있게 됩니다.
하지만 Front Controller 패턴도 단점이 존재합니다.
- FrontController에서 요청을 분기처리하는 로직이 하드 코딩으로 작성되어야 합니다.
- 하나의 FrontController에서 처리할 요청이 많아질 경우 분기문이 길어져 가독성이 떨어집니다.
위와 같이 먼저 요청 url을 분석한 후 switch문
이나 if-else문
을 사용해 요청에 맞는 Controller
를 찾아 요청을 위임해야 합니다.
이렇게 요청에 해당하는 Controller
를 일일이 하드코딩으로 작성해 놔야 하기 때문에, 오타의 위험도 있을뿐더러 실수로 Controller
는 만들었으나 요청 분기문에 추가를 하지 않는 경우도 발생할 수 있습니다.
그래서 Spring에서는 Front Controller 패턴 + Spring 기술을 이용해 DispatcherServlet
을 만들었는데, 이 부분은 다음 챕터에서 정리해 보겠습니다.
하드 코딩보다는 Enum 사용
어떤 변수의 값이나 property의 key 값의 경우 단순히 리터럴 값으로 하드 코딩 하는 경우가 있습니다.
위 코드는 토비님 강의 코드를 일부 발췌한 것인데, 숙련된 개발자라면 메서드 이름만 보고서도 매개변수의 값들이 어떤 의미를 가지는지 쉽게 파악할 수 있을 것입니다.
하지만 그렇지 않은 경우 각각의 값들 200, Content-Type, text/plain이 어떤 의미를 가지는지 파악하기 쉽지 않습니다.
또한 여기서도 개발자의 오타가 발생할 수 있기 때문에 이런 경우에는 직접 값들을 하드 코딩하는 것보다는 Enum
을 사용하는 것이 훨씬 좋습니다.
HttpStatus
, HttpHeaders
, MediaType
등과 같은 Enum
은 친절하게 Spring에서 이미 제공하는 Enum들이며 우리가 사용하고자 했던 값들이 전부 Enum으로 정리되어 있습니다.
200 → HttpStatus.OK.value()
Content-Type → HttpHeaders.CONTENT_TYPE
text/plain → MediaType.TEXT_PLAIN_VALUE
이런 점을 기억하여 개발시 값들을 하드코딩하는 것이 아니라 직접 Custom Enum
을 작성하여 관리하는 습관을 들이는 것이 좋습니다.
번외
Spring없이 직접 DispatcherServlet
을 구현해 본 코드를 공유드립니다.
다음 챕터인 독립 실행형 스프링 애플리케이션에서 DispatcherServlet
을 사용해 서블릿 컨테이너를 구성하는데
사실 DispatcherServlet
을 잘 몰라도 학습하는데 큰 어려움은 없으나, DispatcherServlet
의 동작 방식이나 내부 구현이 궁금하신 분들이 있다면 참고하시면 좋을 것 같습니다.
Spring의 DispatcherServlet
을 완벽하게 구현하지는 못하고 간략하게 구현했기 때문에 DispatcherServlet
을 모르시는 분들은 대충 이런 느낌으로 만들어졌구나라는 느낌으로, 이미 DispatcherServlet
을 아는 분들은 복습의 느낌으로 보시면 좋을 것 같습니다.
'Lecture > 토비의 스프링 부트 - 이해와 원리' 카테고리의 다른 글
토비의 스프링 부트 - 자동 구성 기반 애플리케이션 (0) | 2023.02.12 |
---|---|
토비의 스프링 부트 - DI와 테스트, 디자인 패턴 (0) | 2023.02.08 |
토비의 스프링 부트 - 독립 실행형 스프링 애플리케이션 (1) | 2023.02.05 |
토비의 스프링 부트 - 스프링 부트 살펴보기 ~ 스프링 부트 시작하기 (0) | 2023.01.31 |
토비의 스프링 부트 - 시작하기 (0) | 2023.01.30 |
댓글