일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
- multiparfile데이터
- 동등성동일성
- HttpServlet
- DispatcherServlet
- 프로세스 생성
- java enum
- equals
- fcmv1
- 래퍼클래스
- 데이터베이스파서
- multipart바인딩
- fcm데이터구조
- 공유기작동방식
- 왜불변객체인가
- 동기비동기블로킹논블로킹
- rest api
- 스프링요청반응
- 불변객체
- httpservlet기술
- Wrapper class
- rest api 검증
- fcm성능비교
- 옵티마이저
- 디스패처서블릿
- 검증 실패 예외처리
- biblecash
- 클라이언트요청반응
- 옵티마저
- 중첩클래스
- HTTP프로토콜
- Today
- Total
개발은 아름다워
[ Spring ] 스프링에서 응답 데이터 만드는 방식 본문
현재 필자의 회사는 springMVC 쓰고 jsp를 쓰면서 데이터를 주고 받을때는 HTTP API를 이용한다. 그래서 도대체 어떻게 데이터를 주고 받는지 파악하기가 힘들었다. 그래서 오늘은 스프링에서 만드는 응답 데이터를 정리하는 시간을 가지려고 한다.
스프링에서 응답 데이터를 만드는 3가지 방법
- 정적 리소스
- 뷰 템플릿 사용
- HTTP 메세지 사용
1.정적 리소스
스프링 부트는 클래스패스의 다음 디테럭에 있는 정적 리소스를 제공한다.
/static , /public , /resources, /META-INF/resources
src/main/resources는 리소르를 보관하는 곳이고, 또 클래스패스의 시작 경로이다. 따라서 다음 디렉토리에 리소르르 넣어두면 스프링 부트가 정적 리소스로 서비스를 제공한다.
정적 리소스 경로 : src/main/resources/static
만약 다음 경로에 파일이 들어있으면 src/main/resources/static/basic/hello-form.html
웹 브라우져에서 http://localhost:8080/basic/hello-form.html 로 실행하면 된다. 정적 리소스는 해당 파일을 변경 없이 그대로 서비스하는 것이다.
2. 뷰 템플릿
뷰 템플릿을 거쳐서 HTML이 생성되고, 뷰가 응답을 만들어서 전달한다. 일반적으로 HTML을 동적으로 생성하는 용도로 사용하지만, 다른 것들도 가능하다. 뷰 템플릿이 만들 수 있는 것이라면 뭐든지 가능하다. 스프링 부트는 기본 뷰 템플릿 경로를 제공한다.
뷰 템플릿 경로 : src/main/resources/templates
이제 코드로 봐보자. 뷰 템플릿 코드와 뷰 템플릿을 호출하는 컨트롤러 코드이다.
1. 뷰 템플릿
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p th:text="${data}">empty</p>
</body>
</html>
2. 뷰 템플릿을 호출하는 컨트롤러
@Controller
public class ResponseViewController {
@RequestMapping("/response-view-v1")
public ModelAndView responseViewV1(){
ModelAndView mav = new ModelAndView("response/hello")
.addObject("data", "hello!");
return mav;
}
@RequestMapping("/response-view-v2")
public String responseViewV2(Model model){
model.addAttribute("data", "hello");
return "response/hello";
}
@RequestMapping("/response/hello")
public void responseViewV3(Model model){
model.addAttribute("data", "hellow~!");
}
}
1) /response-view-v1
viewName과 data가 포함된 ModelAndView 객체를 반환한다. 이전 FrontController에서 컨트롤러가 ModelView를 반환하면 FrontController에서 뷰 리졸버와 뷰 렌더를 통해 템플릿에 전달하듯이 DispatcherServlet 내부에에서 뷰 리졸버와 뷰 렌더를 통해 템플릿에 데이터를 전달한다.
2) /response-view-v2
이 경우는 반환 타입이 String이다! 이럴 경우 어떻게 되는걸까? @ResponsBody가 없으면 반환 값이 response/hello로 뷰 리졸버가 실행되어서 뷰를 찾고 렌더링한다. @ResponBody가 있으면 뷰 리졸버를 실행하지 않고, HTTP 메시지 바디에 직접 response/hello 라는 문자가 입력된다.
3) /response/hello
이번에는 void를 반환하는 경우이다. @Controller를 사용하고 HttpServletResponse,OutputStream 같은 HTTP 메서지 바디를 처리하는 파라미터가 없으면 요청 URL을 참고해서 논리 뷰 이름으로 사용한다. 이 방식은 명시성이 너무 떨어지고 URL과 논리 뷰 이름이 딱 맞는 경우도 많이 없어서 권장되지 않는다.
HTTP 메세지 - 메세지 바디에 직접 입력
@ResponseBody,HttpEntity를 사용하면 HTTP 메세지 바디에 직접 응답 데이터를 출력할 수 있다.
이번에는 코드와 함께 설명도 주석으로 달아 놓았다.
@Controller
public class ResponseBodyController {
// 고대의 서블릿때처럼 HttpServletResponse 객체를 통해 HTTP 메세지 바디에 직접 OK 응답 메세지 전달
@GetMapping("/response-body-string-v1")
public void responseBodyV1(HttpServletResponse response) throws IOException{
response.getWriter().write("It's ok~!");
}
// ResponseEntity는 HttpEntity를 상속 받았다.
// HttpEntity는 HTTP 메세지의 헤더,바디 정보를 가지고 있다.
// ResponseEntity는 HTTP 응답 코드를 설정할 수 있다.
@ResponseBody
@GetMapping("/response-body-string-v2")
public ResponseEntity<String> responseBodyV2(){
return new ResponseEntity<>("ok",HttpStatus.OK);
}
// @ResponseBody를 사용하면 view를 사용하지 않고 HTTP 메세지 컨버터를 통해
// HTTP 메세지바디에 직접 입력할 수 있다.
@ResponseBody
@GetMapping("/response-body-string-v3")
public String responseBodyV3() {
return "ok";
}
// ResponseEntity 를 반환한다.
// HTTP 메세지 컨버터를 통해서 JSON 형식으로 변환되서어 반환된다.
@GetMapping("/response-body-json-v1")
public ResponseEntity<HelloData> responseBodyJsonV1(){
HelloData helloData = new HelloData();
helloData.setUsername("userA");
helloData.setAge(22);
return new ResponseEntity<>(helloData,HttpStatus.OK);
}
// ResponseEntity는 HTTP 응답코드를 설정할 수 있는데
// ResponseBody를 사용하면 응답 코드를 설정하기 까다롭다
// 따라서 @ResponseStatus(HttpStatus.OK)로 응답코드를 설정한 것이다.
@ResponseStatus(HttpStatus.OK)
@ResponseBody
@GetMapping("/response-body-json-v2")
public HelloData responseBodyJsonV2(){
HelloData helloData = new HelloData();
helloData.setUsername("UserB");
helloData.setAge(30);
return helloData;
}
}
참고 @RestController
@Controller 대신 @RestController를 사용하면 해당 컨트롤러에 모두 @ResponseBody가 적용되는 효과가 있다. 따라서 뷰 템플릿을 사용하는 것이 아닌 HTTP 메세지 바디에 직접 데이터를 입력한다. 보통 Rest API(HTTP API)를 만들 때 사용하는 컨트롤러이다.
정리
필자의 회사는 응답타입을 ModelAndView로 하는데 해당 JSP 서블릿에 대한 논리 뷰 경로를 눈 씻고 찾아봐도 찾을 수 없었다. 이번에 스프링 데이터 응답 방식을 공부하면서 현 회사의 응답 데이터는 어떤 방식인 것인지 실마리를 찾았다. ModelAndView("jsonViewer") 객체로 응답 값으로 주는데, 이 경우에는 HTTP API JSON과 같이 메세지 바디에 JSON 형식의 응답 데이터를 내려준다는 알게되었다. 다음에는 HTTP API 방식을 더 깊이 이해하기 위한 메시지 컨버터를 공부해봐야겠다.
'스프링' 카테고리의 다른 글
[ Spring ] 데이터베이스 접근 기술 JDBC - 근본은 변하지 않는다 (0) | 2024.10.14 |
---|---|
[ Spring ] HTTP API를 가능하게 해주는 메세지 컨버터 (0) | 2024.10.14 |
[ Spring ] 고대의 서블릿을 찾아서(8) - 어댑터패턴과 트레이드 오프 (0) | 2024.10.14 |
[ Spring ] 고대의 서블릿을 찾아서(7) - ModelView를 없애고 더욱 단순하게 (0) | 2024.10.14 |
[ Spring ] 고대의 서블릿을 찾아서(6) - ModelView의 등판 (1) | 2024.10.14 |