본 시리즈는 인프런 학습 사이트의 김영한 강사님의 java spring mvc - 백엔드 웹 개발 핵심 기술 편을 학습한 내용을 바탕으로 정리하였습니다.
지난 시간까지 우리는 Dispatcher Servlet
이 컨트롤러에 동작하면서 핸들러 어댑터를 매핑하고 뷰 리졸버를 통해 View를 반환 받는 것까지 살펴보았다. 이러한 사이클을 기억하면서 이제 드디어 본격적으로 스프링 MVC를 시작해보자.
애노테이션(@)
기반으로 동작@RequestMapping
애노테이션을 사용하는 컨트롤러를 사용import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class SpringMemberFormControllerV1 {
@RequestMapping("/springmvc/v1/members/new-form")
public ModelAndView process() {
return new ModelAndView("new-form");
}
}
@Controller
: 스프링이 자동으로 스프링 빈으로 등록한다. 또한, 스프링 MVC에서 애노테이션 기반 컨트롤러로 인식하게 된다.
@RequestMapping
: 요청 정보를 매핑한다. 해당 URL이 호출되면 이 메서드가 호출된다. 애노테이션을 기반으로 동작하기 때문에, 메서드의 이름은 임의로 지으면 된다.
ModelAndView
: 모델과 뷰 정보를 담아서 반환하면 된다.
RequestMappingHandlerMapping
은 스프링 빈 중에서 @RequestMapping
또는 @Controller
가 클래스 레벨에 붙어 있는 경우에 매핑 정보로 인식한다.
따라서 다음 코드도 동일하게 동작한다.
@Component // 컴포넌트 스캔을 통해 스프링 빈으로 등록
@RequestMapping
public class SpringMemberFormControllerV1 {
@RequestMapping("/springmvc/v1/members/new-form")
public ModelAndView process() {
return new ModelAndView("new-form");
}
}
@Controller
public class SpringMemberSaveControllerV1 {
private MemberRepository memberRepository = MemberRepository.getInstance();
@RequestMapping("/springmvc/v1/members/save")
public ModelAndView process(HttpServletRequest request, HttpServletResponse
response) {
/// ... (회원 저장에 대한 로직)
ModelAndView mv = new ModelAndView("save-result");
mv.addObject("member", member);
return mv;
}
}
mv.addObject("member", member)
ModelAndView
를 통해 Model 데이터를 추가할 때는 addObject()
를 사용하면 된다. 이 데이터는 이후 뷰를 렌더링 할 때 사용된다.@RequestMapping
을 잘 보면 클래스 단위가 아니라 메서드 단위에 적용된 것을 확인할 수 있다. 따라서 컨트롤러 클래스를 유연하게 하나로 통합할 수 있다.
SpringMemberControllerV2
@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) {
... (save에 관한 로직)
mav.addObject("member", member);
return mav;
}
@RequestMapping
public ModelAndView members() {
... (뷰에 관한 로직)
mav.addObject("members", members);
return mav;
}
}
💡컨트롤러를 조합하는것도 가능하다.
클래스 레벨에서@RequestMapping("/spring/mvc/v2/members")
을 사용함으로써 각 메서드에서/springmvc/v2/members
을 붙여주지 않아도 된다. 중복을 제거할 수 있게 된 셈이다.
@Controller
@RequestMapping("/springmvc/v3/members")
public class SpringMemberControllerV3 {
private MemberRepository memberRepository = MemberRepository.getInstance();
@GetMapping("/new-form")
public String newForm() {
return "new-form";
}
@PostMapping("/save")
public String save(
@RequestParam("username") String username,
@RequestParam("age") int age, Model model) {
// (생략)
model.addAttribute("member", member);
return "save-result";
}
@GetMapping
public String members(Model model) {
// (생략)
model.addAttribute("members", members);
return "members";
}
실무에서는 위와 같은 방식을 주로 사용한다.
Model 파라미터
: save()
, members()
를 보면 Model을 파라미터로 받는 것을 확인할 수 있다.
ViewName 직접 반환
: 뷰의 논리 이름을 반환할 수 있다.
@RequestParam 사용
: 스프링은 HTTP 요청 파라미터를 @RequestParam
으로 받을 수 있다.
@RequestParam("username")
은 request.getParameter("username")
와 거의 같은 코드라 생각하면 된다. 물론 GET 쿼리 파라미터, POST Form 방식을 모두 지원한다.
@RequestMapping → @GetMapping, @PostMapping
: @RequestMapping
은 URL만 매칭하는 것이 아니라, HTTP Method도 함께 구분할 수 있다. 참고로 Get
, Post
, Put
, Delete
, Patch
모두 애노테이션이 있다.