✅ HTTP 응답 처리
Spring MVC에서 서버가 클라이언트에게 응답을 만드는 방식은 크게 세 가지로 구분된다.
- 정적 리소스 응답
- 뷰 템플릿 응답
- HTTP 메시지 바디 직접 응답 (HTTP API)
이 세 방식은 DispatcherServlet 이후의 처리 흐름이 서로 다르다.
1️⃣ 정적 리소스 응답(Static Resource)
- 정적 리소스란 서버에서 가공하지 않고 그대로 제공되는 파일을 의미한다.
- HTML
- CSS
- Javascript
- 이미지 파일 등
컨트롤러를 거치지 않으며, 파일 내용이 그대로 HTTP응답 바디에 담긴다.
1. SpringBoot의 정적 리소스 기본 경로
Spring Boot는 다음 경로를 정적 리소스 경로로 자동 등록한다.
/static
/public
/resources
/META-INF/resources
실제 위치:
src/main/resources/static
예시:
src/main/resources/static/basic/hello-form.html
요청:
GET /basic/hello-form.html
👉 처리 흐름
- 클라이언트 요청
- DispatcherServlet
- 정적 리소스 핸들러(ResourceHttpRequestHandler)
- 파일을 그대로 응답 바디에 작성
특징
- 컨트롤러 불필요
- ViewResolver 미사용
- HttpMessageConverter 미사용
- 가장 단순하고 빠른 응답 방식
2️⃣ 뷰 템플릿 응답(View Template)
- 뷰 템플릿 방식은 서버에서 HTML을 동적으로 생성하여 응답하는 방식이다.
- 서버가 데이터(Model)을 전달
- 뷰 템플릿 엔진이 HTML을 생성
- 생성된 HTML이 HTTP 응답 바디에 담김
1. SpringBoot의 기본 뷰 템플릿 설정
Spring Boot + Thymeleaf 기준:
뷰 템플릿 경로
src/main/resources/templates
접두사(prefix)
classpath:/templates/
접미사(suffix)
.html
2. 컨트롤러 반환 방식
hello.html
<!doctype html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<p th:text="${data}">empty</p>
</body>
</html>
ResponseViewController
package hello.springmvc.basic.response;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class ResponseViewController {
@RequestMapping("/response-view-v1")
public ModelAndView responseViewV1() {
ModelAndView modelAndView = new ModelAndView("response/hello");
modelAndView.addObject("data", "hello!");
return modelAndView;
}
@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!");
}
}
3. 컨트롤러 반환 방식
1) ModelAndView 반환
return new ModelAndView("response/hello")
.addObject("data", "hello");
2) String 반환 + Model 사용
model.addAttribute("data", "hello");
return "response/hello";
❓@ResponseBody와의 차이
- @ResponseBody 없음
- 반환값 → 뷰 이름
- ViewResolver 실행
- @ResponseBody 있음
- 반환값 → HTTP 응답 바디
- ViewResolver 실행 안 함
3️⃣ HTTP 메시지 바디 직접 응답(HTTP API)
- HTML이 아닌 데이터(JSON, 문자열)를 직접 응답 바디에 작성하는 방식이다.
- REST API
- 비동기 통신
- 모바일 / 프론트엔드 연동
ResponseBodyController
package hello.springmvc.basic.response;
import hello.springmvc.basic.HelloData;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Slf4j
@Controller
public class ResponseBodyController {
@GetMapping("/response-body-string-v1")
public void responseBodyV1(HttpServletResponse response) throws IOException {
response.getWriter().write("ok");
}
@GetMapping("/response-body-string-v2")
public ResponseEntity<String> responseBodyV2() {
return new ResponseEntity<>("ok", HttpStatus.OK);
}
@GetMapping("/response-body-string-v3")
@ResponseBody
public String responseBodyV3() {
return "ok";
}
@GetMapping("/response-body-json-v1")
public ResponseEntity<HelloData> responseBodyJsonV1() {
HelloData helloData = new HelloData();
helloData.setUsername("userA");
helloData.setAge(20);
return ResponseEntity.status(HttpStatus.OK).body(helloData);
}
@ResponseStatus(HttpStatus.OK)
@GetMapping("/response-body-json-v2")
@ResponseBody
public HelloData responseBodyJsonV2() {
HelloData helloData = new HelloData();
helloData.setUsername("userA");
helloData.setAge(20);
return helloData;
}
}
1. 사용 방법
1) HttpServletResponse 직접 사용
response.getWriter().write("ok");
2) HttpEntity / ResponseEntity
return new ResponseEntity<>("ok", HttpStatus.OK);
- ResponseEntity는 HTTP 응답 코드를 설정할 수 있다.
- @ResponseStatus 애노테이션 사용 시 응답 코드 설정 가능. 하지만 애노테이션이기 때문에 응답코드를 동적으로 변경할 수는 없다.
- 프로그램 조건에 따라서 동적으로 변경하려면 ResponseEntity를 사용하면 된다.
3) @ReponseBody
@ResponseBody
return "ok";
4) JSON 응답
@ResponseBody
return helloData;
- 객체 -> JSON 자동 변환
- HttpMessageConverter 사용
5) @RestController
@Controller + @ResponseBody
- 모든 메서드의 반환값을 HTTP 응답 바디로 처리
- ViewResolver 사용 안 함
- HTTP API 전용 컨트롤러
✅ 응답 처리와 HttpMessageConverter
1️⃣ HttpMessageConverter의 역할
- Java 객체 ↔ HTTP 메시지 바디 변환
- 요청과 응답 양쪽 모두에서 사용됨
2️⃣ 응답 시 동작 조건
HttpMessageConverter는 다음 경우에 사용된다.
- @ResponseBody
- HttpEntity / ResponseEntity 반환
3️⃣ 응답 시 선택 기준
- 컨트롤러 반환 타입
- 클라이언트 Accept 헤더
- @RequestMapping의 produces 조건
✅ 요청 매핑 핸들러 어댑터 구조

Spring MVC의 핵심 구조
Client
→ DispatcherServlet
→ HandlerMapping
→ HandlerAdapter
→ Controller
👉 애노테이션 기반 컨트롤러(@RequestMapping)를 처리하는 어댑터는 아래와 같다.
RequestMappingHandlerAdapter
1️⃣ HandlerAdapter의 역할
HandlerAdapter는 다음 두 가지 핵심 기능을 담당한다.
- 컨트롤러 파라미터 처리
- 컨트롤러 반환값 처리
이를 위해 내부적으로 다음 컴포넌트를 사용한다.
- ArgumentResolver
- ReturnValueHandler
2️⃣ ArgumentResolver
역할:
- 컨트롤러 메서드가 요구하는 파라미터 객체 생성
예
- HttpServletRequest
- @RequestParam
- @ModelAttribute
- @RequestBody
- HttpEntity
동작 방식
- supportsParameter()로 지원 여부 확인
- resolveArgument()로 실제 객체 생성
- 컨트롤러 호출 시 파라미터로 전달
3️⃣ ReturnValueHandler
- ArgumentResolver 내부에서 요청 바디 처리 시 사용
- ReturnValueHandler 내부에서 응답 바디 처리 시 사용
즉, HandlerAdapter 내부에서 사용된다.
출처 : https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1/dashboard?cid=326674
스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술| 김영한 - 인프런 강의
현재 평점 5.0점 수강생 30,211명인 강의를 만나보세요. 웹 애플리케이션을 개발할 때 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. 스프링 MVC의 핵심 원리와 구조를 이해하고,
www.inflearn.com
'Spring' 카테고리의 다른 글
| 스프링 MVC 2편 - 타임리프 기본기능(1) (0) | 2026.02.18 |
|---|---|
| 스프링 MVC1편 - 스프링MVC 기본 기능(2) (1) | 2026.01.31 |
| 스프링 MVC1편 - 스프링MVC 기본 기능(1) (0) | 2026.01.21 |
| 스프링 MVC1편 - 스프링 MVC 구조이해(2) (0) | 2026.01.11 |
| 스프링 MVC1편 - 스프링 MVC 구조이해(1) (0) | 2026.01.11 |