@ResponseBody
Controller에서 사용할 수 있는 @중에 @ResponseBody가 있다.
일반적으로 Spring에서 요청을 처리하는 메소드를 만들면 다음과 같다.
package com.study.temp;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class TempController {
@RequestMapping("/idcheck.wow")
public String idCheck(String id) {
return "idcheck";
}
}
이 때 idcheck.wow로 요청을 보낸다면
DispatcherServlet은 /WEB-INF/views/idcheck.jsp파일을 찾아서 forwarding할 것이다.
idcheck.jsp를 만들지 않았다면 404에러가 뜰것이고 만들었다면 해당 jsp를 보게 될 것이다.
그런데 저 "idcheck"라는 문자를 그대로 전달하고 싶은 경우가 있다.
(지금은 String이지만 List나 여러가지 객체들도 그대로 전달하고 싶지 않겠는가?)
컨트롤러 안에서 return 값이 jsp를 찾는데 쓰이지 않고 return 값을 그대로 전달하고 싶을 때
붙이는 @이 바로 @ResponseBody이다.
위 메소드에 @ResponseBody를 붙여보자
package com.study.temp;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class TempController {
@RequestMapping("/idcheck.wow")
@ResponseBody //@은 순서 상관없다
public String idCheck(String id) {
return "idcheck";
}
}
그리고 요청을 "idcheck.wow"로 요청을 보내보자. 다음과 같은 화면이 나온다.
브라우저가 Http요청을 통해 얻은 데이터가 "idcheck" 이기 때문에 화면에 그대로 출력된다.
@ResponseBody가 붙었을 때 return 값(자바 객체 : String, int->Integer, List 등)을
HTTP 요청/응답 몸체로 변환해주는 객체는
HttpMessageConverter 인터페이스를 구현한 클래스가 담당한다.
여기서 잠깐. 서버가 어찌됐든 브라우저에 응답했다.
응답했다는건 서버가 response를 브라우저에게 전달했다는 것이다.
이 때 따로 설정을 안했다면 response의 header에서 content-type은 "text/html;charset=ISO-8859-1" 이다.
f12를 눌러서 network 탭에서 확인할 수 있다. 물론 response의 바디는 단순히 "idcheck"이다.
Content-type
위에서 봤듯이 response는 Header와 Body(몸체) 부분으로 이루어져있다.
브라우저는 이 response를 받아 해석하는데
Header의 Content-type에 따라 Body를 다르게 해석한다.
Content-Type이 text/html인 경우 Body의 내용을 html로 해석하고,
text/plain인 경우 그냥 문자로 해석한다.
예전에는 jsp에서 직접 Content-Type을 지정해줬지만
@ResponseBody를 쓰면 jsp로 가지않고 브라우저한테 바로 응답한다.
그렇다면 컨트롤러 메소드안에서 이 Content-Type을 지정해줘야 된다는 소리이다.
이 Content-Type을 지정해주려면 @RequestMapping() 의 produces속성에서 지정해주면 된다.
@RequestMapping(value = "/idcheck.wow",produces ="text/plain;charset=UTF-8" )
@ResponseBody //@은 순서 상관없다
public String idCheck(String id) {
return "이제 한글도 보낼수 있다.";
}
idcheck.wow로 요청하면 respoonse header를 살펴보면 다음과 같이 나온다.
Content-Type은 여러 종류가 있다. 구글에 "content Type 종류" 라고 검색하면 여러가지가 나온다.
전부 외울필요는 없고 그 때 그때 검색해서 찾으면 된다.
※@RequestMapping에서 produces로 "text/plain" 해놓고 jsp로 포워딩했다.
그런데 만약 jsp에서는 contentType이 "text/html" 인 경우는 어떻게 될까?.
이 때 당연히 jsp가 더 늦게 실행되는 것이기 때문에 응답객체의 Content -Type은 "text/html"이 된다.
보통 @ResponseBody를 안붙여서 jsp로 포워딩 되는 경우에는 jsp에서 contentType을 지정한다.
※보통 이렇게 jsp가 아닌 데이터를 그대로 전달하는 경우는 ajax요청의 경우가 많다.
그렇다 보니 별 생각없이 ajax로 요청하면 @ResponseBody를 붙여야 돼 라고 생각하는데, @ResponseBody를 붙일 때 고려해야 할건
요청이 ajax요청이냐 아니냐가 아니라 데이터를 그대로 응답할건지 아닌지이다.