Spring

(Spring)@GetMapping & @PostMapping

odong2 2022. 9. 4. 19:21

@RequestMapping을 사용할 때 @RequestMapping("/add")와 같이 사용하였다.

이 문장의 원래 형태는 @RequestMapping(value="/add", method={RequestMethod.GET, RequestMethod.POST})이다.

즉 RequestMapping에 method 부분을 생략하면 배열의 형태로 GET과 POST방식 둘 다 허용한다는 의미가 된다.

 

만약 GET방식만 허용 하고 싶은 경우에는 @RequestMapping(value="/add", method=RequestMethod.GET) 와 같이 명시적으로 적어야한다.

 

하지만 위의 코드가 번잡하기 때문에 Spring 4.3 이후 부터 @GetMapping / @PostMapping을 지원하게 되었다.

즉 이 둘 애너테이션은 @RequestMapping을 좀 더 간단하게 사용하게 하기 위해 만들어진 애너테이션이다.

아래의 코드를 통해 자세히 살펴보자.

@Controller
@RequestMapping("/register")
//신규 회원 가입 화면
public class RegisterController {
//	@RequestMapping(value="/add", method={RequestMethod.GET, RequestMethod.POST}) 
	@GetMapping("/add")
	public String register() {
		return "registerForm"; // WEB-INF/views/registerForm.jsp
	}

//	@RequestMapping(value="/save", method=RequestMethod.POST) -> Get방식으로는 회원가입 불가
//	@RequestMapping(value="/save", method={RequestMethod.GET, RequestMethod.POST) -> 배열로 가능(get과 post요청 둘 다 허용)
// 	@RequestMapping("/save")로 메서드 명시가 없으면 위의 문장과 동일 / 즉 get, post요청 둘 다 받는다
	@PostMapping("/save")  // Spring 4.3부터 
	public String save(User user, Model m) throws Exception {
		// 1. 유효성 검사
		if(!isValid(user)) {
			String msg = URLEncoder.encode("id를 잘못입력하셨습니다.", "utf-8");
			
			m.addAttribute("msg", msg);
			return "forward:/register/add";
//			return "redirect:/register/add?msg="+msg; // URL재작성(rewriting), 위 두 줄과 동일
		}
		
		// 2. DB에 신규회원 정보를 저장 
		return "registerInfo";
	}

	private boolean isValid(User user) {
		return false;
	}
}

 

신규회원 가입 화면의 경우 화면만 보여주는 것이기 때문에 POST는 필요 없으므로 위의 코드에서와 같이

@GetMapping("/add")로 GET 요청만 받게 끔 변경할 수 있다.

 

하지만 이는 registerForm.jsp 와 url 연결만 해줄 뿐 딱히 하는 일이 없다.

 

그래서 이것을 view-controller로 바꿀 수 있다.

 

 

view-controller 연결 방법

 

view-controller에 연결하기 위해서는 [webapp] → [WEB-INF] → [appServlet] → servlet-context.xml에서 설정해야 한다.

참고로 servlet-context.xml 은 스프링과 관련되 web설정을 하는 xml 파일이다.

servlet-context.xml에 파일에서 위와 같이 view-controller를 작성하면 path에 등록된 주소를 view-name에 작성된 jsp파일과 연결하게 된다.

 

view-controller에 등록한 것은 GET 요청만 가능하다는 특징이 있다.

 

즉 위의 코드에서 @GetMapping("/add") 한 register 메서드와 똑 같은 역할을 이 한줄이 대신하게 된다.

 

 

URLEncoder.encode

위 코드에서 주석으로 막아 놓은 svae 메서드의 return "redirect:/register/add?msg="+msg; 부분을 살펴보자.

브라우저에서 주소창에 직접 사용자가 한글을 입력할 때는 브라우저가 자동으로 URL 인코딩을 해준다.

하지만 redirect:/register/add?msg="+msg 와 같이 컨트롤러에서 직접 URL을 만들면 이것은 브라우저가 직접 인코딩 해 줄 수가 없다.

그러므로 개발자가 아래와 같이 URL인코딩을 직접 해줘야 한다.

 

String msg = URLEncoder.encode("id를 잘못입력하셨습니다.", "utf-8");

 

그리고 이 url을 받는 jsp에서는 utf-8로 아래와 같이 디코드를 해줘야 한다.

URLDecoder는 java.net 패키지에 있기 때문에 import문 또한 명시하여야 한다. 

 

<%@ page import="java.net.URLDecoder"%>
${URLDecoder.decode(param.msg, "utf-8")}

 

클래스에 붙이는 @RequestMapping

@RequestMapping("/register")
//신규 회원 가입 화면
public class RegisterController {
//	@RequestMapping(value="/add", method={RequestMethod.GET, RequestMethod.POST}) 
	@GetMapping("/add")
	public String register() {
		return "registerForm"; // WEB-INF/views/registerForm.jsp
	}

원래는 RequestMapping을 Controller클래스 안의 메서드에서 작성하였지만 GET,POST 매핑 사용시 클래스 앞에 작성할 수 있다.

RequestMapping을 메서드에 붙일 때는 @RequestMapping("register/add") 와 같이 상위 경로인 register까지 다 붙여 적었지만 클래스에 RequestMapping("/register") 와 같이 명시하면 그 하위 메서드에서는 @GetMapping("/add)만 적으면 

클래스에 있는 RequestMapping과 합쳐져서 @RequestMapping("register/add")으로 된다.

 

결론은 클래스에 명시된 @RequestMapping("")이 클래스 안의 GET/POST 매핑에 모두 붙게 된다.

 

스프링에서는 서블릿과 달리 매핑을 클래스 별이 아닌 메서드 별로 하게 되는데 이 메서드를 모듈별("/register")로 나눠서 하나의 클래스에 넣고 나머지 메서드에서는 그 이후 경로만 작성한다.

 

 

 

Reference

'스프링의 정석 : 남궁성과 끝까지 간다' 수강 후 복습한 내용입니다.