본문 바로가기
Spring

스프링 MVC1편 - 스프링MVC 기본 기능(3)

by KongJiHoon 2026. 2. 1.
 

✅ HTTP 응답 처리

Spring MVC에서 서버가 클라이언트에게 응답을 만드는 방식은 크게 세 가지로 구분된다.

  1. 정적 리소스 응답
  2. 뷰 템플릿 응답
  3. 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는 다음 두 가지 핵심 기능을 담당한다.

  1. 컨트롤러 파라미터 처리
  2. 컨트롤러 반환값 처리

이를 위해 내부적으로 다음 컴포넌트를 사용한다.

  • ArgumentResolver
  • ReturnValueHandler

 

2️⃣ ArgumentResolver

역할:

  • 컨트롤러 메서드가 요구하는 파라미터 객체 생성

  • HttpServletRequest
  • @RequestParam
  • @ModelAttribute
  • @RequestBody
  • HttpEntity

동작 방식

  1. supportsParameter()로 지원 여부 확인
  2. resolveArgument()로 실제 객체 생성
  3. 컨트롤러 호출 시 파라미터로 전달

 

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