URL에서 파라미터 값과 이름을 함께 전달하는 방식으로 주로 HTTP 통신 Method 중 GET 방식의 통신을 할 때 많이 사용. @Requestparam을 사용하면 요청 파라미터 값에 아주 쉽고 간편하게 접근(Parameter Binding)가능. ? 뒤에 오는 URL을 Query String, Query Parameter, Request Param이라 함.
// GET http://localhost:8080/v1/request-param?name=사용자1&age=28 @ResponseBody @GetMapping("/v1/request-param") public String requestParamV1 ( @RequestParam("name") String userName, @RequestParam("age") int userAge) { log.info("name={}", userName); // name=사용자1 log.info("age={}", userAge); // age=28 return "success"; }
@Controller + @ResponseBody
- View를 찾는 것이 아니라 ResponseBody에 응답을 작성(=
@RestController)@RequestParam
- 파라미터 이름으로 바인딩
@RequestParam("속성값")
- 속성값이 파라미터 이름으로 매핑
// GET http://localhost:8080/v2/request-param?name=사용자1&age=28 @ResponseBody @GetMapping("/v2/request-param") public String requestParamV2 ( @RequestParam String name, @RequestParam int age) { log.info("name={}", name); // name=사용자1 log.info("age={}", age); // age=28 return "success"; }
- 속성값과 변수명이 같으면 생략 가능
@RequestParam("name") String name==@RequestParam String name
@ResponseBody @GetMapping("/v4/request-param") public String requestParamV4 ( @RequestParam(required = true) String name, // 필수 @RequestParam(required = false) int age // 필수 아님) { log.info("name={}", name); log.info("age={}", age); return "success"; } // http://localhost:8080/v4/request-param?name=사용자1&age=28 → 정상 요청 // http://localhost:8080/v4/request-param?name=사용자1 → 정상 요청 // http://localhost:8080/v4/request-param?age=28 → Exception 발생 // http://localhost:8080/v4/request-param → Exception 발생 (int 타입에는 null을 넣을 수 없기 때문에 500 Error 발생, 따라서 Integer나 default 옵션을 사용)
- required 속성 설정
- 파라미터의 필수 값을 설정
- API 스펙을 규정할 때 사용
- @RequestParam을 사용하면 default값은 True
- true로 설정된 파라미터 값이 요청에 존재하지 않으면 400 BadRequest(클라이언트 측 에러)
@ResponseBody @GetMapping("/v5/request-param") public String requestParamV5 ( @RequestParam(required = true, defaultValue = "사용자1") String name, @RequestParam(required = false, defaultValue = "1") int age) { log.info("name={}", name); log.info("age={}", age); return "success" } // http://localhost:8080/v5/request-param?age=28 → name=사용자1, age=28 // http://localhost:8080/v5/request-param?name=사용자1 → name=사용자1, age=28 // http://localhost:8080/v5/request-param → name=사용자1, age=28 // http://localhost:8080/v5/request-param?name&age → name=사용자1, age=28 // http://localhost:8080/v5/request-param?name=user1age=32 → name=user1, age=32
- default 속성 적용
- 파라미터의 기본 값을 설정
@ResponseBody @GetMapping("/v6/request-param") public String requestParamV6( @RequestParam Map<String, String> map) { log.info("name={}", map.get("name")); log.info("age={}", map.get("age")); return "success"; } http://localhost:8080/v6/request-param?name=사용자1&age=28@ResponseBody @GetMapping("/v6/request-param") public String requestParamV6( @RequestParam MultiValueMap<String, String> map) { log.info("name={}", map.get("name")); log.info("age={}", map.get("age")); return "success"; } http://localhost:8080/v6/request-param?name=사용자1&name=user1&name=person1&age=28
- Map 사용
- 파라미터를 Map 형태로 조회 가능
- MultiValueMap 형태도 조회 가능
요청 파라미터를 받아 필요한 Object로 바인딩 해줌. 주로 HTML 폼에서 전송된 파라미터를 바인딩하고 HTTP Method POST인 경우 사용.
@ResponseBody @PostMapping("/v2/member") public String modelAttributeV2( @ModelAttribute Member member) { String name = member.getName(); int age = member.getAge(); return "member name = " + name + " age = " + age; } // http://localhost:8080/v2/member + x-www-form-urlencoded// Postman POST /v2/member content-type: application/x-www-form-urlencoded name=사용자1&age=28
- @ModelAttribute 동작 순서
- 파라미터에 @ModelAttribute가 있으면 파라미터인 Member 객체를 생성
- 요청 파라미터 이름으로 객체 필드의 Setter를 호출해서 바인딩
- 파라미터 이름이
name이면setName(value)를 호출- 파라미터 이름과 필드 이름이 반드시 같아야 함
- 만약 Setter가 없다면, 객체 필드에 값이 설정되지 않음
- 파라미터의 타입이 다르다면(age에
String값이 전달된다면), BindException 발생
→ Validation(검증)이 필요한 이유
- HttpEntity의 역할
- Http Request Body Message를 직접 조회한다
- Request 뿐만 아니라 Response도 사용할 수 있도록 만들어줌
- Response Header도 사용 가능
- Request Parameter를 조회하는 기능과는 관계가 없으며, View를 반환하지 않음
- HttpEntity를 상속 받은 객체
RequestEntity<>
- HTTP Request Method, URL 정보가 추가 되어있음
ResponseEntity<>
- HTTP Response 상태 코드 설정 가능
@Controller // @RestController = @Controller + @ResponseBody
public class RequestBodyStringController {
@ResponseBody
@PostMapping("/v5/request-body-text")
public String requestBodyTextV5(
@RequestBody String body,
@RequestHeader HttpHeaders headers) {
// HttpMessageConverter가 Http RequestBody Message를 읽어서 String이나 Object로 변환해줌
String bodyMessage = body;
return "request header = " + headers + " response body = " + bodyMessage;
}
}
- 요청 파라미터, HTML Form 데이터에 접근하는 경우
- @RequestParam, @ModelAttribute 사용
- Http Message Body에 접근하는 경우
- @RequestBody 사용(json, XML, TEXT)
- @RestController 에서 가장 많이 사용되는 데이터 형식
- 대부분의 API는 Request, Response 모두 json 형태로 통신
- Json 형태로 데이터를 전송할 때는 Request Header의 content-type에 application/json 설정 필수
스프링에서 HTTP 요청과 응답을 변환하는 인터페이스. 클라이언트와 서버 간에 데이터를 주고받을 때, 요청 데이터를 자바 객체로 변환하거나 자바 객체를 응답 본문으로 변환하는 역할을 수행.
💡 `MappingJackson2HttpMessageConverter`는 json을 처리하는 대표적인 HTTP Message Converter의 구현체이다.
// json { "name": "사용자1", "age": 28 } 👇 👆 // HTTP Message Converter 👇 👆 // Object public class Member { private String name; private int age; }
- @RequestBody
- 요청 데이터 + Request Header를 참고하여 Object로 변환
- HTTP Request Body(json Data) → Converter(Jackson) → Object
- Reqeust Header
- Content-Type : application/json(전달할 데이터 형식)
- @ResponseBody
- 응답 데이터 + Accept Header를 참고하여 원하는 데이터 형식으로 변환
- Object → Converter(Jackson) → HTTP Response Body(json Data)
- Request Header
- Accept : application/json(허용할 데이터 형식)
웹 애플리케이션에서 변하지 않는 파일들을 의미하며, HTML, CSS, JavaScript, 이미지 파일(JPG, PNG, GIF) 등이 해당함.
/static/public/META-INF/resourcessrc/main/resources/staticSpring에서는 Thymeleaf, JSP와 같은 템플릿 엔진을 사용해 View Template 작성 가능. View Template은 서버에서 데이터를 받아 HTML 구조에 맞게 삽입한 후, 최종적으로 클라이언트에게 전송되는 HTML 문서로 변환하여 사용자에게 동적으로 생성된 웹 페이지를 제공.
📌 View Template
- View Template은 Model을 참고하여 HTML 등이 동적으로 만들어지고 Client에 응답된다.
- Spring Boot는 기본적으로 View Template 경로(
src/main/resources/templates)를 설정한다.- build.gradle에 Thymeleaf 의존성을 추가하면
ThymeleafViewResolver와 필요한 Spring Bean들이 자동으로 등록된다.
@Controller public class ViewTemplateController { @RequestMapping("/response-view") public String responseView(Model model) { // key, value model.addAttribute("data", "example"); return "thymeleaf-view"; // View name } }<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Hello</title> </head> <body> <h1>Thymeleaf</h1> <h2 th:text="${data}"></h2> </body> </html>
- @Controller의 응답으로 String을 반환하는 경우
- @ResponseBody가 없으면 View Resolver가 실행되며, View를 찾고 렌더링함
- @ResponseBody가 있으면 HTTP Message Body에 return 문자열 값이 입력됨
REST API를 만드는 경우 Server에서 Client로 HTML을 전달하는 방식이 아닌 HTTP Message Body에 직접 Data를 json 형식으로 담아서 전달.
- HttpServletResponse
@Controller public class ResponseBodyController { @GetMapping("/v1/response-body") public void responseBodyV1( HttpServletResponse response) throws IOException { response.getWriter().write("data"); } }
- Reponse Body에 data라는 문자열이 입력되어 응답
- 기존 Servlet을 다룰 때의 코드와 같은 형태
- ResponseEntity<>
@GetMapping("/v2/response-body") public ResponseEntity<String> responseBodyV2() { return new ResponseEntity<>("data", HttpStatus.OK); }
- Response Body에 data라는 문자열과 HttpStatus.OK에 해당하는 상태 코드를 반환
- ResponseEntity는 HttpEntity를 상속 받음
- HttpEntity는 HTTP Message의 Header, Body 모두 가지고 있음
- @ResponseBody(TEXT, json)
@Data @NoArgsConstructor // 기본 생성자 @AllArgsConstructor // 전체 필드를 인자로 가진 생성자 public class Member { private String name; private int age; }// TEXT 데이터 통신 @ResponseBody @GetMapping("/v3/response-body-text") public String responseBodyText() { return "data"; // HTTP Message Body에 "data" }@ResponseStatus(HttpStatus.OK) @ResponseBody @GetMapping("/v4/response-body") public Member responseBodyJson() { Member member = new Member("사용자1", 28); return member; }
- View를 사용하는 것이 아닌 HTTP Message Converter를 통해 HTTP Message Body를 직접 입력 가능
- ResponseEntity와 동일
- @ResponseStatus를 사용하여 상태 코드 지정 가능
- 응답 코드를 조건에 따라서 동적으로 변경 불가
- ResponseEntity <Object>(json)
@ResponseBody @GetMapping("/v5/response-body") public ResponseEntity<Member> responseBody() { Member member = new Member("사용자1", 28); if (조건) { return new ResponseEntity<>(member, HttpStatus.OK); } else { return new ResponseEntity<>(member, HttpStatus.BAD_REQUEST); } }
ResponseEntity<>두 번째 파라미터에 Enum(HttpStatusCode)을 사용하여 상태 코드 설정 가능
- 동적으로 응답 코드를 변경 가능
- HTTP Message Converter를 통하여 json 형태로 변환되어 반환