본문 바로가기
Spring MVC

[MVC] 스프링 MVC - 기본 기능(4)

by 개발 Blog 2025. 3. 6.

공부 내용을 정리하고 앞으로의 학습에 이해를 돕기 위해 작성합니다.

 

HTTP 요청 메시지 - 단순 텍스트

HTTP 메시지 바디를 통한 데이터 전송

  • HTTP message body에 데이터를 직접 담아 요청
  • HTTP API에서 주로 사용 (JSON, XML, TEXT)
  • 데이터 형식은 주로 JSON 사용
  • POST, PUT, PATCH 메서드에서 활용
  • 요청 파라미터(@RequestParam, @ModelAttribute)와 다르게 HTTP 메시지 바디를 통해 데이터가 직접 전달됨

InputStream을 활용한 직접 읽기 - requestBodyStringV1

@Slf4j
@Controller
public class RequestBodyStringController {
    @PostMapping("/request-body-string-v1")
    public void requestBodyString(HttpServletRequest request,
                                  HttpServletResponse response) throws IOException {
        ServletInputStream inputStream = request.getInputStream();
        String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
        log.info("messageBody={}", messageBody);
        response.getWriter().write("ok");
    }
}
  • HttpServletRequest를 사용하여 HTTP 메시지 바디의 데이터를 읽음
  • StreamUtils.copyToString()을 이용하여 UTF-8 문자열로 변환

InputStream, OutputStream을 활용한 처리 - requestBodyStringV2

/**
* InputStream(Reader): HTTP 요청 메시지 바디의 내용을 직접 조회
* OutputStream(Writer): HTTP 응답 메시지의 바디에 직접 결과 출력
*/
@PostMapping("/request-body-string-v2")
public void requestBodyStringV2(InputStream inputStream, Writer responseWriter) throws IOException {
    String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
    log.info("messageBody={}", messageBody);
    responseWriter.write("ok");
}
  • InputStream을 직접 사용하여 요청 메시지 바디 읽기
  • Writer를 이용하여 응답 메시지 바디에 직접 결과 출력

HttpEntity 활용 - requestBodyStringV3

/**
* HttpEntity: HTTP header, body 정보를 편리하게 조회
* - 메시지 바디 정보를 직접 조회(@RequestParam X, @ModelAttribute X)
* - HttpMessageConverter 사용 -> StringHttpMessageConverter 적용
*/
@PostMapping("/request-body-string-v3")
public HttpEntity<String> requestBodyStringV3(HttpEntity<String> httpEntity) {
    String messageBody = httpEntity.getBody();
    log.info("messageBody={}", messageBody);
    return new HttpEntity<>("ok");
}
  • HttpEntity를 사용하여 HTTP 헤더 및 바디 정보 조회
  • 요청 파라미터와 관계없이 메시지 바디를 직접 조회 가능
  • 응답에도 HttpEntity를 사용할 수 있으며, 헤더 포함 가능

ResponseEntity, RequestEntity

  • RequestEntity: HttpMethod, URL 정보를 추가로 포함하며 요청에서 사용
  • ResponseEntity: HTTP 상태 코드 설정 가능, 응답에서 사용
  • 예제:
return new ResponseEntity<>("Hello World", responseHeaders, HttpStatus.CREATED);

 

@RequestBody 활용 - requestBodyStringV4

/**
* @RequestBody
* - 메시지 바디 정보를 직접 조회(@RequestParam X, @ModelAttribute X)
* - HttpMessageConverter 사용 -> StringHttpMessageConverter 적용
*/
@ResponseBody
@PostMapping("/request-body-string-v4")
public String requestBodyStringV4(@RequestBody String messageBody) {
    log.info("messageBody={}", messageBody);
    return "ok";
}
  • @RequestBody를 사용하여 HTTP 메시지 바디를 편리하게 조회
  • 요청 파라미터(@RequestParam, @ModelAttribute)와 관계없이 메시지 바디만 처리
  • HTTP 헤더 정보가 필요할 경우 HttpEntity 또는 @RequestHeader를 사용

@ResponseBody

  • @ResponseBody를 사용하면 응답 데이터를 HTTP 메시지 바디에 직접 전달
  • View를 사용하지 않음

요청 파라미터 vs HTTP 메시지 바디

기능 요청 파라미터 HTTP 메시지 바디
어노테이션 @RequestParam, @ModelAttribute @RequestBody
데이터 전달 방식 URL 쿼리 스트링, HTML Form HTTP 메시지 바디
데이터 형식 Key-Value JSON, XML, TEXT

 

참고: HttpMessageConverter

  • 스프링 MVC 내부에서 HTTP 메시지 바디를 읽고 변환하는 역할 수행
  • 문자 또는 객체로 변환하여 컨트롤러에 전달
  • StringHttpMessageConverter 적용됨

HTTP 요청 메시지 - JSON

JSON 데이터 처리 개요

  • HTTP API에서 주로 JSON 데이터를 사용하여 요청을 보냄
  • @RequestBody를 활용하여 JSON 데이터를 자바 객체로 변환 가능
  • Jackson 라이브러리(ObjectMapper)를 사용하여 JSON을 객체로 변환

HttpServletRequest를 활용한 JSON 처리 - requestBodyJsonV1

@Slf4j
@Controller
public class RequestBodyJsonController {
    private ObjectMapper objectMapper = new ObjectMapper();
    
    @PostMapping("/request-body-json-v1")
    public void requestBodyJsonV1(HttpServletRequest request, HttpServletResponse response) throws IOException {
        ServletInputStream inputStream = request.getInputStream();
        String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
        
        log.info("messageBody={}", messageBody);
        HelloData data = objectMapper.readValue(messageBody, HelloData.class);
        log.info("username={}, age={}", data.getUsername(), data.getAge());
        
        response.getWriter().write("ok");
    }
}
  • HttpServletRequest를 사용하여 HTTP 메시지 바디에서 데이터 직접 읽기
  • ObjectMapper를 활용하여 JSON 데이터를 자바 객체로 변환

@RequestBody를 활용한 JSON 처리 - requestBodyJsonV2

@ResponseBody
@PostMapping("/request-body-json-v2")
public String requestBodyJsonV2(@RequestBody String messageBody) throws IOException {
    HelloData data = objectMapper.readValue(messageBody, HelloData.class);
    log.info("username={}, age={}", data.getUsername(), data.getAge());
    return "ok";
}
  • @RequestBody를 활용하여 요청 메시지 바디를 문자열로 변환 후 처리
  • ObjectMapper를 사용하여 JSON 데이터를 객체로 변환

@RequestBody를 활용한 객체 변환 - requestBodyJsonV3

@ResponseBody
@PostMapping("/request-body-json-v3")
public String requestBodyJsonV3(@RequestBody HelloData data) {
    log.info("username={}, age={}", data.getUsername(), data.getAge());
    return "ok";
}
  • @RequestBody를 사용하여 JSON 데이터를 객체로 바로 변환
  • HTTP 메시지 컨버터(MappingJackson2HttpMessageConverter)가 자동으로 처리

@RequestBody 생략 불가능한 이유

  • @ModelAttribute@RequestParam이 생략되면 기본적으로 적용되는 규칙:
    • String, int, Integer 같은 단순 타입 → @RequestParam 적용
    • 나머지 객체 → @ModelAttribute 적용
  • @RequestBody를 생략하면 @ModelAttribute가 적용되어 요청 파라미터로 처리됨

HttpEntity를 활용한 JSON 처리 - requestBodyJsonV4

@ResponseBody
@PostMapping("/request-body-json-v4")
public String requestBodyJsonV4(HttpEntity<HelloData> httpEntity) {
    HelloData data = httpEntity.getBody();
    log.info("username={}, age={}", data.getUsername(), data.getAge());
    return "ok";
}
  • HttpEntity를 활용하여 요청 본문을 직접 조회하고 JSON 데이터를 객체로 변환
  • HTTP 메시지 컨버터를 통해 자동 변환

JSON 데이터 응답 처리 - requestBodyJsonV5

@ResponseBody
@PostMapping("/request-body-json-v5")
public HelloData requestBodyJsonV5(@RequestBody HelloData data) {
    log.info("username={}, age={}", data.getUsername(), data.getAge());
    return data;
}
  • @ResponseBody를 사용하여 JSON 데이터를 직접 응답으로 반환
  • HTTP 메시지 컨버터를 활용하여 객체를 JSON으로 변환 후 응답

요청과 응답의 JSON 변환 과정

요청 응답
@RequestBody 사용 @ResponseBody 사용
JSON → 객체 변환 객체 → JSON 변환
HttpMessageConverter 자동 적용 HttpMessageConverter 자동 적용

 

주의 사항

  • 요청 시 Content-Type: application/json을 반드시 설정해야 HTTP 메시지 컨버터가 JSON을 올바르게 처리함
  • @RequestBody는 생략 불가능 (생략 시 @ModelAttribute가 적용됨)
  • Jackson 라이브러리를 활용하여 JSON 데이터를 변환 (Spring Boot 기본 내장)

HTTP 응답 - 정적 리소스, 뷰 템플릿

스프링에서 응답 데이터를 만드는 방법

  1. 정적 리소스: HTML, CSS, JS 같은 정적인 리소스를 제공할 때 사용
  2. 뷰 템플릿: 동적인 HTML을 생성할 때 사용
  3. HTTP 메시지: API 응답(JSON 등)을 보낼 때 사용

정적 리소스 제공

  • 스프링 부트는 /static, /public, /resources, /META-INF/resources 디렉토리에 있는 정적 리소스를 자동 제공
  • 기본 정적 리소스 경로: src/main/resources/static
  • 예제:
    • src/main/resources/static/basic/hello-form.html
    • http://localhost:8080/basic/hello-form.html로 접근 가능

뷰 템플릿을 사용한 응답 처리

  • 동적인 HTML을 생성하여 응답
  • 기본 뷰 템플릿 경로: src/main/resources/templates

뷰 템플릿 생성

src/main/resources/templates/response/hello.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <p th:text="${data}">empty</p>
</body>
</html>

 

뷰 템플릿을 호출하는 컨트롤러

@Controller
public class ResponseViewController {
    @RequestMapping("/response-view-v1")
    public ModelAndView responseViewV1() {
        ModelAndView mav = new ModelAndView("response/hello")
                .addObject("data", "hello!");
        return mav;
    }
    
    @RequestMapping("/response-view-v2")
    public String responseViewV2(Model model) {
        model.addAttribute("data", "hello!!");
        return "response/hello";
    }
    
    @RequestMapping("/response/hello")
    public void responseViewV3(Model model) {
        model.addAttribute("data", "hello!!");
    }
}

 

컨트롤러에서 뷰 반환 방식

  • String을 반환하는 경우: @ResponseBody가 없으면 뷰 리졸버를 통해 템플릿이 렌더링 됨
  • void를 반환하는 경우: 요청 URL을 기반으로 뷰 이름이 결정됨 (/response/hellotemplates/response/hello.html 실행)
    • 명시성이 부족하여 권장하지 않음

HTTP 메시지를 직접 응답하는 경우

  • @ResponseBody 또는 HttpEntity를 사용하면 뷰 템플릿 없이 HTTP 메시지 바디에 직접 데이터 출력 가능

Thymeleaf 설정

  • build.gradle에 다음 라이브러리 포함 (Spring Boot 기본 포함됨)
  • implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
  • 기본 설정 (변경 필요시 설정 가능)
  • spring.thymeleaf.prefix=classpath:/templates/ spring.thymeleaf.suffix=.html

참고