Spring 입문 (Front Controller Pattern, Adapter Pattern, DispatcherServlet)

KimGwangmin·2026년 9월 6일

Front Controller Pattern

  • 모든 요청이 단 하나의 진입점을 가짐
  • 모든 요청에 적용될 공통 로직의 중앙화
    • 공통 로직: 인증, 로깅, 인코딩 등
    • 중앙화된 컨트롤러가 있으니 새로운 기능 추가 시에도 자동 적용
  • 요청에 따라 적절한 세부 컨트롤러로 위임 (공통 로직을 제외한 추가적인 처리)
  • 일관된 처리 흐름, 유지보수성 향상
전통적인 방식의 경우

  • 각 서블릿마다 공통 로직 중복
  • 새 기능 추가 시 모든 서블릿 수정 필요
  • 유지보수성 낮음 (일관성 유지가 어려움)

Adapter Pattern

  • 서로 다른 인터페이스를 가진 클래스들을 연결해주는 패턴
  • 다형성을 구현해주는 디자인패턴

Spring의 다양한 컨트롤러 형태

// 1. @Controller 어노테이션 방식
@Controller
public class HelloController {
    @RequestMapping("/hello")
    public String hello() {
        return "hello";
    }
}

// 2. Controller 인터페이스 방식  
public class OldController implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, 
                                    HttpServletResponse response) {
        return new ModelAndView("hello");
    }
}

// 3. HttpRequestHandler 인터페이스 방식
public class SimpleController implements HttpRequestHandler {
    @Override
    public void handleRequest(HttpServletRequest request, 
                            HttpServletResponse response) {
        // 처리 로직
    }
}

어댑터 패턴을 적용

여러 타입의 컨트롤러를 하나의 인터페이스로 처리 가능
// HandlerAdapter 인터페이스 (공통 인터페이스)
public interface HandlerAdapter {
    boolean supports(Object handler); // 처리 가능 여부 판단(boolean)
    
    ModelAndView handle( // 어떻게 처리할 것인지에 대한 로직
      HttpServletRequest request,
      HttpServletResponse response, 
      Object handler) throws Exception;
}

// Controller 구현 1 (HandlerAdapter를 implements)
public class RequestMappingHandlerAdapter implements HandlerAdapter {
    @Override
    public boolean supports(Object handler) {
        return handler instanceof HandlerMethod;  // @RequestMapping 메서드인지 확인
    }
    
    @Override
    public ModelAndView handle(HttpServletRequest request, 
                             HttpServletResponse response, 
                             Object handler) {
        // @Controller 방식으로 처리
        return invokeHandlerMethod((HandlerMethod) handler, request, response);
    }
}

// Controller 구현 2 (HandlerAdapter를 implements)
public class SimpleControllerHandlerAdapter implements HandlerAdapter {
    @Override
    public boolean supports(Object handler) {
        return handler instanceof Controller;
    }
    
    @Override
    public ModelAndView handle(HttpServletRequest request, 
                             HttpServletResponse response, 
                             Object handler) {
        // Controller 인터페이스 방식으로 처리
        return ((Controller) handler).handleRequest(request, response);
    }
}

DispatcherServlet

스프링 MVC의 프론트 컨트롤러

1. 요청

  • 클라이언트가 서버로 요청 전송
  • 프론트 컨트롤러인 DispatcherServlet에 도달

2. 핸들러 조회

  • 주체: DispatcherServlet
  • HandlerMapping에게 요청을 처리할 핸들러(Controller)를 조회

3. 핸들러 실행

  • 주체: DispatcherServlet
  • HandlerMapping의 반환 정보를 토대로 해당 Controller에게 요청 처리 위임
  • 이때 컨트롤러를 직접 호출하지 않고, 요청을 실행할 수 있는 HandlerAdapter를 탐색하여 요청을 위임
  • HandlerAdapter가 앞서 논의한 어댑터 패턴: 다양한 컨트롤러를 HandlerAdater라는 단일 인터페이스로 처리 가능

4. ModelAndView 반환

  • 주체: 요청을 위임받은 Controller
  • 컨트롤러가 비즈니스 로직을 수행한 후, 처리한 데이터(Model)와 보여줄 화면(View) 이름을 담은 ModelAndView 객체를 DispatcherServlet에게 반환

5. View 해석

  • 주체: DispatcherServlet
  • ModelAndView 객체로부터 뷰의 논리적 이름을 추출하여 ViewResolver에게 전달, 실제 View 객체를 조회

6. View 렌더링

  • 주체: DispatcherServlet
  • ViewResolver에게서 받은 View 객체에게 Model을 전달하여 View 렌더링 요청

7. 응답

  • 주체: DispatcherServlet
  • 렌더링된 View 결과물이 클라이언트에게 최종 응답으로 전달

위의 절차는 SSR에서의 표준 흐름이며, CSR에서는 4번 이후의 흐름이 달라진다.
객체(Data)를 바로 반환하고, JSON 문자열로 변환한 뒤, 클라이언트에게 데이터만 바로 응답한다.
현대 스프링 MVC는 주로 4-6 과정은 사장되었으며, JSON 데이터만 반환하는 것이 일반적이다.

0개의 댓글