DispatcherServlet?(공식문서 들어가기전 알고가기)

박지성 학부생·2024년 2월 21일
0

BackEnd Develop log

목록 보기
20/27
post-thumbnail

안까먹게 어원쪼개기

디스패처(Dispatcher)

  • 디스패처는 '분배자' or '배치자'
  • 어원 ⇒ 라틴어 'dis' (분리, 떨어진)와 'pachere' (보내다)의 조합으로, 디스패처는 요청, 작업, 정보 등을 적절한 대상이나 장소로 보내는 역할을 함
  • Spring MVC에서 디스패처는 HTTP 요청을 받아 이를 처리할 적절한 컨트롤러로 전달

서블릿(Servlet)

  • "Servlet" ⇒ '서비스'를 의미하는 'service'와 작은 것을 의미하는 접미사 '-let'의 결합, 서비스를 제공하는 작은 프로그램이라는 의미
  • 웹 서버와 통신하여 웹 페이지의 동적인 콘텐츠를 생성, 클라이언트에게 HTML, JSON 등의 형태로 응답을 전송하는 역할

DispatcherServlet:

  • Spring MVC의 핵심 컴포넌트
  • 모든 HTTP 요청을 받아 적절한 컨트롤러에 배분하는 중앙 집중식 컨트롤러

아직 뭔지 잘 모르겠음

그래서 DispatcherServlet이 존재하기전에는 어떤 어려움이 있었고 DispatcherServlet이 어떤 이점을 가져다 주었는가?

DispatcherServlet 등장 전

  • 각 HTTP 요청을 처리하기 위해 개발자들은 다수의 서블릿을 만들고 각각을 요청 URL에 직접 매핑해야 함
    • 중복 코드: 여러 서블릿 간에 공통된 로직의 중복이 발생할 수 있음
      • 예시상황 ㄱㄱ
        • 여러 웹 페이지에서 공통적으로 사용자 인증을 확인해야 하는 상황
        • LoginServlet, ProfileServlet, DashboardServlet 등 각각의 서블릿에서 사용자의 로그인 상태를 확인하는 비슷한 코드를 반복해서 작성해야 함
        • 상당히 귀찮고 비효율적. 인증 로직에 변경이 필요할 경우 모든 서블릿을 수정해야 하는 번거로움이 있음
        • 하지만 현재 우리는 config나 인터셉터로 인증&인가에 대한 역할을 따로 분리하여 필요할때 불러 씀
    • 유지 관리의 어려움: 요청 처리 로직이 여러 서블릿에 분산되어 있어, 변경 사항이 있을 때마다 여러 파일을 수정해야 하는 등 유지 관리가 어려움
    • 프로젝트 구조의 복잡성: 각 요청마다 별도의 서블릿을 만들어야 하므로, 프로젝트의 구조가 복잡해지고 관리가 어려움
    • 유연성 부족: 요청 처리 로직을 변경하거나 추가하는 것이 번거롭고, 재사용성이 떨짐
  • “각 HTTP 요청을 처리하기 위해 개발자들은 다수의 서블릿을 만들고 각각을 요청 URL에 직접 매핑” 한다는게 무슨말이지?
    • 예시코드 ㄱㄱ(DispatcherServlet이 도입되기 전, 일반적인 서블릿 기반의 웹 애플리케이션 개발 방식) 사용자 로그인, 사용자 정보 조회, 사용자 정보 업데이트를 해야하는 상황 각 기능을 처리하기 위해, 다음과 같이 세 개의 서블릿을 만들고 각각을 요청 URL에 매핑해야 함
      1. 로그인 서블릿

        • 서블릿 이름: LoginServlet
        • 매핑 URL: /login
      2. 사용자 정보 조회 서블릿

        • 서블릿 이름: UserInfoServlet
        • 매핑 URL: /user/info
      3. 사용자 정보 업데이트 서블릿
        - 서블릿 이름: UserUpdateServlet
        - 매핑 URL: /user/update

        하나: 공포의 web.xml(서블릿 3.0 이후에는 @WebServlet 사용으로 안해도 되긴함.)

        <servlet>
            <servlet-name>LoginServlet</servlet-name>
            <servlet-class>com.example.LoginServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>LoginServlet</servlet-name>
            <url-pattern>/login</url-pattern>
        </servlet-mapping>
        
        <servlet>
            <servlet-name>UserInfoServlet</servlet-name>
            <servlet-class>com.example.UserInfoServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>UserInfoServlet</servlet-name>
            <url-pattern>/user/info</url-pattern>
        </servlet-mapping>
        
        <servlet>
            <servlet-name>UserUpdateServlet</servlet-name>
            <servlet-class>com.example.UserUpdateServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>UserUpdateServlet</servlet-name>
            <url-pattern>/user/update</url-pattern>
        </servlet-mapping>

        둘: 위에서 등록한 서블릿 매핑

        @WebServlet("/login")
        public class LoginServlet extends HttpServlet {
            // 로그인 처리 로직
        }
        
        @WebServlet("/user/info")
        public class UserInfoServlet extends HttpServlet {
            // 사용자 정보 조회 로직
        }
        
        @WebServlet("/user/update")
        public class UserUpdateServlet extends HttpServlet {
            // 사용자 정보 업데이트 로직
        }

        ⇒ 각 기능마다 별도의 서블릿을 생성하고 관리해야함. 현재 컨트롤러딴에서 서비스 역할까지 다 때려박아야하는 일이 빈번..

  • DispatcherServlet의 등장 이후
    • 가장 중요 ⇒ 단일 진입점 설정: 모든 요청은 DispatcherServlet을 통해 처리됨
      • web.xml에 설정되거나, Spring Boot를 사용할 경우 자동으로 설정됨
    • DispatcherServlet은 컨트롤러만을 호출함 사실상 이게 포인트
      • 컨트롤러는 비즈니스 로직을 처리하는 서비스 계층을 호출 ⇒ 결과를 뷰에 전달 ⇒ 비즈니스 로직과 뷰 로직의 분리를 자연스럽게 유도
      • 컨트롤러 정의: 각 요청을 처리할 컨트롤러는 어노테이션을 사용해 매핑. 이 컨트롤러들은 요청을 받아 처리 후, 모델 데이터와 뷰 이름을 반환함
      • 핸들러 매핑: DispatcherServlet은 핸들러 매핑을 통해 들어온 요청 URL을 처리할 컨트롤러를 찾음
      • 뷰 리졸버: 컨트롤러가 반환한 뷰 이름을 기반으로 실제 뷰 템플릿을 찾아 응답을 생성함
    • 위 코드에서 이렇게 변화됨
      @Controller
      public class UserController {
      
          @RequestMapping(value = "/login", method = RequestMethod.GET)
          public String login() {
              // 로그인 페이지 반환
              return "login";
          }
      
          @RequestMapping(value = "/user/info", method = RequestMethod.GET)
          public ModelAndView userInfo() {
              ModelAndView mav = new ModelAndView();
              mav.addObject("userInfo", "사용자 정보");
              mav.setViewName("userInfo");
              return mav;
          }
      
          @RequestMapping(value = "/user/update", method = RequestMethod.POST)
          public String updateUser(@ModelAttribute User user) {
              // 사용자 정보 업데이트 로직
              return "redirect:/user/info";
          }
      }
      • DispatcherServlet 하나가 모든 요청을 받아 적절한 컨트롤러로 라우팅함
      • 컨트롤러는 단순히 요청을 받아 로직을 처리하고 결과를 반환하는 역할만 수행함 ⇒ 이전의 서블릿 방식보다 훨씬 간결하고 명확

결론: DispatcherServlet이 뭐냐고 물어보면 어떻게 대답해야 하는가?

  • DispatcherServlet은 Spring MVC 프레임워크에서 중앙 집중화된 프론트 컨트롤러 역할을 하는 핵심 요소
  • 모든 웹 요청을 받아들이고, 해당 요청을 애플리케이션의 다른 컴포넌트로 라우팅하는 역할
  • 요청에 따라 적절한 컨트롤러를 찾아주고, 컨트롤러가 처리한 결과를 바탕으로 뷰를 선택하여 클라이언트에게 응답을 제공
  • 이 과정에서 인터셉터, 뷰 리졸버 등과 같은 Spring MVC의 컴포넌트와 상호 작용
  • DispatcherServlet의 사용으로 인해 개발자는 요청 처리 과정에서 발생할 수 있는 중복 코드와 복잡성을 줄이고, MVC 패턴을 효율적으로 구현할 수 있게 됨

MVC 본격적으로 알아보기(클릭)!

profile
참 되게 살자

0개의 댓글