[MVC] 5. 스프링 MVC 구조 이해
스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 (김영한) 강의 수강 후 정리한 자료입니다.
❗스프링 MVC 구조 이해❗
✨ 스프링 동작 방식 정리
핸들러
- 컨트롤러 안에서 어떤 요청을 처리할 수 있는 메서드
- @Controller와는 다르며, 핸들러 = 컨트롤러라 생각해도 무방하다.
-> 여러 개의 핸들러를 미리 스프링에서 만들어 둚.
핸들러 매핑
- 요청 url과 매칭되는 컨트롤러를 찾아준다.
- 핸들러 어댑터는 말 그대로 어댑터 기능을 하는데, 핸들러 매핑에서 찾은 컨트롤러를 어떤 어댑터가 처리할 수 있는지 확인하고 값을 ModelAndView로 반환한다.
ModelAndView
- 스프링에서 컨트롤러가 처리한 결과를 보여줄 뷰와 필요한 데이터를 모델에 담아 전달하기 위한 클래스
ViewResolber
- ModelAndView 객체를 view 영역으로 전달하기 위해 알맞은 view 정보를 설정하는 역할을 한다.
✨ 컨트롤러 호출
- 핸들러 매핑에서 컨트롤러 찾기
- 핸들러 (컨트롤러)를 찾고 실행해 주는 핸들러 어댑터가 필요하다.
✨ 스프링 MVC
@Controller
- 컴포넌트 스캔의 대상
- 스프링 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