Written by
Sunwoo Han
on
on
스프링 MVC 기본 기능 - HTTP 응답
스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술을 공부하고 정리하는 포스트입니다.
HTTP 응답
종류
- HTTP Response로 서버에서 클라이언트로 제공하는 데이터를 만드는 방법은 3가지.
- 정적 리소스 : 웹 브라우저에 정적인 HTML / CSS / JS 을 제공
- 뷰 템플릿 : 웹 브라우저에 동적인 HTML을 제공하는 뷰 템플릿
- HTTP 메시지 사용 : HTTP Response Message Body에 JSON과 같은 형식으로 데이터를 실어 보냄
정적 리소스
- 스프링 부트의 클래스 패스(classpath)
/static
/public
/resources
/META-INF/resources
/src/main/resources
는 리소스를 보관하는 곳이며, 클래스 패스의 시작경로- ex)
src/main/resources/static/basic/hello-form.html
이 있을 때 ->http://localhost:8080/basic/hello-form.html
로 접근 가능 -> 정적 리소스는 해당 파일을 변경 없이 그대로 서비스 하는 것
- ex)
뷰 템플릿
V3
는 명시성이 떨어지고 딱 맞는 경우가 많이 없어서 권장하지 않음.- JSP / 타임리프 / 머스태치 등 다양한 뷰 템플릿을 동적으로 만들어서 사용자에게 제공
- 스프링 부트는 기본 뷰 템플릿 경로를 제공 -> /src/main/resources/templates
- Spring에서는 타임리프 템플릿 엔진을 기본적으로 권장함!
application.properties
에 prefix / suffix 설정 가능
/* 기본적으로 들어가 있는 설정이다. 타임리프가 템플릿 엔진 사용시 변경하면 된다. */
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
HTTP 메시지 사용
responseBodyV1
- 서블릿을 직접 다룰 때처럼
HttpServletResponse
객체를 통해서 HTTP 메시지 바디에 직접 “ok” 응답 메시지를 전달
- 서블릿을 직접 다룰 때처럼
responseBodyV2
ResponseEntity
는 HttpEntity를 상속, HTTP Status Code를 직접 설정할 수 있음
responseBodyV3
@ResponseBody
를 통해 응답 메시지 자체로 데이터를 받게 설정
responseBodyJsonV1
ResponseEntity
를 반환, HTTP 메시지 컨버터를 통해서 JSON 형식으로 변환되어서 반환.
responseBodyJsonV2
- ResponseEntity를 사용하면 Status Code를 직접 설정 할 수 있으며, 그렇지 않으면 @ResponseStatus 어노테이션으로 지정할 수도 있음.
- 실무에서는 Entity를 직접 반환하지 않고 무조건 DTO를 통해 HTTP response를 반환함!
- 응답 메시지를 처리하는 과정에서도 HTTP 메시지 컨버터가 사용됨.
HTTP 메시지 컨버터
역할
HTTP response
로 뷰가 아닌 데이터를 담아서 보내는 경우viewResolver
대신HttpMessageConventer
가 동작 (다양한 종류의 컨버터가 존재함)- 기본 문자 ->
StringHttpMessageConverter
가 처리 - 기본 객체 ->
MappingJackson2HttpMessageConverter
가 처리
- HTTP request가 오거나 HTTP response로 데이터를 body에 담아서 보낼 때 -> 스프링이 모든 메시지 내용을 알맞게 변환 -> 이러한 역할을 해주는 것이 바로 HTTP 메시지 컨버터
사용 원리
- 스프링 MVC는 다음의 경우에 HTTP 메시지 컨버터를 적용 : 메시지 컨버터가 필요한 경우 ->
Http request Body
에 데이터가 있는 경우- HTTP 요청 :
@RequestBody
/HttpEntity(RequestEntity)
- HTTP 응답 :
@ResponseBody
/HttpEntity(ResponseEntity)
- HTTP 요청 :
- HTTP 메세지 컨버터 인터페이스
canRead()
/canWrite()
-> 메시지 컨버터가 해당 클래스, 미디어타입을 지원하는지 체크read()
/write()
-> 메시지 컨버터를 통해서 메시지를 읽고 쓰는 기능
주요한 메시지 컨버터
ByteArrayHttpMessageConverter
: byte[] 데이터를 처리한다.- 클래스 타입 : byte[], 미디어타입 :
*/*
- 요청 예)
@RequestBody byte[] data
- 응답 예)
@ResponseBody return byte[]
쓰기 미디어타입application/octet-stream
- 클래스 타입 : byte[], 미디어타입 :
StringHttpMessageConverter
: String 문자로 데이터를 처리한다.- 클래스 타입: String, 미디어타입 :
*/*
- 요청 예)
@RequestBody String data
- 응답 예)
@ResponseBody return "ok"
쓰기 미디어타입text/plain
- 클래스 타입: String, 미디어타입 :
MappingJackson2HttpMessageConverter
: application/json- 클래스 타입: 객체 또는 HashMap, 미디어타입 :
application/json
관련 - 요청 예)
@RequestBody HelloData data
- 응답 예)
@ResponseBody return helloData
쓰기 미디어타입application/json
관련
- 클래스 타입: 객체 또는 HashMap, 미디어타입 :
HTTP 요청 데이터 읽기
- HTTP 요청 흐름
- HTTP Request 요청
- Controller에서
@RequestBody
혹은HttpEntity 파라미터
를 사용 - 메시지 컨버터가 메시지를 읽을 수 있는지 확인하기 위해
canRead()
를 호출-
- 대상 클래스 타입 확인
- ex)
@RequestBody
로 받은 대상 클래스 타입(byte[] / String 등등)
-
- HTTP request의 Conent-Type에 해당하는 미디어 타입을 지원하는지 확인
- ex)
text/plain
,application/json
등등
-
canRead()
를 만족하면read()
를 호출해서 객체를 읽어서 우리가 쓸 수 있도록 생성하고 반환
HTTP 응답 데이터 생성
- HTTP 응답 흐름
- Controller에서
@ResponseBody
/HttpEntity
로 값이 반환 - 메시지 컨버터가 메시지를 쓸 수 있는지 확인하기 위해
canWrite()
를 호출- 대상 클래스 타입 확인
- HTTP request의 Accept에 해당하는 미디어 타입을 지원하는지 확인
canWrite()
을 만족하면write()
를 호출해서 HTTP Response Body에 데이터 생성
- Controller에서
Argument Resolver & ReturnValue Handler
- 스프링 MVC에서 HTTP 메시지 컨버터가 사용되는 위치는?
- 핸들러 어댑터를 통해 실제 핸들러(컨트롤러)를 호출하는 과정을 알아야 함.
- 애노테이션 기반의 컨트롤러, 즉
@RequestMapping
을 처리하는 핸들러 어댑터RequestMappingHandlerAdapter
(요청 매핑 핸들러 어댑터)
- 애노테이션 기반의 컨트롤러는 굉장히 많은 종류의 파라미터를 사용함 (
HttpServletRequest
/Model
/@RequestParam
/@ModelAttribute
등) - 이렇게 유연하게 파라미터를 처리할 수 있는 이유가 바로
ArgumentResolver
!
Argument Resolver
- 정확히는
HandlerMethodArgumentResolver
인데 줄여서ArgumentResolver
라고 함. - 유연하게 다양한 파라미터를 처리하기 위한 것
- 핸들러 어댑터는
Argument Resolver
를 호출해서 미리 들어갈 매개변수를 파악 & 생성 -
스프링은 30개가 넘는 ArgumentResolver를 기본으로 제공
- 동작 원리
- 핸들러 어댑터가
Argument Resolver
를 호출 Argument Resolver
는 내부에supportsParameter()
를 호출하며 어떤 파라미터를 지원하는지 확인- 지원하는 파라미터를 찾은 뒤
resolveArgument()
를 호출해서 실제 객체를 생성 (실제 객체를 생성할 때 HTTP 메서드 컨버터를 통해 메시지를 변환하여 사용)
- 핸들러 어댑터가
ReturnValue Handler
HandlerMethodReturnValueHandler
를 줄여서ReturnValueHandler
라 부름ArgumentResolver
와 비슷, 이것은 응답 값을 변환하고 처리- 컨트롤러에 String으로 뷰 이름을 반환해서 동작하는 이유
- 스프링은 10개가 넘는
ReturnValueHandler
를 지원
HTTP 메시지 컨버터
ArgumentResolver
/ReturnValueHandler
가 대응되는 파라미터와 반환값을 만들어주는 과정에서 HTTP 메시지 컨버터를 호출해서 사용- 요청 :
@RequestBody
를 처리하는ArgumentResolver
가 있고,HttpEntity
를 처리하는ArgumentResolver
가 있음. 이ArgumentResolver
들이 HTTP 메시지 컨버터를 사용해서 필요한 객체를 생성. - 응답 :
@ResponseBody
와HttpEntity
를 처리하는ReturnValueHandler
가 있음. 여기에서 HTTP 메시지 컨버터를 호출해서 응답 결과를 생성.
- 요청 :
- 스프링은
ArgumentResolver
/ReturnValueHandler
/HttpMessageConverter
모두 인터페이스로 제공- 실제 확장이 필요할 때 이러한 내부 원리를 알고있어야 확장 포인트를 알 수 있음!
Comments
SPRING 의 다른 글
-
스프링 타입 컨터버 24 Jun 2022
-
API 예외 처리 17 Jun 2022
-
예외 처리와 오류 페이지 12 Jun 2022
-
로그인 처리 - 인터셉터 08 Jun 2022
-
로그인 처리 - 필터 06 Jun 2022
-
로그인 처리 - 쿠키, 세션 31 May 2022
-
Bean Validation 22 May 2022
-
검증 22 May 2022
-
메시지, 국제화 21 May 2022
-
타임리프 - 스프링 통합과 폼 19 May 2022
-
타임리프 - 기본 기능 10 May 2022
-
스프링 MVC 기본 기능 - 웹 페이지 만들기 02 May 2022
-
스프링 MVC 기본 기능 - HTTP 응답 30 Apr 2022
-
스프링 MVC 기본 기능 - HTTP 요청 24 Apr 2022
-
스프링 MVC 기본 기능 - 요청 매핑 19 Apr 2022
-
스프링 MVC 기본 기능 19 Apr 2022
-
스프링 MVC 구조 이해 14 Apr 2022
-
MVC 프레임워크 만들기 - V4, V5 12 Apr 2022
-
MVC 프레임워크 만들기 - V1, V2, V3 09 Apr 2022
-
서블릿, JSP, MVC 패턴 05 Apr 2022
-
서블릿 29 Mar 2022
-
웹 애플리케이션 이해 24 Mar 2022
-
스프링 웹 계층이란? 05 Nov 2021
-
스프링 시큐리티 공식문서 번역 27 Sep 2021
-
스프링 AOP 총정리 : 개념, 프록시 기반 AOP, @AOP 27 Apr 2021
-
SpEL (스프링 Expression Language) 25 Apr 2021
-
데이터 바인딩 추상화 : Converter와 Formatter 21 Apr 2021
-
데이터 바인딩 추상화 : PropertyEditor 12 Apr 2021
-
Validation 추상화 10 Apr 2021
-
Resource 추상화 08 Apr 2021
-
IoC 컨테이너 9부 07 Apr 2021
-
IoC 컨테이너 8부 06 Apr 2021
-
IoC 컨테이너 7부 02 Apr 2021
-
IoC 컨테이너 6부 29 Mar 2021
-
IoC 컨테이너 5부 27 Mar 2021
-
IoC 컨테이너 4부 23 Mar 2021
-
IoC 컨테이너 3부 20 Mar 2021
-
IoC 컨테이너 2부 18 Mar 2021
-
IoC 컨테이너 1부 12 Mar 2021
-
스프링 PSA 07 Jan 2021
-
스프링 @AOP 실습 07 Jan 2021
-
프록시 패턴 06 Jan 2021
-
스프링 AOP 04 Jan 2021
-
의존성 주입(Dependency Injection) 04 Jan 2021
-
스프링 빈(Bean) 02 Jan 2021
-
스프링 IoC 컨테이너 01 Jan 2021
-
스프링 IoC 01 Jan 2021