본문 바로가기
Spring/스프링 MVC

[스프링 MVC 1편] 4 - (5) 프론트 컨트롤러 - v5

by Poorm 푸름 2023. 11. 13.

 *  스프링 입문 = window, 스프링 MVC 1편 = Mac 으로 진행합니다

 *  진도 : 섹션4 - (6) ~ (7)

 *          : 자바 클래스명,         : 코드,         : 단축키

 

1. 프론트 컨트롤러_구현 5단계 (V3 지원)

 

  • Controller를 v1 ~ v4 까지 만들어보았는데 컨트롤러를 섞어서 다양하게 써보자

    지금까지 우리가 개발한 프론트 컨트롤러는 한가지 방식의 컨트롤러 인터페이스만 사용할 수 있다
    예로 ControllerV3 , ControllerV4 는 다른 인터페이스라 호환이 불가능하다 

    어댑터 패턴을 사용해서 프론트 컨트롤러가 다양한 방식의 컨트롤러를 처리하자

     


  • 어댑터 패턴

    서로 다른 인터페이스를 사용할 수 있도록 바꿔줌으로써 기존 코드를 재사용


  • 핸들러란

    이벤트가 발생했을 때, 해당 이벤트에 맞는 동작을 수행하는자 라고 생각하면 된다.

    즉, 해당 URI에 맞는 동작을 수행하는 자 = 컨트롤러 라고 생각하면된다. 컨트롤러의 상위 개념이 핸들러이다
  • 핸들러 어댑터
    핸들러 매핑에서 리턴받은 핸들러 객체를 가지고 이에 맞는 어댑터를 찾는 과정
    핸들러 어댑터는 컨트롤러에서 String으로 응답받든, Model로 응답받든, 무조건 Dispatcher Servlet에서 ModelAndView객체로 응답을 해줘야한다 

 

1) 어댑터용 인터페이스
 [ src - java - hello.servlet - web - frontcontroller .v5 - MyHandlerAdapter ]

public interface MyHandlerAdapter {
    boolean supports(Object handler);
    ModelView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws SecurityException, IOException;
}

 

 

boolean supports (Object handler)

  • 어댑터가 해당 컨트롤러를 처리할 수 있는지 판단하는 메서드
  • object는 객체 생성 중의 가장 상위 개념(모든 것 포함가능)

 

ModelView handle

  • 어댑터는 실제 컨트롤러를 호출, 그 결과로 ModelView를 반환
    (반환하지 못하면 어댑터가 ModelView를 직접 생성해서라도 반환)

  • 어댑터를 통해서 실제 컨트롤러 호출 (이전에는 프론트 컨트롤러가 컨트롤러를 호출)

더보기

< 기존의 ControllerV3 인터페이스 코드 >

 

public interface ControllerV3 {
    ModelView process(Map<String, String> paramMap);
}

 

< 기존의 ControllerV4 인터페이스 코드 >

 

public interface ControllerV4 {
    String process(Map<String, String> paramMap,Map<String, Object> model);
}

 

 2) V3 지원하는 어댑터 
 [ src - java - hello .servlet - web - frontcontroller .v5 - adapter - ControllerV3HandlerAdapter ]

public class ControllerV3HandlerAdapter implements MyHandlerAdapter {
    @Override
    public boolean supports(Object handler) {
        return (handler instanceof ControllerV3);
    }

    @Override
    public ModelView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws SecurityException, IOException {
        ControllerV3 controller = (ControllerV3) handler;
        Map<String, String> paramMap = createParamMap(request);
        ModelView mv = controller.process(paramMap);
        return mv;
    }

    private static Map<String, String> createParamMap(HttpServletRequest request) {
        Map<String, String> paramMap = new HashMap<>();
        request.getParameterNames().asIterator()
                .forEachRemaining(paramName -> paramMap.put(paramName, request.getParameter(paramName)));
        return paramMap;
    }
}

 

  • 상속 implements MyHandlerAdapter (option + enter)

    • boolean supports / ModelView handle 2개가 구현된다

  • 핸들러 참 or 거짓 boolean supports~return(handler instanceof ControllerV3)

    • ControllerV3가 넘어오면 참을 반환

  • 핸들러 처리 ModelView handle~(handler instanceof ControllerV3)

    • ControllerV3 controller = ~ handler

      handler를 컨트롤러 V3로 변환한다

    • 파라미터네임 꺼내기 (그냥 FrontControllerV3 복사해도 된다)
      • parammap 맵 생성 
      • request.getParameterNames() ~ 파라미터 다 꺼내기 : iterator 인터페이스형으로 바꿔서 반환
      • key = paramName, value = request.getParameter(paramName)

         너무 길어서 따로 메서드로 뽑는게 좋다!
        paramMap부터 request.getParameterName 까지 드래그 후
        option + command + m하고 parammapcreateParamMap 입력하기 

  •  모델뷰 반환 controller.process(paramMap) (option + command + v



 3) 프론트 컨트롤러 
[ src - java - hello.servlet - web - frontcontroller. v5 - FrontControllerServletV5 ]

@WebServlet(name = "frontControllerServletV5", urlPatterns = "/front-controller/v5/*")
public class FrontControllerServletV5 extends HttpServlet {
    private final Map<String, Object> handlerMappingMap = new HashMap<>();
    private final List<MyHandlerAdapter> handlerAdapters = new ArrayList<>();

    public FrontControllerServletV5() {
        initHandlerMappingMap();

        initHandlerAdapters();
    }

    private void initHandlerMappingMap() {
        handlerMappingMap.put("/front-controller/v5/v3/members/new-form", new MemberFormControllerV3());
        handlerMappingMap.put("/front-controller/v5/v3/members/save", new MemberSaveControllerV3());
        handlerMappingMap.put("/front-controller/v5/v3/members", new MemberListControllerV3());
    }

    private void initHandlerAdapters() {
        handlerAdapters.add(new ControllerV3HandlerAdapter());
    }

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Object handler = getHandler(request);
        if(handler==null){
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
        }
        MyHandlerAdapter adapter = getHandlerAdapter(handler);
        ModelView mv = adapter.handle(request, response, handler);


        String viewName = mv.getViewName();
        MyView view = viewResolver(viewName);

        view.render(mv.getModel(), request, response);
    }

    private MyHandlerAdapter getHandlerAdapter(Object handler) {
        for (MyHandlerAdapter adapter : handlerAdapters) {
            if (adapter.supports(handler)){
               return adapter;
            }
        }
        throw new IllegalArgumentException("adapter 를 찾을 수 없습니다. handler=" +handler);

    }
    private static MyView viewResolver(String viewName) {
        return new MyView("/WEB-INF/views/" + viewName + ".jsp");
    }

    private Object getHandler(HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        return handlerMappingMap.get(requestURI);
    }
}

 

  • 프론트 컨트롤러는 꼭 서블릿으로 작성한다!

1. 상속 extends HttpServlet

 

2. 서블릿 생성@WebServlet

 

3. 핸들러 매핑 맵 생성 private final Map <Stirng,Object>

 

  • key = url, value = Object (어떠한 컨트롤러도 들어갈 수 있음)

4. 리스트 만들기  List<MyHandlerAdapter> ~ new ArrayList<>()

  • 어댑터가 여러개 담겨 있기 때문에 만들어줌

5. 매핑 정보 public FrontControllerServiceV5()

  • command + n 하고 constructor 클릭 → Select None 클릭
  • 매핑정보를 담기!
  • key 값이 요청되면 value를 실행하게끔 설정

     너무 길어서 따로 메서드로 뽑는게 좋다!
            경로 드래그 후 option + command + m하고 initHandlerMappingMap 입력하기 

6. 리스트에 어댑터 클래스 넣기 handlerAdapters.add()

 

  • 얘도 메서드로 따로 뽑기!
            드래그 후 option + command + m하고 initHandlerAdapters 입력하기 

 

7. 서비스 생성 protected service

 

 

8. URI

 

  • 주소 가져오 request.getRequestURI (option + command + v)
  • 에서 URI 찾아 컨트롤러 반환 handlerMappingMap.get(requestURI)(option + command + v)
  • 두 줄 드래그하고 option + command + m 해서 getHandler메서드로 따로 뽑기!

  • 새로 생긴 메서드에서 반환 타입 변경
    • private void getHandler private Object getHandler 변경
    • Object Handler = handlerMappingMap.get() → return handlerMappingMap.get() 변경

 

  1. 예외처리는 404 출력 SC_NOT_FOUND

 

9. 어댑터 for문 작성 handlerAdapters.iter (enter)

 

  • 드래그, option + command + m 해서 getHandlerAdapter메서드로 따로 뽑기!
  • MyHandlerAdapter adapter = getHandlerAdapter 로 변경
    이때 MyHandlerAdapter는 앞서 만든 인터페이스다

  • 새로 생긴 메서드에서 반환 타입 변경
    • private void private MyHandlerAdapter 변경
    • a = adapter → return adapter 변경

  • 새로 생긴 메서드에 예외 코드 추가
    • throw new IllegalArgumentException ~

10. 모델 뷰 반환 ModelView mv = adpater handle ~

 

 11. 뷰 설정 (프론트컨트롤러v3 랑 같음)

  • new MyView("/WEB-INF/views/" + viewName + ".jsp") (option + command + v) 하고
     option + command + m
     해서 viewResolver(viewName) 입력하기 
    •  컨트롤러가 반환한 논리 뷰 이름을 실제 물리 뷰 경로로 변경, 실제 물리 경로가 있는 MyView 객체를 반환 논리 뷰 이름: members
      물리 뷰 경로: /WEB-INF/views/members.jsp

  • 렌더 호출 view.render(model, request, respontse)

더보기

< 기존의 FrontControllerService4 클래스에서 수정한 코드 >

 

  • 3번 과정 Map 형식이 ControllerV4 에서 Object로 바뀜
  • 5번 과정 경로 /v5/v3 으로 변경
  • 8번 과정 controllerMap에서 가져오던거 이제는 handlerMappingMap에서 가져오고 Object로 변경
  • Map paramMap / model 2개 다 삭제
  • String ViewName ~ 삭제
  • createParamMap 메서드 삭제
@WebServlet(name = "frontControllerServiceV4", urlPatterns = "/front-controller/v4/*")
public class FrontControllerServiceV4 extends HttpServlet {

    private Map<String, ControllerV4> controllerMap = new HashMap<>();

    public FrontControllerServiceV4() {
        controllerMap.put("/front-controller/v4/members/new-form", new MemberFormControllerV4());
        controllerMap.put("/front-controller/v4/members/save", new MemberSaveControllerV4());
        controllerMap.put("/front-controller/v4/members", new MemberListControllerV4());
    }

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        String requestURI = request.getRequestURI();
        ControllerV4 controller = controllerMap.get(requestURI);
        if(controller==null){
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
        }

        Map<String, String> paramMap = createParamMap(request);
        Map<String, Object> model = new HashMap<>();
        String viewName = controller.process(paramMap, model);

        MyView view = viewResolver(viewName);
        view.render(model, request, response);
    }

    private static MyView viewResolver(String viewName) {
        return new MyView("/WEB-INF/views/" + viewName + ".jsp");
    }

    private static Map<String, String> createParamMap(HttpServletRequest request) {
        Map<String, String> paramMap = new HashMap<>();
        request.getParameterNames().asIterator()
                .forEachRemaining(paramName -> paramMap.put(paramName, request.getParameter(paramName)));
        return paramMap;
    }
}

 

 

< 실행 과정 >

 

1. 클라이언트 요청이 오면 프론트 컨트롤러가 핸들러 매핑 정보 뒤지기 (5번 과정)

2. 찾아와서 핸들러를 처리할 수 있는 핸들러 어댑터 찾기 (9번 과정)

3. 핸들 어댑터(=ControllerV3HandlerAdapter)를 호출 (9번 과정)

4. 핸들 호출 (ControllerV3HandlerAdapter 클래스 실행)

5. 모델뷰 반환 (10번 과정)

6. viewResolver 호출 (11번 과정)

7. MyView 반환 (11번 과정)

8. 렌더링 (11번 과정)

 

 

2. 프론트 컨트롤러_구현 5단계 (V4 지원)

 

 1) V4 지원하는 어댑터 
 [ src - java - hello .servlet - web - frontcontroller .v5 - adapter - ControllerV3HandlerAdapter ]

public class ControllerV4HandlerAdapter implements MyHandlerAdapter {
    @Override
    public boolean supports(Object handler) {
        return(handler instanceof ControllerV4);
    }

    @Override
    public ModelView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws SecurityException, IOException {
        ControllerV4 controller = (ControllerV4) handler;
        Map<String, String> paramMap = createParamMap(request);
        HashMap<String, Object> model = new HashMap<>();
        String viewName = controller.process(paramMap, model);

        ModelView mv = new ModelView(viewName);
        mv.setModel(model);

        return mv;
    }
    private static Map<String, String> createParamMap(HttpServletRequest request) {
        Map<String, String> paramMap = new HashMap<>();
        request.getParameterNames().asIterator()
                .forEachRemaining(paramName -> paramMap.put(paramName, request.getParameter(paramName)));
        return paramMap;
    }
}

 

  • 상속 implements MyHandlerAdapter (option + enter)

    • boolean supports / ModelView handle 2개가 구현된다

  • 핸들러 참 or 거짓 boolean supports~return(handler instanceof ControllerV4) 

    • ControllerV4가 넘어오면 참을 반환

  • 핸들러 처리 ModelView handle~(handler instanceof ControllerV4)

    • ControllerV4 controller = ~ handler

      handler를 컨트롤러 V3로 변환한다

          
    • 파라미터네임 꺼내기 (그냥 FrontControllerV4 복사해도 된다)

      • parammap 맵 생성 
      • request.getParameterNames() ~ 파라미터 다 꺼내기 : iterator 인터페이스형으로 바꿔서 반환
      • key = paramName, value = request.getParameter(paramName)

         너무 길어서 따로 메서드로 뽑는게 좋다!
        paramMap부터 request.getParameterName 까지 드래그 후
        option + command + m하고 parammapcreateParamMap 입력하기 

  •  인터페이스, 회원 등록/저장/목록 컨트롤러에서 사용한 맵 2개 등록

    • Map<String, String> paraMap = new HashMap<>()

    • HashMap<String, Object> model = new HashMap<>()

  •  파라미터 받기  controller.process(paramMap) (option + command + v)

  • 모델 뷰 생성 new ModelView(viewName) (option + command + v)

더보기

< 기존의 ControllerV3HandlerAdapter 클래스 코드 >

 

public class ControllerV3HandlerAdapter implements MyHandlerAdapter {
    @Override
    public boolean supports(Object handler) {
        return (handler instanceof ControllerV3);
    }

    @Override
    public ModelView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws SecurityException, IOException {
        ControllerV3 controller = (ControllerV3) handler;
        Map<String, String> paramMap = createParamMap(request);
        ModelView mv = controller.process(paramMap);
        return mv;
    }

    private static Map<String, String> createParamMap(HttpServletRequest request) {
        Map<String, String> paramMap = new HashMap<>();
        request.getParameterNames().asIterator()
                .forEachRemaining(paramName -> paramMap.put(paramName, request.getParameter(paramName)));
        return paramMap;
    }
}

 

 2) 프론트 컨트롤러 
[ src - java - hello.servlet - web - frontcontroller. v5 - FrontControllerServletV5 ]

@WebServlet(name = "frontControllerServletV5", urlPatterns = "/front-controller/v5/*")
public class FrontControllerServletV5 extends HttpServlet {
    private final Map<String, Object> handlerMappingMap = new HashMap<>();
    private final List<MyHandlerAdapter> handlerAdapters = new ArrayList<>();

    public FrontControllerServletV5() {
        initHandlerMappingMap();

        initHandlerAdapters();
    }

    private void initHandlerMappingMap() {
        handlerMappingMap.put("/front-controller/v5/v3/members/new-form", new MemberFormControllerV3());
        handlerMappingMap.put("/front-controller/v5/v3/members/save", new MemberSaveControllerV3());
        handlerMappingMap.put("/front-controller/v5/v3/members", new MemberListControllerV3());

        //V4 추가
        handlerMappingMap.put("/front-controller/v5/v4/members/new-form", new MemberFormControllerV4());
        handlerMappingMap.put("/front-controller/v5/v4/members/save", new MemberSaveControllerV4());
        handlerMappingMap.put("/front-controller/v5/v4/members", new MemberListControllerV4());
    }

    //처리할 어댑터
    private void initHandlerAdapters() {
        handlerAdapters.add(new ControllerV3HandlerAdapter());
        handlerAdapters.add(new ControllerV4HandlerAdapter());
    }

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Object handler = getHandler(request);
        if(handler==null){
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
        }
        MyHandlerAdapter adapter = getHandlerAdapter(handler);
        ModelView mv = adapter.handle(request, response, handler);


        String viewName = mv.getViewName();
        MyView view = viewResolver(viewName);

        view.render(mv.getModel(), request, response);
    }

    private MyHandlerAdapter getHandlerAdapter(Object handler) {
        for (MyHandlerAdapter adapter : handlerAdapters) {
            if (adapter.supports(handler)){
               return adapter;
            }
        }
        throw new IllegalArgumentException("adapter 를 찾을 수 없습니다. handler=" +handler);

    }
    private static MyView viewResolver(String viewName) {
        return new MyView("/WEB-INF/views/" + viewName + ".jsp");
    }

    private Object getHandler(HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        return handlerMappingMap.get(requestURI);
    }
}
  • 프론트 컨트롤러는 꼭 서블릿으로 작성한다!

1. 상속 extends HttpServlet

 

2. 서블릿 생성@WebServlet

 

3. 핸들러 매핑 맵 생성 private final Map <Stirng,Object>

 

  • key = url, value = Object (어떠한 컨트롤러도 들어갈 수 있음)

4. 리스트 만들기  List<MyHandlerAdapter> ~ new ArrayList<>()

  • 어댑터가 여러개 담겨 있기 때문에 만들어줌

5. 매핑 정보 public FrontControllerServiceV5()

  • command + n 하고 constructor 클릭 → Select None 클릭
  • 매핑정보를 담기!
  • key 값이 요청되면 value를 실행하게끔 설정

     너무 길어서 따로 메서드로 뽑는게 좋다!
            경로 드래그 후 option + command + m하고 initHandlerMappingMap 입력하기 

6. 리스트에 어댑터 클래스 넣기 handlerAdapters.add()

 

  •  얘도 메서드로 따로 뽑기!
            드래그 후 option + command + m하고 initHandlerAdapters 입력하기 

 

7. 서비스 생성 protected service

 

 

8. URI

 

  • 주소 가져오 request.getRequestURI (option + command + v)
  • 에서 URI 찾아 컨트롤러 반환 handlerMappingMap.get(requestURI)(option + command + v)
  • 두 줄 드래그하고 option + command + m 해서 getHandler 메서드로 따로 뽑기!

  • 새로 생긴 메서드에서 반환 타입 변경
    • private void getHandler private Object getHandler 변경
    • Object Handler = handlerMappingMap.get() → return handlerMappingMap.get() 변경

 

  1. 예외처리는 404 출력 SC_NOT_FOUND

 

9. 어댑터 for문 작성 handlerAdapters.iter (enter)

 

  • 드래그, option + command + m 해서 getHandlerAdapter 메서드로 따로 뽑기!
  • MyHandlerAdapter adapter = getHandlerAdapter 로 변경
    이때 MyHandlerAdapter는 앞서 만든 인터페이스다

  • 새로 생긴 메서드에서 반환 타입 변경
    • private void private MyHandlerAdapter 변경
    • a = adapter → return adapter 변경

  • 새로 생긴 메서드에 예외 코드 추가
    • throw new IllegalArgumentException ~

10. 모델 뷰 반환 ModelView mv = adpater handle ~

 

11. 뷰 설정 (프론트컨트롤러v3 랑 같음)

  • new MyView("/WEB-INF/views/" + viewName + ".jsp") (option + command + v) 하고
     option + command + m
     해서 viewResolver(viewName) 입력하기 
    •  컨트롤러가 반환한 논리 뷰 이름을 실제 물리 뷰 경로로 변경, 실제 물리 경로가 있는 MyView 객체를 반환 논리 뷰 이름: members
      물리 뷰 경로: /WEB-INF/views/members.jsp

  • 렌더 호출 view.render(model, request, respontse)

더보기

< 기존의 FrontControllerService5(V3버전) 클래스 코드 >

 

@WebServlet(name = "frontControllerServletV5", urlPatterns = "/front-controller/v5/*")
public class FrontControllerServletV5 extends HttpServlet {
    private final Map<String, Object> handlerMappingMap = new HashMap<>();
    private final List<MyHandlerAdapter> handlerAdapters = new ArrayList<>();

    public FrontControllerServletV5() {
        initHandlerMappingMap();

        initHandlerAdapters();
    }

    private void initHandlerMappingMap() {
        handlerMappingMap.put("/front-controller/v5/v3/members/new-form", new MemberFormControllerV3());
        handlerMappingMap.put("/front-controller/v5/v3/members/save", new MemberSaveControllerV3());
        handlerMappingMap.put("/front-controller/v5/v3/members", new MemberListControllerV3());
    }

    private void initHandlerAdapters() {
        handlerAdapters.add(new ControllerV3HandlerAdapter());
    }

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Object handler = getHandler(request);
        if(handler==null){
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
        }
        MyHandlerAdapter adapter = getHandlerAdapter(handler);
        ModelView mv = adapter.handle(request, response, handler);


        String viewName = mv.getViewName();
        MyView view = viewResolver(viewName);

        view.render(mv.getModel(), request, response);
    }

    private MyHandlerAdapter getHandlerAdapter(Object handler) {
        for (MyHandlerAdapter adapter : handlerAdapters) {
            if (adapter.supports(handler)){
               return adapter;
            }
        }
        throw new IllegalArgumentException("adapter 를 찾을 수 없습니다. handler=" +handler);

    }
    private static MyView viewResolver(String viewName) {
        return new MyView("/WEB-INF/views/" + viewName + ".jsp");
    }

    private Object getHandler(HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        return handlerMappingMap.get(requestURI);
    }
}

 

 

< V4버전 실행 과정 >

 

 

1. 클라이언트 요청: http://localhost:8080/front-controller/v5/v4/members/new-form

 

2. [FrontControllerServletV5] - initHandleMappingMap  (5번 과정)
     매핑정보 찾아서 MemberFormControllerV4 반환

 

3. [FrontControllerServletV5] - MyHandlerAdapter adater = getHandlerAdapter(handler) (9번 과정)

     MemberFormControllerV4핸들러를 처리할 수 있는 핸들러 어댑터 찾기 

4. [FrontControllerServletV5] - initHandlerAdapters (6번 과정)

     핸들러 어댑터 목록보기
     list에는 ControllerV3HandlerAdapter, ControllerV4HandlerAdapter 가 들어가 있다

 

5. [FrontControllerServletV5] - MyHandlerAdapter adater - adapter.supports (9번 과정)

     [ControllerV3HandlerAdapter/ControllerV4HandlerAdapter] - public boolean supports 

     어댑터들의 boolean supports 메서드 호출하고 해당하는 어댑터를 반환

  • ControllerV3HandlerAdapter에서는 instanceof ControllerV3이라 false
  • ControllerV4HandlerAdapter에서는 instanceof ControllerV4라 반환 ok

6. [FrontControllerServletV5] - ModelView mv = adapter.handle (10번 과정)

     [ControllerV4HandlerAdapter] - public ModelView handle 

     해당 어댑터의 핸들 메서드 호출

 

7.  [ControllerV4HandlerAdapter] - public ModelView handle

      ControllerV4로 캐스팅하고 이에 맞춰서 paramMap, model 맵 2개를 넘겨 viewName 반환

      viewName를 이용해 ModelView mv를 만들고 모델뷰 반환한다 

 

8. [FrontControllerServletV5] viewResolver 호출 (11번 과정)

 

9. [FrontControllerServletV5] MyView 반환 (11번 과정)

 

10. [FrontControllerServletV5] 렌더링 (11번 과정)

 

 

 

 

 

 

 

 

[출처] 김영한 강사님 인프런 스프링 mvc1

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1/dashboard 

 

스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 - 인프런 | 강의

웹 애플리케이션을 개발할 때 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. 스프링 MVC의 핵심 원리와 구조를 이해하고, 더 깊이있는 백엔드 개발자로 성장할 수 있습니다., 원

www.inflearn.com