You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@ControllerpublicclassResponseViewController {
@RequestMapping("/response-view1")
publicModelAndViewresponseViewV1() {
ModelAndViewmav = newModelAndView("response/hello")
.addObject("data", "hello!"); // 위 타임리프의 data 부분에 hello! 가 출력returnmav;
}
// 여기 만약 @ResponseBody 가 있으면 뷰를 찾지 않고 그냥 내용 출력@RequestMapping("/response-view2")
publicStringresponseViewV2(Modelmodel) {
model.addAttribute("data", "hello2!");
return"response/hello"; // 뷰의 논리적 이름!
}
@RequestMapping("/response/hello") // 컨트롤러의 맵핑 이름과, 뷰의 논리 이름이 같으면 반환값이 없어도 스프링이 알아서 해줌publicvoidresponseViewV3(Modelmodel) {
model.addAttribute("data", "hello2!");
}
}
String 을 반환하는 경우
View @responsebody 가 없으면 반환한 스트링으로("response/hello") 뷰 리졸버가 실행, 뷰를 찾고 렌더링함
논리 이름을 templates/response/hello.html 로 바꿔서 진행
HTTP 메시지
@ResponseBosy 가 있으면 HTTP 메시지 바디에 직접 반환한 스트링 ("response/hello") 가 입력되어 응답
void 를 반환하는 경우 @controller 사용하고, HttpServletResponse, OutputStream 같은 HTTP 메시지 바디 처리 파라미터 없으면 요청 URL을 뷰 이름으로 사용
권장하지 않음!
Thymeleaf 스프링 부트 설정
build.gradle 에 타임리프 라이브러리를 추가하면,
스프링 부트가 자동으로 *ThymeleafViewResolver* + 관련된 필요한 스프링 빈 등록.
또, 기본 경로 및 확장자까지 application.properties에 설정해줌
반환의 형태에 대한부분은 위에 설명이 되었지만
객체를 반환했을 때 이걸 JSON 으로 변환이 어떻게 되는거지???
Http 메시지 컨버터
JSON 데이터를 HTTP 메시지 바디에 쓰는 경우 HTTP 메시지 컨버터를 사용하면 편리하다!
원래는 ServletInputStream + ObjectMapper 로 변환 후 response.getWriter().write() 로 직접 넣어줄 수 있는데
매우 불편, 이를 HttpMessageConverter 로 쉽게 가능!
스프링 기초 강의에 나왔던 ResponseBody 원리
@responsebody 가 있으면 HttpMessageConverter 가 동작함. (ViewResolver 대신)
컨트롤러가 리턴하는걸 받아 스트링 or JSON 을 선택해 응답 보냄
기본 문자 처리: StringHttpMessageConverter
기본 객체 처리: MappingJackson2HttpMessageConverter
byte 처리 : ByteArrayHttpMessageConverter
등 다양한 HttpMessageConverter가 등록되어 있음.
=> 다양한 메시지 컨버터 중 선택할 때 HTTP Accept 해더(응답) or 미디어 타입(요청), 컨트롤러의 반환 타입(응답) or 대상 클래스 타입(요청)을 조합해 어떤 HttpMessageConverter 를 선택할지 결정함.
** HTTP 메시지 컨버터 적용하는 경우 (요청, 응답 둘다 사용)
요청: @RequestBody, HttpEntity(RequestEntity) (응답의 데이터를 읽어 객체로 바꿔 컨트롤러의 파라미터로 넣어줌)
응답: @responsebody, HttpEntity(ResponseEntity) (컨트롤러 리턴값을 읽어 HTTP 응답 메시지 만듦)
HTTP 메시지 컨버터는 양방향! 그래서 canRead(), canWrite() 메서드로 둘 다 체크 가능
주요한 메시지 컨버터
HTTP Body 에 무언가를 적어 넣으면, HTTP 헤더의 미디어 타입에 맞는 타입을 함께 넣어야 한다.
응답 예시) @responsebody return helloData => 쓰기 미디어타입: application/json
HTTP 요청 데이터 읽기
1. HTTP 요청이 오고, 컨트롤러에서 @RequestBody or HttpEntity 사용
2. 메시지 컨버터를 구현한 스트링빈들을 쭉 돌면서 canRead() 호출, 컨버팅 가능한지 확인
2-1. 대상 클래스 타입 확인(@RequestBody or HttpEntity<> 의 대상 클래스 타입)
2-2. HTTP 요청 헤더의 Content-Type 확인
3. 가능한 메시지 컨버터에서 read() 호출해 객체 생성 및 반환
HTTP 응답 데이터 생성
1. 컨트롤러에서 @responsebody or HttpEntity 로 반환
2. 메시지 컨버터를 구현한 스트링빈들을 쭉 돌면서 canWrite() 호출, 컨버팅 가능한지 확인
2-1. 대상 클래스 타입 확인 (return의 대상 클래스 타입)
2-2. HTTP 요청 헤더의 Accept 확인
3. 가능한 메시지 컨버터에서 write() 호출해 맞는 타입으로 응답
// 이런 경우 컨버팅 가능한 스프링 빈이 없어 탈락!content-type: text/html@RequestMapping()
voidhello(@RequestBodyHelloDatadata) {
}
@ResponseBody@RequestMapping("/examp")
publicStringexam(@ModelAttributeExamexam) { // ModelAttribute 를 보고 누군가가 객체를 만들어서 컨트롤러에 던져줘야함!return"ok";
}
ArgumentResolver
애노테이션 기반 컨트롤러는 정말 다양한 파라미터를 사용할 수 있는데 이렇게 파라미터를 유연하게 처리할 수 있는 이유가 바로 ArgumentResolver 덕분.
요청 매핑 핸들러 어뎁터는 이 ArgumentResolver 를 호출해 컨트롤러가 필요한 파라미터를 생성함. 파라미터 값이 모두 준비되면 그때 컨트롤러를 호출
방식
요청 매핑 핸들러가 ArgumentResolver 에게 나 이런 파라미터 필요한데 이거 줄 수 있어? 물어보고, 줄 수 있는 ArgumentResolver 가 객체를 만들어 줌
이렇게 해서 파라미터가 다 준비되면 컨트롤러를 호출한다.
스프링은 30개가 넘은 ArgumentResolver 제공.
// 정식 명칭은 이거임publicinterfaceHandlerMethodArgumentResolver {
// 파라미터 줄 수 있는지 확인booleansupportsParameter(MethodParameterparameter);
// 가능하면 객체 만들어 넘겨줌@NullableObjectresolveArgument(MethodParameterparameter, @NullableModelAndViewContainermavContainer,
NativeWebRequestwebRequest, @NullableWebDataBinderFactorybinderFactory) throwsException;
}
에노테이션 컨트롤러가 처리할 수 있는 파라미터가 어느게 있는지? -> 우리가 이미 봤던 페이지!
이게 사실(?)은 ArgumentResolver가 처리할 수 있는 객체들 이었던것!
컨트롤러가 리턴하는 타입도 다양함.
이를 처리해주는 것 -> ReturnValueHandler
컨트롤러에서 String 을 반환해도 잘 동작하는 이유가 ReturnValueHandler 덕분.
파라미터는 OK! 그럼 HTTP 메시지 컨버터는 어디있나요?
HTTP 메시지 컨버터는 ArgumentResolver 와 ReturnValueHandler 가 사용한다.
"요청"
컨트롤러에 있는 파라미터에 따라 매칭되는 ArgumentResolver 가 있다. (@RequestBody 를 처리하는 ArgumentResolver / HttpEntity 를 처리하는 ArgumentResolver(HttpEntityMethodProcessor))
이 각각의 ArgumentResolver 들이 Http 메시지 컨버터를 사용해서 필요한 객체를 생성한다.
메시지 컨버터를 루프 돌리면서 변환 가능한지 확인하고(canRead()), 객체를 만들도록 함(read()).
"응답"
컨트롤러가 리턴하는 타입에 매칭되는 ReturnValueHandler 가 있다. (@responsebody 를 처리하는 ReturnValueHandler / HttpEntity를 처리하는 ReturnValueHandler)
이 각각의 ReturnValueHandler 들이
스프링은
HandlerMethodArgumentResolver
HandlerMethodReturnValueHandler
HttpMessageConverter
이 세가지를 인터페이스로 제공해 확장성이 크다!
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Http 응답 - 정적 리소스, 뷰 템플릿
스프링(서버) 에서 응답 데이터를 만드는 방법은 크게 3가지. 1. 정적 리소스 - 정적인 HTML, CSS, js 를 제공할 때 2. 뷰 템플릿 사용 - 동적인 HTML 3. HTTP 메시지 사용 - HTTP 메시지 바디에 JSON, XML 등의 형식으로 데이터 보냄정적 리소스
스프링 부트는 보통의 웹프로젝트인(?) webapp 을 제공하지 않고, 아래 경로에 있는 정적 리소스를 제공한다./static,/public,/resources,/META-INF/resources우리가 보통 사용하는
src/main/resources/static경로에 html 파일이 있으면 localhost:8080/'이곳에 파일 경로를 넣어 바로 접근 가능하다.'
뷰 템플릿
뷰 템플릿을 거처서 html 생성, 뷰가 응답을 만들어서 전달하는 방식. 동적 html 생성의 용도지만, 다른것들도 가능하다? 스프링이 제공하는 기본 템플릿 경로src/main/resources/templatesString 을 반환하는 경우
@responsebody 가 없으면 반환한 스트링으로("response/hello") 뷰 리졸버가 실행, 뷰를 찾고 렌더링함
논리 이름을 templates/response/hello.html 로 바꿔서 진행
@ResponseBosy 가 있으면 HTTP 메시지 바디에 직접 반환한 스트링 ("response/hello") 가 입력되어 응답
void 를 반환하는 경우
@controller 사용하고, HttpServletResponse, OutputStream 같은 HTTP 메시지 바디 처리 파라미터 없으면 요청 URL을 뷰 이름으로 사용
권장하지 않음!
Thymeleaf 스프링 부트 설정
build.gradle 에 타임리프 라이브러리를 추가하면, 스프링 부트가 자동으로 *ThymeleafViewResolver* + 관련된 필요한 스프링 빈 등록. 또, 기본 경로 및 확장자까지 application.properties에 설정해줌classpath -> /src/main/resources
Http 응답 - HTTP API, 메시지 바디에 직접 입력
REST API, HTTP API 라고 부름 이런경우는 html 이 아니라 데이터를 직접 전달해야 함. 사실 위에 했던 방식도 HTTP메시지 바디에 HTML 을 넣어서 보냄, 이번 방식은 정적리소스, 뷰 템플릿을 거치지 않고 직접 HTTP 응답 메시지를 전달하는 경우지금 @responsebody 가 여러 메서드에 주렁주렁 있는데, 이를 class level 로 올리면 한방에 가능.
그런데 @controller + @responsebody = @RestController
반환의 형태에 대한부분은 위에 설명이 되었지만
객체를 반환했을 때 이걸 JSON 으로 변환이 어떻게 되는거지???
Http 메시지 컨버터
JSON 데이터를 HTTP 메시지 바디에 쓰는 경우 HTTP 메시지 컨버터를 사용하면 편리하다! 원래는 ServletInputStream + ObjectMapper 로 변환 후 response.getWriter().write() 로 직접 넣어줄 수 있는데 매우 불편, 이를 HttpMessageConverter 로 쉽게 가능!스프링 기초 강의에 나왔던 ResponseBody 원리
@responsebody 가 있으면 HttpMessageConverter 가 동작함. (ViewResolver 대신)
컨트롤러가 리턴하는걸 받아 스트링 or JSON 을 선택해 응답 보냄
=> 다양한 메시지 컨버터 중 선택할 때 HTTP Accept 해더(응답) or 미디어 타입(요청), 컨트롤러의 반환 타입(응답) or 대상 클래스 타입(요청)을 조합해 어떤 HttpMessageConverter 를 선택할지 결정함.
** HTTP 메시지 컨버터 적용하는 경우 (요청, 응답 둘다 사용)
HTTP 메시지 컨버터는 양방향! 그래서 canRead(), canWrite() 메서드로 둘 다 체크 가능
주요한 메시지 컨버터
HTTP 요청 데이터 읽기
1. HTTP 요청이 오고, 컨트롤러에서 @RequestBody or HttpEntity 사용 2. 메시지 컨버터를 구현한 스트링빈들을 쭉 돌면서 canRead() 호출, 컨버팅 가능한지 확인 2-1. 대상 클래스 타입 확인(@RequestBody or HttpEntity<> 의 대상 클래스 타입) 2-2. HTTP 요청 헤더의 Content-Type 확인 3. 가능한 메시지 컨버터에서 read() 호출해 객체 생성 및 반환HTTP 응답 데이터 생성
1. 컨트롤러에서 @responsebody or HttpEntity 로 반환 2. 메시지 컨버터를 구현한 스트링빈들을 쭉 돌면서 canWrite() 호출, 컨버팅 가능한지 확인 2-1. 대상 클래스 타입 확인 (return의 대상 클래스 타입) 2-2. HTTP 요청 헤더의 Accept 확인 3. 가능한 메시지 컨버터에서 write() 호출해 맞는 타입으로 응답요청 매핑 헨들러 어뎁터 구조
HTTP 메시지 컨버터는 스프링의 어디에서 사용되는 걸까? 요청 매핑 핸들러 어뎁터: @RequestMapping을 통해 @controller 를 처리해주는 어뎁터!위 그림에서 Http 메시지 컨버터가 보이지 않음. 어디에서 동작하는거지?
에노테이션 기반의 컨트롤러의 여러 파라미터를 만들어서 호출하는것 => 요청 매핑 핸들러 어뎁터가 해준다! => 요게 메시지 컨버터와 관련있다.
요청 매핑 핸들러의 동작 방식!
어찌저찌해서 요청 매핑 핸들러까진 찾았고 이게 컨트롤러를 호출해야함.
ArgumentResolver
애노테이션 기반 컨트롤러는 정말 다양한 파라미터를 사용할 수 있는데 이렇게 파라미터를 유연하게 처리할 수 있는 이유가 바로 ArgumentResolver 덕분.
요청 매핑 핸들러 어뎁터는 이 ArgumentResolver 를 호출해 컨트롤러가 필요한 파라미터를 생성함. 파라미터 값이 모두 준비되면 그때 컨트롤러를 호출
방식
요청 매핑 핸들러가 ArgumentResolver 에게 나 이런 파라미터 필요한데 이거 줄 수 있어? 물어보고, 줄 수 있는 ArgumentResolver 가 객체를 만들어 줌
이렇게 해서 파라미터가 다 준비되면 컨트롤러를 호출한다.
스프링은 30개가 넘은 ArgumentResolver 제공.
에노테이션 컨트롤러가 처리할 수 있는 파라미터가 어느게 있는지? -> 우리가 이미 봤던 페이지!
이게 사실(?)은 ArgumentResolver가 처리할 수 있는 객체들 이었던것!
컨트롤러가 리턴하는 타입도 다양함.
이를 처리해주는 것 -> ReturnValueHandler
컨트롤러에서 String 을 반환해도 잘 동작하는 이유가 ReturnValueHandler 덕분.
파라미터는 OK! 그럼 HTTP 메시지 컨버터는 어디있나요?
HTTP 메시지 컨버터는 ArgumentResolver 와 ReturnValueHandler 가 사용한다.
"요청"
컨트롤러에 있는 파라미터에 따라 매칭되는 ArgumentResolver 가 있다. (@RequestBody 를 처리하는 ArgumentResolver / HttpEntity 를 처리하는 ArgumentResolver(HttpEntityMethodProcessor))
이 각각의 ArgumentResolver 들이 Http 메시지 컨버터를 사용해서 필요한 객체를 생성한다.
메시지 컨버터를 루프 돌리면서 변환 가능한지 확인하고(canRead()), 객체를 만들도록 함(read()).
"응답"
컨트롤러가 리턴하는 타입에 매칭되는 ReturnValueHandler 가 있다. (@responsebody 를 처리하는 ReturnValueHandler / HttpEntity를 처리하는 ReturnValueHandler)
이 각각의 ReturnValueHandler 들이
스프링은
HandlerMethodArgumentResolver
HandlerMethodReturnValueHandler
HttpMessageConverter
이 세가지를 인터페이스로 제공해 확장성이 크다!
만약 세가지를 구현해 추가하고싶다면 WebMvcConfigurer 에 추가하면 된다.
All reactions