6. 스프링 MVC - 기본 기능[응답]

이건회·2022년 7월 10일
0

springmvc

목록 보기
26/29

1) 정적 리소스, 뷰 템플릿

  • 스프링에서 응답 데이터를 만드는 방법은 3가지다.

  • 웹 브라우저에 정적인 HTML, css, js를 제공할 때는, 정적 리소스를 사용한다.

  • 웹 브라우저에 동적인 HTML을 제공할 때는 뷰 템플릿을 사용한다.

  • HTTP API를 제공하는 경우에는 HTML이 아니라 데이터를 전달해야 하므로, HTTP 메시지 바디에 JSON 같은 형식으로 데이터를 실어 보낸다.

  • /static , /public , /resources , /META-INF/resources 에 있는 리소스는 스프링 부트가 정적으로 제공한다.

  • 뷰 템플릿을 거쳐서 HTML이 생성되고, 뷰가 응답을 만들어서 전달한다.

  • 뷰 템플릿은 일반적으로 html을 동적으로 생성하는 용도지만 다른 것도 가능하다.
    "src/main/resources/templates"는 스프링 부트의 기본 템플릿 경로다.


  • hello.html을 "src/main/resources/templates"경로 하위에 넣고, 템플릿 언어오 html 안에 동적으로 넣을 데이터를 명시한 뒤(

    empty

    )
  • 컨트롤러를 생성하고 해당 url 매핑에서 새로운 모델앤뷰를 생성한 뒤, html 템플릿 안의 변수와 같은 변수를 attributeName 인자로 넣고, 값(hello)을 넣어준 후 해당 url을 실행하면

  • 정상적으로 밸류값을 html에 동적 리턴한다

  • @Controller에서 String으로 반환하면 모델을 파라미터로 넣어준다. 이 때 리턴값이 뷰의 논리적 이름이 된다.
  • 즉 뷰의 논리 이름인 "response/hello"를 반환하면 ("templates/response/hello.html")의 뷰 템플릿이 렌더링 된다.

2) HTTP 응답 - HTTP API, 메세지 바디에 직접 입력

  • HTTP API를 제공하는 경우는 HTTP 메시지 바디에 json 등의 형식으로 데이터를 실어 보낸다.

  • HTTP 메세지 바디에 응답을 전달하는 컨트롤러다.

  • 서블릿을 직접 다룰 대 처럼 HttpServletResponse를 통해 HTTP 메세지 바디에 직접 ok 응답 메시지를 전달한다.

  • ResponseEntity 엔티티는 HttpEntity를 상속 받은 엔티티다. HttpEntity는 HTTP 메시지의 헤더,바디 정보를 가지고 있다. ResponseEntity는 여기에 추가로 HTTP 응답 코드를 설정 가능ㅎ다ㅏ.

  • @ResponseBody를 사용하면 view를 사용하지 않고 HTTP 메시지 컨버터를 통해 HTTP 메시지를 직접 입력할 수 있다.

  • ResponseEntity 를 반환한다. HTTP 메시지 컨버터를 통해서 JSON 형식으로 변환되어서 반환된다.

  • ResponseEntity 는 HTTP 응답 코드를 설정할 수 있는데, @ResponseBody 를 사용하면 이런 것을 설정하기 까다롭다.
    @ResponseStatus(HttpStatus.OK) 애노테이션을 사용하면 응답 코드도 설정할 수 있다.

  • @Restcontroller: @Controller 대신에 @RestController 애노테이션을 사용하면, 해당 컨트롤러에 모두 @ResponseBody 가 적용되는 효과가 있다. 따라서 뷰 템플릿을 사용하는 것이 아니라, HTTP 메시지 바디에 직접 데이터를 입력한다. 이름 그대로 Rest API(HTTP API)를 만들 때 사용하는 컨트롤러이다.

3) HTTP 메시지 컨버터

  • 뷰 템플릿처럼 html을 동적으로 생성해 응답하는 것이 아닌 JSON 데이터를 http 메시지 바디에 직접 읽거나 쓰는 경우 Http 메시지 컨버터를 사용하면 편리하다.

  • @ResponseBody는 HTTP 바디에 문자 내용을 직접 반환한다.

  • 스프링 mvc는 http 요청의 경우에는 @RequestBody, 응답의 경우에는 @ResponseBody의 경우에 http 메시지 컨버터를 적용한다.

  • 즉 http 메시지 컨버터는 http 요청/응답 모두 사용한다.

  • canRead() , canWrite() : 메시지 컨버터가 해당 클래스, 미디어타입을 지원하는지 체크하는 기능이다.

  • read() , write() : 메시지 컨버터를 통해서 메시지를 읽고 쓰는 기능(canRead() , canWrite() 통과 후 적용)

  • 몇 가지 주요한 http 메시지 컨버터는 다음과 같다.

  • ByteArrayHttpMessageConverter : byte[] 데이터를 처리한다.
    클래스 타입: byte[] , 미디어타입: /(전부 가능) ,
    요청 예) @RequestBody byte[] data
    응답 예) @ResponseBody return byte[] 쓰기 미디어타입 application/octet-stream

  • StringHttpMessageConverter : String 문자로 데이터를 처리한다. 클래스 타입: String , 미디어타입: /
    요청 예) @RequestBody String data
    응답 예) @ResponseBody return "ok" 쓰기 미디어타입 text/plain

  • MappingJackson2HttpMessageConverter : application/json 클래스 타입: 객체 또는 HashMap , 미디어타입 application/json 관련
    요청 예) @RequestBody HelloData data
    응답 예) @ResponseBody return helloData 쓰기 미디어타입 application/json 관련

  • 메시지 컨버터 동작 순서

1-HTTP 요청 데이터 읽기
1.1- HTTP 요청이 오고, 컨트롤러에서 @RequestBody , HttpEntity 파라미터를 사용한다.
1.2- 메시지 컨버터가 메시지를 읽을 수 있는지 확인하기 위해 canRead() 를 호출한다.
1.3- 대상 클래스 타입을 지원하는가.
예) @RequestBody 의 대상 클래스 ( byte[] , String , HelloData )
1.4- HTTP 요청의 Content-Type 미디어 타입을 지원하는가. 예) text/plain , application/json , /
1.5- canRead() 조건을 만족하면 read() 를 호출해서 객체 생성하고, 반환한다.

2- HTTP 응답 데이터 생성
2-1 컨트롤러에서 @ResponseBody , HttpEntity 로 값이 반환된다.
2-2 메시지 컨버터가 메시지를 쓸 수 있는지 확인하기 위해 canWrite() 를 호출한다.
2-3대상 클래스 타입을 지원하는가.
예) return의 대상 클래스 ( byte[] , String , HelloData )
2-4 HTTP 요청의 Accept 미디어 타입을 지원하는가.(더 정확히는 @RequestMapping 의 produces ) 예) text/plain , application/json , /
2-5 canWrite() 조건을 만족하면 write() 를 호출해서 HTTP 응답 메시지 바디에 데이터를 생성한다.

4) 요청 매핑 핸들러 어댑터 구조

  • http 메시지 컨버터는 위 스프링 mvc의 구조 중 애노테이션 기반의 컨트롤러인 핸들러 어댑터에서 존재한다.

  • 요청 매핑 핸들러 어댑터의 구조이다.
  • 애노테이션 기반의 컨트롤러는 다양한 유형의 파라미터를 모두 처리할 수 있었다. HttpServletRequest , Model 은 물론이고, @RequestParam , @ModelAttribute 같은 애노테이션 그리고 @RequestBody , HttpEntity 같은 HTTP 메시지를 처리하는 부분까지 매우 큰 유연함을 보여주었다.
  • 이렇게 파라미터를 유연하게 처리할 수 있는 이유가 바로 ArgumentResolver 덕분이다.
  • 애노테이션 기반 컨트롤러를 처리하는 RequestMappingHandlerAdapter 는 바로 이 ArgumentResolver 를 호출해서 컨트롤러(핸들러)가 필요로 하는 다양한 파라미터의 값(객체)을 생성한다.
  • 그리고 이렇게 파리미터의 값이 모두 준비되면 컨트롤러를 호출하면서 값을 넘겨준다.

  • ArgumentResolver 의 실제 형태다.
  • ArgumentResolver 의 supportsParameter() 를 호출해서 해당 파라미터를 지원하는지 체크하고, 지원하면 resolveArgument() 를 호출해서 실제 객체를 생성한다. 그리고 이렇게 생성된 객체가 컨트롤러 호출시 넘어가는 것이다.

  • 이 ArgumentResolver가 사용하는 것이 http 메시지 컨버터다.
  • ArgumentResolver가 반복문을 돌며 여러 HTTP 메시지 컨버터중 필요한 것을 사용해서 필요한 객체를 생성하는 것이다.
  • HTTP 메시지 컨버터를 사용하는 @RequestBody 도 결국 컨트롤러가 필요로 하는 파라미터의 값에 사용된다. @ResponseBody 의 경우도 컨트롤러의 반환 값을 이용한다.
profile
하마드

0개의 댓글