스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 (김영한) 강의 수강 후 정리한 자료입니다.

❗스프링 MVC 구조 이해❗

✨ 스프링 동작 방식 정리

image

핸들러

  • 컨트롤러 안에서 어떤 요청을 처리할 수 있는 메서드
  • @Controller와는 다르며, 핸들러 = 컨트롤러라 생각해도 무방하다.

-> 여러 개의 핸들러를 미리 스프링에서 만들어 둚.

핸들러 매핑

  • 요청 url과 매칭되는 컨트롤러를 찾아준다.
  • 핸들러 어댑터는 말 그대로 어댑터 기능을 하는데, 핸들러 매핑에서 찾은 컨트롤러를 어떤 어댑터가 처리할 수 있는지 확인하고 값을 ModelAndView로 반환한다.

ModelAndView

  • 스프링에서 컨트롤러가 처리한 결과를 보여줄 뷰와 필요한 데이터를 모델에 담아 전달하기 위한 클래스

ViewResolber

  • ModelAndView 객체를 view 영역으로 전달하기 위해 알맞은 view 정보를 설정하는 역할을 한다.

✨ 컨트롤러 호출

  1. 핸들러 매핑에서 컨트롤러 찾기
  2. 핸들러 (컨트롤러)를 찾고 실행해 주는 핸들러 어댑터가 필요하다.

✨ 스프링 MVC

@Controller

  1. 컴포넌트 스캔의 대상
  2. 스프링 MVC에서 애노테이션 기반 컨트롤러로 인식한다.

@RequestMapping

  • RequestMappingHandlerMapping
  • RequestMappingHandlerAdapter

이 두 개를 지원해 줌으로써 컨트롤러를 호출할 수 있도록 도와준다.

또한, RequestMappingHandlerMapping과 같은 경우, 스프링 빈으로 등록되어 있는 것 중에서 @RequestMapping 또는 @Controller이 클래스 레벨에 붙어 있는 경우 매핑 정보로 인식한다.

-> 구현되어 있는 RequestMappingHandlerMapping 코드 내부에 아래와 같은 코드가 있음.

@Override
protected boolean isHandler(Class<?> beanType) {
  return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
  AnnotateElementUtils.hasAnnotation(beanType, RequestMapping.class));
}

따라서 핸들러인지 아닌지 구분하려면 “클래스” 레벨에 Annotation이 붙어 있어야 함.

✨ 스프링 MVC - 실용적인 방식

  • 애노테이션 기반 컨트롤러는 String으로 반환해도 그 값으로 View를 찾아준다.
    -> 꼭 ModelAndView를 반환하지 않아도 된다.

@RequestParam

  • request, response 말고도 파라미터를 직접 받는 방법을 사용해 코드를 깔끔하게 수정한다.

기존 코드

@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("/save")
    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";
    }

위와 같이 코드를 수정하면 파라미터를 파싱하지 않아도 되며, String으로 View를 찾을 수 있으므로 ModelAndView를 통해 전달하지 않아도 되어 코드가 깔끔해진다.

RequestMapping 개선

  • 모든 것을 전부 @RequestMapping으로 받아버리면, 이 요청이 GET인지, POST인지 상관하지 않고 해당 url로 오는 요청을 모두 처리하게 된다. 이는 좋은 코드가 아니므로, 요청 방식을 명시해 줘야 한다.
// 기존 코드
@RequestMapping("/new-form")

// 수정 코드
@RequestMapping(value = "/new-form", method = RequestMethod.GET)

너무 길다는 단점이 있어, @RequestMapping보다는 @GetMapping, @PostMapping처럼 짧게 줄여 사용한다.

@GetMapping("new-form")

이렇게 수정하면 GET으로 요청이 들어올 때만 처리를 하게 된다.

✨ 참고자료

  • https://ksabs.tistory.com/250
  • https://ittrue.tistory.com/237
  • https://jjangadadcodingdiary.tistory.com/entry/Spring-ModelAndView%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%9C-%EB%B7%B0%EC%99%80-%EB%AA%A8%EB%8D%B8%EC%9D%98-%ED%9A%A8%EA%B3%BC%EC%A0%81%EC%9D%B8-%EC%A0%84%EB%8B%AC
  • https://velog.io/@qkrmekem/%ED%95%B8%EB%93%A4%EB%9F%AC-%EB%A7%A4%ED%95%91%EA%B3%BC-%ED%95%B8%EB%93%A4%EB%9F%AC-%EC%96%B4%EB%8C%91%ED%84%B0

카테고리:

업데이트: