[김영한님의 스프링 MVC 1편-백엔드 웹 개발 핵심 기술을 학습 후 정리한 내용입니다.]
HTTP요청이 들어올 때 매핑하는 방식부터 시작해서, 여러가지 어노테이션으로 요청 파라미터를 처리하는 방식, 또 json은 어떻게 처리하는지, 그리고 응답하는 방법과 여러가지 예시를 다루었다. 나중에 까먹을 수도 있다는 생각으로 정리했다.
● HTTP 요청을 매핑해보자.
@RequestMapping(value= "/URL", method = RequestMethod.HTTP메서드)
@RequestMapping(value="/hello-basic", method=RequestMethod.GET)
public String helloBasic() {
log.info("helloBasic");
return "ok";
}
URL요청이 오면 이 어노테이션이 붙은 메서드가 실행되도록 매핑하는 역할을 한다. @RequestMapping에 method속성으로 HTTP 메서드를 지정하지 않을 시에 get, post, patch, delete 등과 같은 HTTP 메서드와 무관하게 호출이 가능하다. 하지만,, 보다 Restful한 개발을 하기 위해서는 HTTP method가 명시된 @GetMapping, @PostMapping과 같은 어노테이션을 사용해야 할 것이다.(직관적이기도 하다)
● HTTP 요청 파라미터를 어떻게 받을까?
@PathVariable
@GetMapping("/mapping/users/{userId}/orders/{orderId}")
public String mappingPath(@PathVariable String userId, @PathVariable Long
orderId) {
log.info("mappingPath userId={}, orderId={}", userId, orderId);
return "ok";
}
PathVariable(경로변수)을 사용해서 요청의 파라미터값들을 받을 수 있다. 위와 같이 @PathVariable의 이름과 파라미터 이름이 같으면 생략가능하다.ex) URL의 {userId}와 메서드 인자의 userId가 같다.
@RequestParam
@RequestMapping("/request-param-v3")
public String requestParamV3(
@RequestParam String username,
@RequestParam int age){
log.info("username={}, age={}",username,age);
return "ok";
}
@RequestParam을 사용하면 요청파라미터를 매우 편리하게 사용가능하다. url에서 각 구분자에 들어오는 값을 처리해야 할 때 앞 예제와 같이 @PathVariable을 사용했지만, @RequestParam의 경우도 url뒤에 붙는 파라미터의 값을 가져올 때 사용된다. 파라미터가 많아질 경우에는 Map<>으로 조회가 가능하다.
요청파라미터를 이런식으로 받게 되면, 실제로 우리 객체에 데이터를 저장할 수도 있어야 한다. 사전에 username과 age를 갖는 HelloData라는 클래스를 정의했고, 이 객체에 저장하는 방법은 아래와 같다.(@ModelAttribute를 사용)
@RequestMapping("/model-attribute-v1")
public String modelAttributeV1(@ModelAttribute HelloData helloData){
log.info("username={}, age={}", helloData.getUsername(), helloData.getAge());
return "ok";
}
@RequestBody
@PathVariable, @RequestParam은 요청파라미터를 조회하는 기능이었다. 이와 달리 @RequestParam은 HTTP 메시지 바디를 직접 조회하는 기능으로, HTTP api를 사용할 때 붙이는 기능이다. 참고로, @ResponseBody또한 붙이게 되면, HTTP 메시지바디에서 직접 조회해서 처리한 응답 결과를 HTTP 메시지 바디에 직접 담아서 반환할 수 있게 된다.
@PostMapping("/request-body-json-v3")
public String requestBodyJsonV3(@RequestBody HelloData data) {
log.info("username={}, age={}", data.getUsername(), data.getAge());
return "ok";
}
위의 요청파라미터인 data가 json형식이라고 가정했을 때, 우리는 @RequestBody를 붙이고, HelloData라는 직접 만든 객체를 지정함으로써 바로 그 객체에 저장되도록 할 수 있다.
*참고로 @RequestBody를 생략하면 @ModelAttribute가 적용되어버리기 때문에 @RequestBody는 생략하면 안된다!(@ModelAttribute가 적용되면 HTTP 메시지 바디가 아닌 요청 파라미터를 처리하게 될 것이므로,,)
- @RequestBody 요청 : JSON 요청 → HTTP 메시지 컨버터 → 객체
- @ResponseBody 응답 : 객체 → HTTP 메시지 컨버터 → JSON 응답
● HTTP 응답의 경우는 어떤 식으로 반환할까?
일단 스프링에서 응답으로 반환하는 것은 크게 ①정적리소스, ②동적html을 제공하는 뷰 템플릿, ③HTTP메시지 3가지로 구분지을 수 있다. ①의 경우는 스프링부트는 기본적으로 src/main/resources/static 의 경로상에 있는 정적 리소스를 제공한다. ②의 경우는 src/main/resources/templates 의 경로상에 있는 템플릿을 제공한다. ③의 경우는 @ResponseBody, HttpEntity를 사용하여 HTTP 메시지 바디에 직접 응답데이터를 담아서 반환할 수 있다.
아래와 같이 HttpEntity를 상속받은 ResponseEntity를 이용해서 메시지바디와 HTTP 응답코드를 설정하여 반환할 수 있다.
@GetMapping("/response-body-string-v2")
public ResponseEntity<String> responseBodyV2() {
return new ResponseEntity<>("ok", HttpStatus.OK);
}
사실, @ResponseBody와 @ResponseStatus(HttpStatus.HTTP상태)로 HTTP응답코드를 설정할 수 있지만, 이는 어노테이션이기 때문에 응답코드를 동적으로 변경할 수 없다는 단점이 있다. 따라서 프로그램 조건에 따라서 동적으로 변경하고 싶으면 ResponseEntity를 사용해야 한다.
@ResponseStatus(HttpStatus.OK)
@ResponseBody
@GetMapping("/response-body-json-v2")
public HelloData responseBodyJsonV2() {
HelloData helloData = new HelloData();
helloData.setUsername("userA");
helloData.setAge(20);
return helloData;
}
*참고
@Controller대신 @RestController를 사용하면, 해당 컨트롤러에 모두 @ResponseBody가 적용된다. 따라서 뷰 템플릿을 사용하는 것이 아닌, HTTP 메시지 바디에 직접 데이터를 입력하여 반환한다. 이름 그대로 Rest API를 만들 때 사용하는 컨트롤러이다. 실제로 RestController를 들어가보면 @Controller와 @ResponseBody가 적용된 모습을 볼 수 있다.
'Frameworks > Springboot' 카테고리의 다른 글
[Springboot] Synchronized, Database로 동시성 문제 해결하기 (0) | 2023.05.09 |
---|---|
[Springboot] PRG패턴 정리 (0) | 2022.08.26 |
[Springboot] 의존관계 자동 주입 방법 정리 (0) | 2022.07.28 |
[Springboot] 컴포넌트 스캔과 의존관계 자동주입 정리 (0) | 2022.07.25 |
[Springboot] 싱글톤 컨테이너 개념 정리 (0) | 2022.07.24 |
댓글