Spring/[인프런 김영한 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술]

[인프런 김영한 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술] 스프링 MVC - 구조 이해

h2boom 2024. 10. 4. 15:04

스프링 MVC - 구조 이해

스프링 MVC 전체 구조

 

  • DispatcherServlet : 프론트 컨트롤러 패턴을 구현한 FrontController 역할을 하는 서블릿이다.
    • 스프링 MVC에서의 핵심
    • 스프링 부트에서 서블릿으로 자동 등록하면서 모든 경로("/")에 대해서 매핑한다.
      • 자세한 경로가 우선 순위가 더 높다.
    • 부모에서 service()가 시작되면 DispatcherServlet의 doDispatch()가 호출된다.
      • 핸들러 조회, 핸들러 어댑터 조회, 핸들러 어댑터 실행, 핸들러 실행, ModelAndView 반환의 기능을 수행한다.

 

  • 스프링 MVC 동작 순서
    1. 핸들러 조회 : 핸들러 매핑을 통해 요청 URL에 매핑된 핸들러(컨트롤러)를 조회한다.
    2. 핸들러 어댑터 조회 : 핸들러를 실행할 수 있는 핸들러 어댑터를 조회한다.
    3. 핸들러 어댑터 실행 : 핸들러 어댑터를 실행한다.
    4. 핸들러 실행 : 핸들러 어댑터가 실제 핸들러를 실행한다.
    5. ModelAndView 반환 : 핸들러 어댑터는 핸들러가 반환하는 정보를 ModelAndView로 변환해서 반환한다.
    6. viewResolver 호출 : 뷰 리졸버를 찾고 실행한다.
    7. View 반환 : 뷰 리졸버로 뷰의 논리 이름을 물리 이름으로 바꾸고 렌더링 역할을 하는 뷰 객체를 반환한다.
    8. 뷰 렌더링 : 뷰를 통해서 뷰를 렌더링한다.

핸들러 매핑과 핸들러 어댑터

  • 스프링 부트가 자동 등록하는 핸들러 매핑과 핸들러 어댑터
    • HandlerMapping 우선 순위 (실제로 더 많지만 중요한 것만 다룸)
      • 0순위 RequestMappingHandlerMapping - 어노테이션 기반 컨트롤러인 @RequestMapping에서 사용
      • 1순위 BeanNameUrlHandlerMapping - 스프링 빈 이름으로 핸들러를 찾는다.
        => URL을 보고 먼저 어노테이션 기반으로 찾고 없으면 스프링 빈 이름을 찾는다.
    • HandlerAdapter 우선 순위
      • 0순위 RequestMappingHandlerAdapter - 어노테이션 기반의 컨트롤러인 @RequestMapping에서 사용
      • 1순위 HttpRequestHandlerAdapter - HttpRequestHandler 처리
      • 2순위 SimpleControllerHandlerAdapter - Controller 인터페이스 (과거에 사용) 처리

 

  • 개발자가 직접 핸들러 매핑과 핸들러 어댑터를 만들 일은 없다.
    • 실무에서는 대부분 어노테이션 기반의 컨트롤러를 지원하는 매핑과 어댑터를 사용한다.

뷰 리졸버

  • 스프링 부트에서 InternalResourceViewResolver라는 뷰 리졸버를 자동으로 등록
    • application.yml / .properties에 등록한 spring.mvc.view.prefix / suffix 설정 정보를 기반으로 등록한다.

 

  • 뷰 리졸버 우선 순위
    • 0순위 BeanNameViewResolver - 빈 이름으로 뷰를 찾아서 반환한다.
    • 1순위 InternalResourceViewResolver - JSP를 처리할 수 있는 뷰를 반환한다.

 

  • 다른 뷰는 실제 뷰를 렌더링하지만 JSP의 경우는 forward()를 통해 해당 JSP로 이동해야 렌더링이 된다.

스프링 MVC

@Controller
public class SpringMemberFormControllerV1 {
    @RequestMapping("/springmvc/v1/members/new-form")
    public ModelAndView process() {
        return new ModelAndView("new-form");
    }
}
  • @Controller
    • 스프링이 자동으로 스프링 빈으로 등록한다.
      (내부에 @Component 어노테이션이 있기에 컴포넌트 스캔 대상이 된다.)
    • 스프링 MVC에서 어노테이션 기반 컨트롤러로 인식한다.
  • @RequestMapping : 요청 정보를 매핑한다. 해당 URL이 호출되면 해당 어노테이션이 붙은 메소드가 호출된다.
    • 어노테이션 기반으로 동작하기 때문에 메소드 이름은 임의로 지으면 된다.
  • RequestMappingHandlerMapping은 스프링 빈 중에서 @RequestMapping이나 @Controller가 클래스 레벨에 붙은 경우에만 매핑 정보로 인식한다.

스프링 MVC - 컨트롤러 통합

@Controller
@RequestMapping("/springmvc/v2/members")
public class SpringMemberControllerV2 {
    private MemberRepository memberRepository = MemberRepository.getInstance();

    @RequestMapping("/new-form")
    public ModelAndView newForm() {
        return new ModelAndView("new-form");
    }

    @RequestMapping("/save")
    public ModelAndView save(HttpServletRequest request, HttpServletResponse response) {
        String username = request.getParameter("username");
        int age = Integer.parseInt(request.getParameter("age"));

        Member member = new Member(username, age);
        memberRepository.save(member);

        ModelAndView mv = new ModelAndView("save-result");
        mv.addObject("member", member);

        return mv;
    }

    @RequestMapping
    public ModelAndView members() {
        List<Member> members = memberRepository.findAll();

        ModelAndView mv = new ModelAndView("members");
        mv.addObject("members", members);

        return mv;
    }
}
  • @RequestMapping은 메소드 레벨에 사용할 수 있기 때문에 컨트롤러를 통합해서 사용할 수 있다.
    • 각 메소드 매핑 URL의 중복은 클래스 레벨에 @RequestMapping(URL)로 공통 처리를 해줄 수 있으며 메소드 레벨과 조합이 된다.

스프링 MVC - 실용적인 방식

@Controller
@RequestMapping("/springmvc/v3/members")
public class SpringMemberControllerV3 {
    private MemberRepository memberRepository = MemberRepository.getInstance();

    @RequestMapping(value = "/new-form", method = RequestMethod.GET)
    //@GetMapping()
    public String newForm() {
        return "new-form";
    }

    @RequestMapping(value = "/save", method = RequestMethod.POST)
    public String save(@RequestParam("username") String username,
                       @RequestParam("age") int age,
                       Model model) {
        Member member = new Member(username, age);
        memberRepository.save(member);

        model.addAttribute("member", member);

        return "save-result";
    }

    @RequestMapping(method = RequestMethod.GET)
    //@PostMapping()
    public String members(Model model) {
        List<Member> members = memberRepository.findAll();

        model.addAttribute("members", members);

        return "members";
    }
}
  • 스프링 MVC에서 어노테이션 방식은 ModelAndView를 반환해도 되지만 String을 반환하는 방식도 있다.
    • String을 반환하는 경우 뷰의 논리명을 문자열로 반환한다.
  • @RequestParam : HTTP 요청 파라미터를 처리하는 어노테이션으로 HttpServletRequest의 getParameter()와 기능이 동일하다
  • Model 파라미터를 받아서 렌더링에 필요한 데이터를 넘겨줄 수 있다.
  • 기존 @RequestMapping 방식은 해당 URL이면 GET 이든 POST 이든지 상관 없이 무조건 호출하는 방식이였다. 
    • 속성에 method로 방식을 지정하면 해당 방식으로 요청이 올 때만 호출된다.
    • Get 방식인 경우 @GetMapping, POST 방식의 경우 @PostMapping도 같은 기능을 수행한다.
      • GET, POST, PUT, DELETE, PATCH 모두 어노테이션으로 제공한다.

출처 : [인프런 김영한 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술]

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

 

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

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

www.inflearn.com