Spring 응답 데이터 (1)
- Server에서 Client로 Data를 전달하는 방법
📚 Server에서 Client로 Data를 전달하는 방법은 정적 리소스, View Template, HTTP Message Body 세가지 방법이 있다.
- 정적 리소스
- 정적인 HTML, CSS, JS, Image 등을 변경 없이 그대로 반환한다.

- View Template
- SSR(Server Side Rendering)을 사용할 때 View가 반환된다.

- HTTP Message Body
- 응답 데이터를 직접 Message Body에 담아 반환한다.

📚 웹 애플리케이션에서 변하지 않는 파일들을 의미한다. 예를 들어, HTML, CSS, JavaScript, 이미지 파일들(JPG, PNG, GIF) 등이 정적 리소스에 해당한다.
- Spring Boot의 정적 리소스 경로
- 아래 경로들에 정적 리소스가 존재하면 서버에서 별도의 처리 없이 파일 그대로 반환된다.
-
/static
-
/public
-
/META-INF/resources
4. src/main/resources
1. /static
- Spring Boot Directory 구조

src/main/resources/static/hello/world.html 디렉토리 구조라면
http://localhost:8080/hello/world.html URL로 리소스에 접근이 가능하다. 
/static 대신 /public 혹은 /META-INF/resources 도 사용 가능하다.
- View Template
📚 Spring에서는 Thymeleaf, JSP와 같은 템플릿 엔진을 사용해 View Template을 작성할 수 있고, View Template은 서버에서 데이터를 받아 이를 HTML 구조에 맞게 삽입한 후, 최종적으로 클라이언트에게 전송되는 HTML 문서로 변환하여 사용자에게 동적으로 생성된 웹 페이지를 제공한다.
📌 View Template
- View Template은 Model을 참고하여 HTML 등이 동적으로 만들어지고 Client에 응답된다.
- Spring Boot는 기본적으로 View Template 경로(`src/main/resources/templates`)를 설정한다.
- build.gradle에 Thymeleaf 의존성을 추가하면 `ThymeleafViewResolver`와 필요한 Spring Bean들이 자동으로 등록된다.
- 기본 설정 예시(아래 내용을 자동으로 Spring Boot가 등록해준다.)
```
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html // or jsp
```
1. **@Controller의 응답으로 String을 반환하는 경우**
- `@ResponseBody` 가 없으면 View Resolver가 실행되며 View를 찾고 Rendering한다.
```java
@Controller
public class ViewTemplateController {
@RequestMapping("/response-view")
public String responseView(Model model) {
// key, value
model.addAttribute("data", "sparta");
return "thymeleaf-view";
}
}
```
```html
Hello
Thymeleaf
```
ex) `http://localhost:8080/response-view`

- `@ResponseBody` 가 있으면 HTTP Message Body에 return 문자열 값이 입력된다.
```java
@Controller
public class ViewController {
@ResponseBody // @RestController = @Controller + @ResponseBody
@RequestMapping("/response-body")
public String responseBody() {
return "thymeleaf-view";
}
}
```
- Postman

2. **반환 타입이 void인 경우**
- 잘 사용하지 않는다.
- @Controller + (@ResponseBody, HttpServletResponse, OutputStream)과 같은 HTTP Message Body를 처리하는 파라미터가 없으면 RequestMapping URL을 참고하여 View Name으로 사용한다.
```java
@Controller
public class ViewTemplateController {
// thymeleaf-view.html 과 Mapping된다.
@RequestMapping("/thymeleaf-view")
public void responseViewV2(Model model) {
model.addAttribute("data", "sparta");
}
}
```
- 예시와 같은 경우에는 viewTemplate(viewName)을 RequestMapping URL 주소로 찾는다.

Spring 응답 데이터 (2)
- HTTP Message Body(응답)
📚 REST API를 만드는 경우 Server에서 Client로 HTML을 전달하는 방식이 아닌 HTTP Message Body에 직접 Data를 JSON 형식으로 담아 전달한다.
⛔ 정적 HTML, View Template 또한 HTTP Message Body에 담겨서 전달된다. 현재 설명하는 Response의 경우는 정적 HTML, View Template을 거치지 않고 직접 HTTP Response Message를 만들어 전달하는 경우를 말하는것.
- **HTTP Message Body**
1. **HttpServletResponse 사용**
```java
@Controller
public class ResponseBodyController {
@GetMapping("/v1/response-body")
public void responseBodyV1(
HttpServletResponse response
) throws IOException {
response.getWriter().write("data");
}
}
```
- Postman

- Response Body에 data 라는 문자열이 입력되어 응답된다.
- 기존 Servlet을 다룰 때 코드와 형태가 같다.
2. **ResponseEntity<> 사용**
```java
@GetMapping("/v2/response-body")
public ResponseEntity responseBodyV2() {
return new ResponseEntity<>("data", HttpStatus.OK);
}
```
- Postman

- Response Body에 data라는 문자열과 HttpStatus.OK에 해당하는 상태 코드를 반환한다.
- `ResponseEntity`는 `HttpEntity` 를 상속받았다.
- `HttpEntity`는 HTTP Message의 Header, Body 모두 가지고 있다.
3. **@ResponseBody(TEXT, JSON)** 사용
```java
@Data
@NoArgsConstructor // 기본 생성자
@AllArgsConstructor // 전체 필드를 인자로 가진 생성자
public class Tutor {
private String name;
private int age;
}
```
```java
// TEXT 데이터 통신
@ResponseBody
@GetMapping("/v3/response-body-text")
public String responseBodyText() {
return "data"; // HTTP Message Body에 "data"
}
```
- Postman

```java
// JSON 데이터 통신
@ResponseBody
@GetMapping("/v3/response-body-json")
public Tutor responseBodyJson() {
Tutor tutor = new Tutor("wonuk", 100);
return tutor; // HTTP Message Body에 Tutor Object -> JSON
}
```
- Postman

- View를 사용하는 것이 아닌 **HTTP Message Converter**를 통해 HTTP Message Body를 직접 입력할 수 있다. → `ResponseEntity`와 같음
- `@ResponseStatus` 를 사용하여 상태 코드를 지정할 수 있다.
```java
@ResponseStatus(HttpStatus.OK)
@ResponseBody
@GetMapping("/v4/response-body")
public Tutor responseBodyV4() {
Tutor tutor = new Tutor("wonuk", 100);
return tutor;
}
```
- Postman

- 단, 응답 코드를 조건에 따라서 동적으로 변경할 수는 없다.
ex) 1번의 경우 OK, 2번의 경우 Created
4. **ResponseEntity**(JSON)
```java
@ResponseBody
@GetMapping("/v5/response-body")
public ResponseEntity responseBody() {
Tutor tutor = new Tutor("wonuk", 100);
return new ResponseEntity<>(tutor, HttpStatus.OK);
}
```
- Postman

- `ResponseEntity<>`두 번째 파라미터에 Enum을 사용하여 상태 코드를 바꿀 수 있다.
- **HTTP Message Converter**를 통하여 JSON 형태로 변환되어 반환된다.
- **동적으로 응답 코드를 변경할 수 있다.**
```java
@ResponseBody
@GetMapping("/v5/response-body")
public ResponseEntity responseBody() {
Tutor tutor = new Tutor("wonuk", 100);
if (조건) {
return new ResponseEntity<>(tutor, HttpStatus.OK);
} else {
return new ResponseEntity<>(tutor, HttpStatus.BAD_REQUEST);
}
}
```
- HttpEntity를 상속받았다.

- 정리
- Client에서 Server로 Data를 전달하는 세가지 방법
-
GET - Query Param, Query String
ex) http://localhost:8080/tutor?name=wonuk&age=100
- 사용하는 어노테이션
- @RequestParam, @ModelAttribute
-
POST - HTML Form(x-www-form-urlencoded)
POST /form-data
content-type: application/x-www-form-urlencoded
**key1=value1&key2=value2**
- 사용하는 어노테이션
- @RequestParam, @ModelAttribute
-
HTTP Request Body
ex) 데이터(JSON, TEXT, XML 등)를 직접 HTTP Message Body에 담아서 사용한다.

- Server(Spring)에서 HTTP 응답을 Client에 전달하는 세가지 방법
-
정적 리소스
- 정적인 HTML, CSS, JS, Image 등을 변경없이 그대로 반환한다.

-
View Template
- SSR(Server Side Rendering)을 사용할 때 View가 반환된다.
- 사용하는 어노테이션

-
HTTP Message Body
- 응답 데이터를 직접 Message Body에 담아 반환한다.
- 사용하는 어노테이션
- @ResponseBody, ResponseEntity

- 요청
- @RequestParam, @ModelAttribute, @RequestBody
- 응답
- 정적 리소스, View Template(@Controller), @ResponseBody, ResponseEntity