[Spring] 스프링 MVC - 간단하게 시작해보기
안녕하세요 이번 포스팅에서는 스프링 MVC를 간단하게 알아보겠습니다
스프링이 제공하는 컨트롤러는 애노테이션 기반으로 동작해서, 매우 유연하고 실용적입니다.
과거에는 자바 언어에 애노테이션이 없기도 했고, 스프링도 처음부터 이런 유연한 컨트롤러를 제공한 것은 아닙니다.
@RequestMapping
스프링은 애노테이션을 활용한 매우 유연하고, 실용적인 컨트롤러를 만들었는데 이것이 바로 @RequestMapping 애노테이션을 사용하는 컨트롤러입니다. 다들 한 번쯤 사용해보았을 것입니다. 여담이지만 과거에는 스프링 프레임워크가 MVC 부분이 약해서 스프링을 사용하더라도 MVC 웹 기술은 스트럿츠 같은 다른 프레임워크를 사용했었습니다. 그런데 @RequestMapping 기반의 애노테이션 컨트롤러가 등장하면서, MVC 부분도 스프링의 완승으로 끝이 났습니다.
그럼 이제 본격적으로 애노테이션 기반의 컨트롤러를 사용해보겠습니다.
SpringMemberFormControllerV1 - 회원 등록 폼
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 :
스프링이 자동으로 스프링 빈으로 등록합니다. (내부에 @Component 애노테이션이 있어서 컴포넌트 스캔의 대상이 됨) 스프링 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");
}
}
SpringMemberSaveControllerV1 - 회원 저장
import hello.servlet.domain.member.Member;
import hello.servlet.domain.member.MemberRepository;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Controller
public class SpringMemberSaveControllerV1 {
private MemberRepository memberRepository = MemberRepository.getInstance();
@RequestMapping("/springmvc/v1/members/save")
public ModelAndView process(HttpServletRequest request, HttpServletResponse
response) {
String username = request.getParameter("username");
int age = Integer.parseInt(request.getParameter("age"));
Member member = new Member(username, age);
System.out.println("member = " + member);
memberRepository.save(member);
ModelAndView mv = new ModelAndView("save-result");
mv.addObject("member", member);
return mv;
}
}
mv.addObject("member", member)
스프링이 제공하는 ModelAndView를 통해 Model 데이터를 추가 할 때는 addObject()를 사용하면 됩니다. 이 데이터는 이후 뷰를 렌더링 할 때 사용됩니다.
SpringMemberListControllerV1 - 회원 목록
import hello.servlet.domain.member.Member;
import hello.servlet.domain.member.MemberRepository;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import java.util.List;
@Controller
public class SpringMemberListControllerV1 {
private MemberRepository memberRepository = MemberRepository.getInstance();
@RequestMapping("/springmvc/v1/members")
public ModelAndView process() {
List<Member> members = memberRepository.findAll();
ModelAndView mv = new ModelAndView("members");
mv.addObject("members", members);
return mv;
}
}
스프링 MVC - 컨트롤러 통합
@RequestMapping을 잘 보면 클래스 단위가 아니라 메서드 단위에 적용된 것을 확인할 수 있습니다. 따라서 컨트롤러 클래스를 유연하게 하나로 통합할 수 있습니다.
SpringMemberControllerV2
import hello.servlet.domain.member.Member;
import hello.servlet.domain.member.MemberRepository;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
* 클래스 단위 -> 메서드 단위
* @RequestMapping 클래스 레벨과 메서드 레벨 조합
*/
@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 mav = new ModelAndView("save-result");
mav.addObject("member", member);
return mav;
}
@RequestMapping
public ModelAndView members() {
List<Member> members = memberRepository.findAll();
ModelAndView mav = new ModelAndView("members");
mav.addObject("members", members);
return mav;
}
}
클래스 레벨에 RequestMapping을 추가 하면서 중복을 제거할 수 있습니다.
스프링 MVC - 실용적인 방식
MVC 프레임워크 만들기에서 v3은 ModelAndView를 개발자가 직접 생성해서 반환했기 때문에, 불편했던 기억이 날것입니다. 물론 v4를 만들면서 실용적으로 개선도 했습니다.
스프링 MVC는 개발자가 편리하게 개발할 수 있도록 수 많은 편의 기능을 제공합니다.
실무에서는 지금 부터 설명하는 방식을 주로 사용합니다.
SpringMemberControllerV3
import hello.servlet.domain.member.Member;
import hello.servlet.domain.member.MemberRepository;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
/**
* v3
* Model 도입
* ViewName 직접 반환
* @RequestParam 사용
* @RequestMapping -> @GetMapping, @PostMapping
*/
@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) {
Member member = new Member(username, age);
memberRepository.save(member);
model.addAttribute("member", member);
return "save-result";
}
@GetMapping
public String members(Model model) {
List<Member> members = memberRepository.findAll();
model.addAttribute("members", members);
return "members";
}
}
Model 파라미터
save() , members() 를 보면 Model을 파라미터로 받는 것을 확인할 수 있습니다. 스프링 MVC도 이런 편의 기능을 제공합니다.
ViewName
직접 반환 뷰의 논리 이름을 반환할 수 있습니다.
@RequestParam 사용
스프링은 HTTP 요청 파라미터를 @RequestParam 으로 받을 수 있습니다. @RequestParam("username") 은 request.getParameter("username")와 거의 같은 코드라 생각하면 됩니다.
물론 GET 쿼리 파라미터, POST Form 방식을 모두 지원합니다.
@RequestMapping @GetMapping, @PostMapping
@RequestMapping 은 URL만 매칭하는 것이 아니라, HTTP Method도 함께 구분할 수 있습니다.
예를 들어서 URL이 /new-form 이고, HTTP Method가 GET인 경우를 모두 만족하는 매핑을 하려면 다음과 같이 처리하면 됩니다.
이것을 @GetMapping , @PostMapping 으로 더 편리하게 사용할 수 있습니다.
참고로 Get, Post, Put, Delete, Patch 모두 애노테이션이 준비되어 있습니다.
다음 포스팅 부터는 스프링에서 제공하는 여러 기능들에 대해서 알아보겠습니다!