@RequestBody로 String 타입을 받는 경우

wisdom·2022년 7월 25일
1

트러블슈팅

목록 보기
1/12

Troubleshooting

발생한 문제

@PostMapping("{id}")
    public boolean checkPassword(@RequestBody String password, @PathVariable long id) {
        System.out.println("password = " + password);
        return blogService.checkPassword(id, password);
    }

요청

결과

  • 위 json 데이터를 요청 보내면 코드 상으로 password 값에 pw가 String 타입으로 있을 거라고 기대했지만 josn 형태로 그대로 들어가있다.

해결 과정

  • 보통 아래의 코드처럼 User 객체를 json 형태로 보냈을 때 user.getName() 의 반환값으로 "wisdom" 이 String 타입으로 들어가있다. @RequestBody 가 내부적으로 바꿔준다 라는 것만 알고 있었는데 @RequestBody 어노테이션이 어떻게 동작하는지 원리를 파악할 필요가 있다고 느꼈다.
{
 "name": "wisdom", 
 "email": "wisdom@gmail.com"
}
// request body에 json 데이터를 보낸다.
@RequestBody User user 

@RequestBody

  • 구글링을 하다보면 @RequestBody의 정의로 클라이언트가 전송하는 Json(application/json) 형태의 HTTP Body를 Java 객체로 변환시켜주는 역할을 한다라고 적혀있는 경우가 많다. 맞는 말이기도 하지만 너무 한정적인 정의라고 생각한다.
  • 먼저 @RequestBody 는 JSON 뿐만 아니라 plain text, xml 등 다양한 포맷을 내부적으로 다룬다.

@RequestBody 동작 순서

  1. HTTP Clients 가 request body에 데이터를 담아 request 를 보낸다.
  2. 컨트롤러 메서드에 @RequestBody 어노테이션이 명시되어 있으면 해당 어노테이션이 스프링에게 request body에 담긴 데이터를 도메인 객체로 역직렬화 처리 하라고 알려준다.
    • 추가적으로 자바 Map 으로도 역직렬화 처리를 해준다.

@RequestBody 정리

  • 스프링 컨트롤러의 핸들러 메서드에서 사용하는 어노테이션이다.
  • 해당 어노테이션이 나타내는 것은 스프링에서는 request body를 객체로 deserialize 해줘야 한다는 것이다.
  • 그리고 그 변환된 객체가 핸들러 메서드의 파라미터로 전달된다.
  • 내부적으로 역직렬화는 많은 구현체 중의 하나인 MessageConverter 가 담당한다.
    • 서버로 들어오는 데이터를 오브젝트로 가공하거나 비즈니스단에서 처리된 오브젝트를 http 메시지로 변환하는 역할을 담당한다.

@RequestBody 어노테이션을 사용하면 request body를 도메인 객체가 아닌 자바 Map 으로도 역직렬화할 수 있다.

 public boolean checkPassword(@RequestBody Map<String, String> passwordMap, @PathVariable long id) {}
  • 위 코드처럼 컨트롤러 메서드 파라미터에 @RequestBody 어노테이션을 명시하고 파라미터의 형태를 Map<String, String> 형태로 전달하면 내부적으로는 HttpMessageConverter 처리해준다.

해결

 @PostMapping("{id}")
    public boolean checkPassword(@RequestBody Map<String, String> passwordMap, @PathVariable long id) {
        System.out.println("stringMap.get(\"password\")" + passwordMap.get("password"));
        return blogService.checkPassword(id, "pw");
    }
  • 위와 같이 Map<String, String> 형태로 받아서 get 메서드로 password 값을 가져왔다.

회고

  • 어노테이션 하나로 스프링 내부적으로 정말 바쁘게 움직이는 거 같다. 다음에 기회가 되면 역직렬화에 대해서도 공부해보고 싶고 MessageConverter 에 대해서도 자세히 분석을 해봐야겠다.
profile
문제를 정의하고, 문제를 해결하는

0개의 댓글