WEEK 5-5: Spring 요청 데이터

ensalada.de.pollo·2025년 5월 11일

be

목록 보기
19/44

@RequestParam

@RequestParam은 HTTP 요청의 쿼리 파라미터 또는 폼 데이터 값을 컨트롤러 메서드의 파라미터로 바인딩할 때 사용하는 어노테이션입니다.
내부적으로는 HttpServletRequest.getParameter("key")와 같은 역할을 더 간결하게 처리할 수 있게 해줍니다.

@GetMapping("/user")
public String getUser(@RequestParam("name") String userName,
					@RequestParam("age") int userAge) {
    // 요청 예시: /user?name=example&age=100
    // userName과 userAge에 쿼리 파라미터 값이 바인딩
	return userName + ", " + userAge;
}

파라미터 이름과 변수명이 같으면 생략이 가능합니다.

@GetMapping("/user")
public String getUser(@RequestParam String name, @RequestParam int age) {
	...
}

단순한 타입이면 @RequestParam 자체도 생략이 가능합니다.

@GetMapping("/user")
public String getUser(String name, int age) {
	...
}

단, 이 경우 파라미터 이름과 변수명이 같아야 하며, 혼동 방지를 위해 명시적으로 작성하는 것을 권장하는 편입니다.

옵션 속성

  1. required(필수 여부)
    기본값은 true입니다. 파라미터가 있어야 하고, 없으면 400 Bad Request가 발생됩니다. 여기서 int와 같은 타입은 null로 받지 못해서, Integer(래퍼 타입)을 사용해야 안전합니다.

  2. defaultValue(기본값)
    파라미터가 없거나 빈 문자열일때 기본값을 지정할 수 있습니다. defaultValue가 있으면 required는 자동으로 false가 됩니다.

Map, MultiValueMap으로 파라미터 받기

모든 파라미터를 한 번에 받고 싶을 때 Map을 사용할 수 있습니다. 동일한 파라미터가 여러 번 오면 MultiValueMap을 사용합니다.

Map

@GetMapping("/user")
public String getUser(@RequestParam Map<String, Sring> paramMap) {
	/// paramMap.get("name"), paramMap.get("age")
    return ...;
}

MultiValueMap

@GetMapping("/user")
public String getUser(@RequestParam MultiValueMap<String, String> paramMap) {
	// paramMap.get("name") -> [철수, 영희, 민지]
    return ...;
}

@RequestParam vs. @PathVariable

차이@RequestParam@PathVariable
위치쿼리 파라미터, 폼 데이터(?key = value)URL 경로의 일부(/users/{id})
용도검색, 필터, 옵션 등 선택적 데이터 전달자원 식별자(고유값) 전달
필수 여부required, defaultValue로 조정이 가능항상 필수
다중 값 처리Map, MultiValueMap 등으로 다중 값 처리 가능일반적으로 단일 값

HttpServletRequest, InputStream/Writer

HttpServletRequest.getInputStream()으로 요청 본문을 직접 읽고, 응답은 HttpServletResponse.getWriter()로 작성합니다.
서블릿 프로그래밍과 유사하게, 바이트 스트림을 직접 다루고 데이터를 수동으로 파싱해야 합니다.

@PostMapping("/request-body-text")
public void requestBodyText(HttpServletRequest request, HttpServletResponse response) throws IOException {
	ServletInputStream inputStream = request.getInputStream();
    String bodyText = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
    response.getWriter().write("response = " + bodyText);
}

InputStream/Writer를 파라미터로 직접 받을 수 있기도 합니다.

@PostMapping("/request-body-text")
public void requestBodyText(InputStream inputStream, Writer responseWriter) throws IOException {
	String body = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
    responseWriter.write("response = " + body);
}

HttpEntity<T>

HttpEntity는 HTTP 요청 또는 응답의 헤더와 body를 모두 캡슐화한 객체입니다. 제네릭 타입(T)에 따라 본문 데이터를 자동으로 변환해줍니다. 이 때 HttpMessageConverter가 작동하고 Content-Type에 맞게 본문을 String, 객체 등으로 변환합니다.

@PostMapping("/request-body-text")
public HttpEntity<String> requestBodyText(HttpEntity<String> httpEntity) {
	String body = httpEntity.getBody();
    return new HttpEntity<>("response = " + body);
}

요청 본문이 JSON이라면 HttpEntity<class이름>로 객체를 변환하여 받을 수 있습니다.

@RequestBody 사용

@RequestBody는 HTTP Messgae Body의 데이터를 원하는 타입(문자열, 객체 등)으로 자동 변환하여 파라미터에 바인딩해줍니다. 내부적으로 HttpMessageConverter가 동작해 Content-Type에 따라 적절한 컨버터가 JSON, XML, TEXT를 객체로 변환합니다.

@PostMapping("/request-body-string")
public String requestBodyString(@RequestBody String body) {
	return "response = " + body;
}

JSON을 객체로 받는 경우는 아래와 같습니다.

@PostMapping("/request-body-json")
public Stirng requestBodyJson(@RequestBody User user) {
	// JSON -> User 객체 변환
    return "name = " + user.getName();
}

@RequestBody는 생략할 수 없습니다. 생략하면 @ModelAttribute로 처리돼 파라미터가 HTTP 본문이 아닌 쿼리 파라미터 또는 폼 파라미터에서 추출됩니다.

HttpMessageConverter

HttpMessageConverter는 Spring에서 HTTP 요청 또는 응답의 body를 Java 객체와 JSON, XML, TEXT 등으로 상호 변환하는 역할을 합니다.
요청의 Content-Type, 응답의 Accept 헤더에 따라 적절한 컨버터가 자동으로 선택이 됩니다.

HttpEntity

HttpEntity는 HTTP 메시지의 헤더와 body를 캡슐화한 객체입니다. 요청과 응답 모두에서 사용할 수 있습니다.
View를 반환하지 않고 오직 데이터(header, body)만 다룹니다. Request Parameter와는 관련이 없습니다.

주요 메서드 및 생성자

  • getBody(): 바디 데이터 반환
  • getHeaders(): 헤더 데이터 반환
@PostMapping("request-body-text")
public HttpEneity<String> requestBodyText(RequestEntity<String> httpEntity) {
	String body = httpEntity.getBody();
    return new ResponseEntity<>("response = " + body, HttpStatus.CREATED);
}

ResponseEntity

ResponseEntity는 HttpEntity를 상속하고 응답에서만 사용할 수 있습니다.
HttpStatus를 명시적으로 선언할 수 있습니다.
body, header, HttpStatus 모두를 세밀하게 제어할 수 있습니다.

@GetMapping("/text")
public ResponseEntity<String> test() {
	return new ResponseEntity<>("Hello World!", HttpStatus.OK);
    // 또는 return ResponseEntity.ok("Hello World!");
}

@RequestBody

HTTP 요청의 body를 Java 객체, String, Map 등으로 자동 변환 시켜줍니다. 내부적으로 HttpMessageConverter가 작동해 JSON, XML, TEXT를 자바 객체로 deserialize합니다.

@ResponseBody

컨트롤러의 반환값을 HTTP 응답의 바디에 바로 넣어줍니다. View를 거치지 않으며 데이터만 응답합니다. 마찬가지로 HttpMessageConverter가 동작하여 객체, 문자열 등을 JSON, XML, TEXT 등으로 serialize합니다.

JSON 데이터와 @RestController

현대는 클라이언트와 서버가 대부분 JSON 형태로 데이터를 주고 받습니다. Spring에서는 @RestController를 사용하면 기본적으로 요청, 응답이 JSON으로 처리됩니다.

JSON -> Java (Deserialization)

1. HttpServletRequest + ObjectMapper

@Data
public class Tutor {
	private String name;
	private int age;
}

@RestController
public class JsonController {
	
	private ObjectMapper objectMapper = new ObjectMapper();

	@PostMapping("/request-body-json")
	public void requestBodyJsonV1(
				HttpServletRequest request, 
				HttpServletResponse response
	) throws IOException {

		ServletInputStream inputStream = request.getInputStream();
		// UTF-8 형식의 String으로 변환한다.
		String requestBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);

		// String requestBody를 ObjectMapper를 사용하여 변환
        // "{"name":"wonuk", "age":10}"
		Tutor tutor = objectMapper.readValue(requestBody, Tutor.class);
        
		response.getWriter().write("tutor" + tutor);
	}
}

ObjectMapper는 Deserialization 뿐만 아니라 Serialization도 가능합니다.

2. @RequestBody + ObjectMapper

@RestController
public class JsonController {
    @PostMapping("/request-body-json")
    public String requestBodyJsonV2(@RequestBody String requestBody) throws IOException {
        Tutor tutor = objectMapper.readValue(requestBody, Tutor.class);
        return "tutor.getName() = "
        	+ tutor.getName()
            + " tutor.getAge() = "
            + tutor.getAge();
    }
}

3. @RequestBody + 객체

@RestController
public class JsonController {
	@PostMapping("request-body-json")
    public String requestBodyJson(@RequestBody Tutor tutor) {
    	return "tutor = " + tutor;
    }
}

@RequestBody는 명시를 꼭 해야 합니다. 명시를 하지 않으면 @ModelAttribute로 작동하여 JSON이 아닌 폼 형태로 처리가 됩니다.

Java -> JSON (Serialization)

@ResponseBody or @RestController

@Controller
public classs JsonController {
	@ResponseBody
    @PostMapping("/request-body-json")
    public Tutor requestJson(@RequestBody Tutor tutor) {
    	return tutor; // JSON으로 변환이 되어 응답으로 넘어감
    }
}

HttpEntity<T>

@RestController
public class JsonController {
	@PostMapping("/request-body-json")
    public String requestBodyJson(HttpEntity<Tutor> httpEntity) {
    	Tutor tutor = httpEntity.getBody();
        return "tutor name = " + tutor.getName() + " tutor age = " + tutor.getAge();
    }
}

자료 및 코드 출처: 스파르타 코딩클럽

0개의 댓글