Spring 요청 데이터, 응답 데이터

star_pooh·2024년 12월 12일
0

TIL

목록 보기
32/39
post-thumbnail

Spring 요청 데이터

@RequestParam

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 형태도 조회 가능

@ModelAttribute

요청 파라미터를 받아 필요한 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

  • HttpEntity의 역할
    • Http Request Body Message를 직접 조회한다
    • Request 뿐만 아니라 Response도 사용할 수 있도록 만들어줌
    • Response Header도 사용 가능
    • Request Parameter를 조회하는 기능과는 관계가 없으며, View를 반환하지 않음
  • HttpEntity를 상속 받은 객체
    • RequestEntity<>
      • HTTP Request Method, URL 정보가 추가 되어있음
    • ResponseEntity<>
      • HTTP Response 상태 코드 설정 가능

@RequestBody, @ResponseBody

@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;
  }
}
  • @RequestBody
    • 요청 메시지 Body Data를 쉽게 조회할 수 있음
  • @RequestHeader
    • 요청 헤더 정보 조회
  • @ResponseBody
    • 응답 메시지 Body에 값을 쉽게 담아서 전달할 수 있도록 해줌
    • View가 아닌 데이터를 반환
  • 요청 파라미터, HTML Form 데이터에 접근하는 경우
    • @RequestParam, @ModelAttribute 사용
  • Http Message Body에 접근하는 경우
    • @RequestBody 사용(json, XML, TEXT)

json

  • @RestController 에서 가장 많이 사용되는 데이터 형식
  • 대부분의 API는 Request, Response 모두 json 형태로 통신
  • Json 형태로 데이터를 전송할 때는 Request Header의 content-type에 application/json 설정 필수

HTTP Message Converter

스프링에서 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(허용할 데이터 형식)

Spring 응답 데이터

정적 리소스

웹 애플리케이션에서 변하지 않는 파일들을 의미하며, HTML, CSS, JavaScript, 이미지 파일(JPG, PNG, GIF) 등이 해당함.

  • Spring Boot의 정적 리소스 경로
    • 아래 경로들에 정적 리소스가 존재하면 서버에서 별도의 처리 없이 파일 그대로 반환
    • /static
    • /public
    • /META-INF/resources
    • src/main/resources
      • /static

View Template

Spring에서는 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 문자열 값이 입력됨

HTTP Message Body

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 형태로 변환되어 반환

0개의 댓글

관련 채용 정보