: client의 reqeuest 를 제한하는 용도
client 의 request 안의 header 정보 내부에 있는 content-type 의 일치 여부를 통해 reqeust 를 제한한다.
reqeust 라는 것의 내부에는
로 분류된다. 그 중에서 get 방식의 경우, 데이터가 start line 의 url 에 쿼리스트링 형태로 담기게 된다.
그런데 header 의 content-type 이라는 것은 requestbody 의 데이터 형식을 지정해주는 것이다.
서버 측에서 request 에 대한 mapping 으로 consumes 에 제한을 걸게되면, get 방식의 경우 그 제한에 걸려버리게 된다.
consumes
는 하나만 받는 것이 아니기 때문에, 배열 형태로 작성해준다.
브라우저의 request header
부분을 보게 되면, get
방식의 경우 conttent-type 항목이 존재하지 않는 것을 볼 수 있다. 그렇기 때문에 RequestMapping 의 consumes
속성을 통해 제한을 걸게 되면 get
방식의 요청이 정상적으로 이루어질 수 없게 되고, 415
에러가 발생하게 된다.
post 방식의 경우, 기본적으로 content-type 이라는 속성이 request header
에 존재하고 있다. 그리고, 그 default 값으로 Content-Type: application/x-www-form-urlencoded
으로 존재하고 있다.
다만 content-type 이라는 속성이 존재하더라도, handler 의 consumes 속성에 매핑한 값과 매칭이 되지 않기 때문에 get 방식과 마찬가지로 415
error 가 발생하게 된다.
이를 해결하기 위해서는 consumes 배열 내부에 application/x-www-form-urlencoded
를 추가해주던가, ajax 혹은 axios 와 같은 처리를 통해 content-type 을 consumes 에 지정해준 값으로 바꾸어 준다.
consumes
에 form 태그의 기본 content-type 을 입력해주고 나니 아까와는 다르게 415 error 가 아닌, 404 error 가 발생하는 것을 볼 수 있다.
보통의 request 는 특별한 경우가 아닌 이상, 요청을 제한하는 경우는 많지 않다.
대신 요청을 처리하고 난 뒤 client 에게 데이터를 전달할 때 해당 데이터가 일반적인 text/html
인지, application/json
인지 정해주는 경우가 많다.
즉 request의 content-type 을 통해 들어오는 데이터를 특정하는 케이스보다 response의 content-type 을 지정하는 케이스가 훨씬 많다.
: client 에게 반환하는 return 하는 data 의 content-type 을 지정하는 역할을 하는 속성이다.
browser 는 response의 content-tpye 을 확인하고, type 에 맞춰서 적절한 처리를 시행한다.
즉, browser 는 결과 데이터가 어떤 타입으로 올 지 모르기 때문에, 타입을 지정해주어야 return 데이터에 걸맞는 처리가 이루어진다.
주의해야 할 점은, produces
속성은 return 하는 데이터의 타입을 지정하는 역할을 하는 것이지, 내가 리턴하는 데이터가 produces 의 타입으로 변환되는 것이 아니다.
messageConverter
라는 것이 타입으로 변환을 시켜준다.
또한, produces
라는 속성은 특정 이유 때문에 @ResponseBody
라는 어노테이션과 함께 사용이 이루어지는 경우가 대부분이다.
return 이 jsp라면, jsp에 설정된 content-type 으로 덮어씌워져서 보내진 것.
다만, produces 로 잡은 타입이 최종적으로 browser 에게 반환된다, 라는 보장은 없다. 왜냐하면, @RequestMapping 의 구조 상 String 으로 반환된 값은 view resolver 에 의해 View 객체로 생성된 후, 그렇게 생성된 view 객체가 최종적으로 반환되기 때문이다.
responsebody 를 통해 데이터를 보낸 것이 아니라, stream 을 통해 새로운 html 파일을 생성해서 별개의 결과를 보내고자 보낸 것.
즉 printWriter 가 가지고 있는 기본적인 content-type 을 통해 전송이 이루어지게 된 것이다.
때문에 한글 인코딩도 모두 깨져서 반환이 이루어지고, response의 header 부분에도 produces 로 설정한 content-type 이 존재하지 않는다.
즉 단독으로 produces 만 사용해봐야 큰 영향을 끼치지 못하게 된다.
Gson 이라는 외부 라이브러리를 new 를 통해 객체 생성해서 사용하는 케이스.
Gson 객체를 생성하는 메소드를 Bean
으로 수동으로 등록한 뒤, autowired 를 통해 자동 생성을 활용하는 케이스
Bean 을 수동으로 등록할 때의 장점
interface 를 기반으로 구현 클래스를 수동으로 등록하면 전략 패턴을 이용할 수 있게 된다.
@Autowired 를 굳이 사용하지 않고도, getBean
을 사용해서 수동으로 applicationContext 내부에 있는 bean 객체를 가져와 사용할 수도 있다.
application context(=root-context)를 직접 사용하는 방법
(@Autowired를 사용한 자동 주입이 아니라 수동으로 사용하는 방법)
사용은 가능하지만, 구현체를 만들어야 가능하다.
spring이 ApplicationContextAware
의 interface 를 제공해준다.
이 interface 를 구현한 구현체를 Bean
으로 등록해서 사용이 가능하다.
구현체인 ApplicationContextProvider 를 Bean 으로 등록하기 위해 @Component 어노테이션을 붙여준다.
그러면 produces
라는 속성이 필요한가...?
HTTP 의 기본 통신 방식
굳이 RequestBody 를 사용하지 않는 이유는, get
방식을 사용했을 경우에 body 부분에 데이터가 담기지 않는 문제가 발생하고, 또한 Command 객체를 생성해서 사용할 수 있었기 때문이다.
다만 ResponseBody 의 경우, 내가 만든 문자열이나 상태코드, headers 들을 직접 설정해서 전송할 수 있다.
즉, Stream 을 직접 열어서 데이터를 전송하는 것이 아니라, ResponseBody
안에 데이터를 담아서 HttpResponse 를 반환한다.
그리고 반환된 HttpResponse 객체 내부에 담긴 ResoponseBody 의 데이터를 뽑아서 사용하게 된다.
따라서 Controller 를 사용할 때
view 객체를 리턴하는 Controller 와 Ajax 를 통해 클라이언트가 결과 데이터만 받아갈 수 있는 rest 기반의 controller 두 가지를 나누어서 사용하게 된다.
그리고, ResponseBody 안에 담길 데이터의 타입을 설정하는 것이 produces
속성이다. 그렇기 때문에 @ResponseBody
어노테이션과 produces
속성이 같이 사용되게 되는 것이다.
= rest api 를 기반으로 client 의 ajax/axios 호출에 대한 결과를 return 할 때
=> JSP 를 사용하지 않는다. 대신에 등장하는 속성이 produces
, @ResponseBody
정석은 ResponseEntity
라는 객체가 리턴되는 것이지만, Data 만을 리턴하는 케이스도 존재한다.
@ResponseBody
라는 어노테이션이 붙어있다면, 문자열만 리턴이 발생하더라도, view resolver 에 의해 jsp 파일을 찾는 것이 아니라 자체적으로 ResponseEntity 객체를 생성해 리턴한다.
이렇게 문자열만 리턴할 경우, 오직 데이터만을 리턴하게 되고, header 나 상태코드를 지정할 수 없게 된다.
String, 문자열만 반환했기 때문에 상태코드는 실제 처리 결과에 따른 코드인 200이 status line 내부에 찍히게 된다.
ResponseEntity<>() 의 생성자에는 data, headers, 상태를 순서대로 담는다.
그 중 상태는 상수값으로 미리 설정이 되어 있다.
httpStatus.CREATED = 201, 서버에서 무언가가 생성이 되었다는 것을 나타내는 상태코드
rest api 의 규약 중 하나로, 상태코드에는 서버에서의 처리 결과를 알아볼 수 있도록 적절한 코드로 리턴해주어야 한다.
browser 의 입장에서는 produces
에 씌여진 값에 의해 messageConverter 에 의해 변환되지만, 궁극적으로 ResponseEntity 의 header 의 content-type 으로 적혀져 있는 값으로 리턴되게 된다.
ResponseEntity 를 생성하여 return 하는 케이스
User 라는 VO객체를 return 하는 케이스
이 케이스에서는 리턴 타입과, produces 속성 값을 messageConverter 가 확인한 뒤, 내부적으로 데이터를 json-text-xml-img... 등으로 변환해서 반환하게 된다.
@RestController
라는 어노테이션을 이용하면, 기본적으로 jsp를 안쓰고 rest 방식으로 데이터를 리턴하겠다라는 의미이며, 의미적으로 @Controller
와 @ResponseBody
라는 두 개의 어노테이션이 합쳐진 어노테이션이다.
ResponseEntity
가 handler adapter 에게 리턴될 때, messageConverter 라는 것이 존재하는데 사용자가 produces
에 지정한 content-type 에 맞춰서 데이터를 변환한 뒤 dispatcher servlet 에게 반환하게 된다.
일반적으로 유저는 Internet 이라는 물리적 platform 위에 www(world wide web) 이라는 service를 활용하고 있다.
SOAP
simple Object Access Protocol
기반의 web service.
이 방법은 http 이 아닌, SOAP 라는 프로토콜을 이용하겠다는 방식
이 방식의 장점은, 보안성과 데이터 무결성.
하지만, 단점으로 protocol 자체가 복잡하고, web 의 c/s 구조와 잘 맞지 않는다.
따라서 일반적인 web 이 아닌 일반적인 enterprise application에서 사용되는 케이스가 많다.
HTTP
HyperText Transfer Protocol
기반의 web service.
HTTP 라는 프로토콜은 web 의 구조와 상당히 잘 어울린다.
HTTP protocol 의 개발자 중 한 명(로이 필딩)이 현재의 프로토콜의 사용 방법에 의문을 품고, 훨씬 양질의 서비스를 구현할 수 있는 하나의 기준이자 가이드를 제시하게 된다. 이것을 아키텍처
라고 부르고, 그것의 이름이 REST
이다.
이러한 규칙을 잘 지켜서 만든 서비스를 RESTFUL
한 서비스이다, 라고 지칭하게 된다.
상세한 포스팅은 해당 링크로...