@RestController의 요청/응답 처리 과정과 HTTPMessageConverter / 요청 처리 Annotation

양성준·2025년 4월 6일

스프링

목록 보기
26/49
post-thumbnail

RestController의 처리 과정

① 클라이언트가 HTTP 요청 전송

  • 브라우저, 모바일 앱, Postman 등이 서버에 HTTP 요청을 보냄
    예: GET /users/1, POST /login

② DispatcherServlet이 요청 수신

  • DispatcherServlet은 Spring MVC의 프론트 컨트롤러
  • 모든 HTTP 요청을 이 Servlet이 가장 먼저 받음
  • 이후 적절한 컨트롤러로 요청을 위임함 (HandlerMapping을 통해)

③ HandlerMapping이 실행되어 Handler(컨트롤러) 결정

  • 요청 URL과 메서드를 보고 어떤 컨트롤러 메서드(@GetMapping 등)를 실행할지 결정
    ex: /users/1 → UserController.getUserById()

④ HandlerAdapter가 실제 컨트롤러 호출을 준비

  • 단순히 Handler(=메서드)를 결정하는 것만으로는 실행이 불가능
  • Spring은 다양한 타입의 핸들러(예: @RestController, @Controller, @RequestMapping)를 실행할 수 있도록
    HandlerAdapter를 통해 호출 방식 및 파라미터 바인딩을 처리

⑤ HandlerAdapter가 실제 컨트롤러(@RestController) 메서드 실행

  • 개발자가 구현한 @RestController 메서드가 호출됨
  • 이 과정에서 @RequestBody, @PathVariable 등이 적용되어 필요한 값이 주입됨
    • 파라미터 바인딩을 하면서, @RequestBody가 있다면 HttpMessageConverter가 동작해서 요청 본문을 자바 객체로 변환
  • Service, Repository를 통해 비즈니스 로직 + DB 처리 수행 후,

⑥ 컨트롤러에서 ResponseEntity 또는 객체 반환

  • ResponseEntity 또는 일반 객체를 반환함
    예: return new ResponseEntity<>(user, HttpStatus.OK);
    또는 그냥 return user;

⑦ HttpMessageConverter가 자바 객체를 JSON 등으로 변환

  • 이 시점이 바로 HTTP 메시지 컨버터가 동작하는 순간!
  • 컨트롤러가 반환한 객체를 HTTP 응답으로 보내기 위해, HttpMessageConverter가 작동하여
    자바 객체 → JSON (또는 XML 등) 문자열로 변환

⑧ DispatcherServlet이 HTTP 응답을 클라이언트에게 반환

  • 최종적으로 JSON 데이터와 함께 200 OK, 404 Not Found 등의 상태 코드를 포함해
    클라이언트에게 응답이 전송됨

HTTPMessageConverter

"Spring MVC에서 HTTP 요청/응답의 바디(body)를 자바 객체 ↔ JSON, XML, 문자열 등으로 변환해주는 인터페이스"

  1. 요청(@RequestBody) → 자바 객체
  2. 자바 객체 → 응답(@ResponseBody, @RestController)

요청

  • 요청에서는 @RequestBody와 @RequestPart를 사용할 때만 HttpMessageConverter가 작동함
    • HTTP 메시지 바디를 변환하는 컴포넌트기 때문에, 요청의 Body를 다룰 때만 동작
    • 쿼리 파라미터나, URL같은 바디가 없는 데이터를 처리할 땐 동작 X
  • 즉, 요청 데이터가 HTTP 메시지 바디에 담겨있다면, 이를 자바 객체로 매핑하기 위해 @RequestBody가 꼭 필요함
    • 이 때, Spring은 요청의 Content-Type 헤더를 보고 등록된 메시지 컨버터들 중, 해당 타입을 처리할 수 있는 컨버터를 자동 선택하여 자바 객체로 매핑
      • text/plain인 경우, StringHttpMessageConverter 사용 (평문을 자바의 String 객체로 변환)
      • application/xml인 경우, MappingJackson2XmlHttpMessageConverter 사용
      • application/json인 경우, MappingJackson2HttpMessageConverter 사용
    • form-data의 경우에도 HTTP 메시지 바디에 포함되지만, Spring은 이를 쿼리스트링처럼 key-value 구조의 요청 파라미터처럼 인식하기 때문에,
      별도의 HttpMessageConverter 없이, 내부 바인딩 처리기(WebDataBinder 등)를 통해 자바 객체로 자동 매핑한다.
      (@RequestParam, @ModelAttribute 사용)
    • 하지만, HTTP 메시지 바디에 있기 떄문에 @RequestBody로 기술적으로는 받을 수 있긴하다.. (Converter도 있지만, 거의 안씀)

요청 처리 Annotation

"@RequestBody는 HTTP 요청 바디(body)의 데이터를 자바 객체로 변환해 달라는 Spring에게의 명확한 신호다."

  • 즉, 요청 데이터가 쿼리 파라미터가 아니라 HTTP 바디에 담겨 있는 경우, Spring은 @RequestBody가 존재할 때만 해당 데이터를 처리하며,
    이때 HttpMessageConverter를 사용해 요청 본문을 자바 객체로 변환한다.
  • 단, multipart/form-data나 application/x-www-form-urlencoded는 예외적으로 처리되며, 이러한 HTTP 메시지 바디 요청은 key-value 구조의 요청 파라미터로 인식되어, Spring 내부 바인딩 처리기를 통해 다음과 같은 방식으로 매핑된다:
    • @RequestParam → 단일 파라미터를 하나씩 바인딩, form 데이터나 쿼리 스트링 처리 ex) String username
    • @ModelAttribute → 여러 파라미터를 묶은 객체, 쿼리스트링(비바디)이나 form 데이터(key-value)를 자바 복합 필드 객체로 자동 바인딩 ex) User user
      • 위에서 언급했듯, form-data는 HTTP 메시지 바디에 포함되긴 하지만, 예외적으로 요청 파라미터 key-value로 인식하여 HTTPMessageConverter없이
        Spring 내부 바인딩 처리기를 통해 객체로 매핑
    • @RequestPart → multipart/form-data 안에 JSON 같은 구조화된 데이터가 포함된 경우 JSON과 파일 데이터를 나눠서 받음
      • 이 경우 JSON이 포함되어 있기 떄문에 HttpMessageConverter 작동
      • 파일 데이터의 경우에는 MultipartResolver가 요청을 파싱하여 자바의 MultipartFile 객체로 자동 바인딩
	  // HTTPMessageConverter가 JSON을 객체로 변환
      @RequestPart("request") RequestDTO requestDTO, 
      // MultipartResolver가 자바의 MultipartFile 객체로 자동 바인딩
      @RequestPart(value = "attachments", required = false) List<MultipartFile> multipartFileList) { 

Annotation 정리

  • multipart/form-data나 application/x-www-form-urlencoded 같은 form 데이터는:
    • @RequestParam → 파라미터 당 단일 값으로 받고싶을 때 (텍스트, 파일 등) / 한 요청에 여러 파라미터가 들어오면 여러 개 쓰면 됨
      • @RequestParam String username, @RequestParam String password
    • @ModelAttribute → 여러 파라미터를 자바 객체로 묶어받고 싶을 때
      • @ModelAttribute User user (useranme과 password가 포함된 User 객체)
    • @RequestPart → multipart 안의 JSON + 파일을 각각 처리할 때
  • JSON, XML, text/plain 등 구조화된 HTTP body 데이터는:
    • @RequestBody로 받아서 Content-Type 헤더에 따라 HttpMessageConverter를 통해 자바 객체로 변환

응답

  • 응답에서는 @ResponseBody나 @RestController가 붙어있어야만 HttpMessageConverter가 작동
  • @ResponseBody가 붙어있다면, Spring Boot는 기본적으로 응답에서 JSON 컨버터 Jackson을 사용 (MappingJackson2HttpMessageConverter)
    • 반환 타입 + 클라이언트의 Accept 헤더를 참고하여, 컨버터를 결정 (XML, 문자 등)
    • 별도로 명시해주지 않으면 기본적으로 객체를 JSON으로 변환

ModelAttribute vs RequestBody

@ModelAttribute

  • 쿼리 스트링 (?name=abc&age=30) 이나
    폼 데이터 (application/x-www-form-urlencoded) 로 넘어오는 값을
    객체에 자동으로 바인딩할 때 사용
  • ex) /users?name=Tom&age=20 → User(name=Tom, age=20)

@RequestBody

  • 요청의 body 에 JSON 같은 데이터가 담겨 있을 때 사용
  • 예를 들어, 클라이언트가 { "name": "Tom", "age": 20 } 이런 JSON을 body에 담아 보내는 경우 그걸 객체로 매핑!
profile
백엔드 개발자

0개의 댓글