정적 리소스
📌 웹 애플리케이션에서 변하지 않는 파일들을 의미한다. 예를 들어, HTML, CSS, JavaScript, 이미지 파일들(JPG, PNG, GIF) 등이 정적 리소스에 해당한다.
- 정적인 HTML, CSS, JS, Image 등을 변경 없이 그대로 반환한다.
정적 리소스의 특징
- 고정된 내용:
- 요청이 올 때마다 동일한 콘텐츠를 제공합니다.
- 실행되거나 동적으로 변환되지 않습니다.
- 캐싱 가능:
- 정적 리소스는 자주 요청되므로 브라우저에서 캐싱하여 성능을 최적화할 수 있습니다.
- 서버 부담 감소:
- 서버는 정적 리소스를 변환하거나 처리하지 않으므로, 부하가 적습니다.
- 브라우저에서 직접 렌더링:
- 클라이언트(브라우저)가 직접 처리할 수 있는 파일 형식으로 제공됩니다.
Spring Boot에서 정적 리소스 제공
- Spring Boot는 기본적으로 정적 리소스를 제공하기 위한 구조를 내장하고 있습니다.
1. 정적 리소스 경로
Spring Boot는 다음 디렉토리에서 정적 리소스를 자동으로 로드합니다:
디렉토리 | 설명 |
/static | src/main/resources/static에 있는 파일을 정적 리소스로 제공. |
/public | src/main/resources/public에 있는 파일을 정적 리소스로 제공. |
/resources | src/main/resources에 있는 파일. |
/META-INF/resources | JAR 파일의 META-INF 디렉토리 내부의 파일. |
2. 정적 리소스 예제
정적 리소스와 동적 리소스 비교
정적 리소스 | 동적 리소스 | |
변경 여부 | 고정된 콘텐츠 (HTML, CSS, JS, 이미지 등). | 요청에 따라 내용이 동적으로 생성됨. |
처리 방식 | 서버가 파일 그대로 응답. | 서버가 요청 데이터를 처리하여 응답 생성. |
요청-응답 속도 | 빠름 (파일 그대로 반환). | 비교적 느림 (처리 후 반환). |
예시 | HTML, CSS, JS, 이미지 파일. | REST API 응답, 템플릿 엔진 출력. |
정적 리소스와 컨트롤러 경로 충돌
Spring Boot는 기본적으로 정적 리소스를 우선 처리합니다.
예:
- /index.html 정적 파일이 있으면, 해당 파일을 반환.
- /index를 처리하는 컨트롤러가 있다면, 정적 리소스 대신 컨트롤러가 처리.
컨트롤러 우선 처리
application.properties에서 다음 설정으로 컨트롤러를 우선 처리하도록 변경 가능합니다:
spring.mvc.static-path-pattern=/**
정적 리소스 최적화
- Gzip 압축:
- 정적 리소스를 Gzip으로 압축하여 전송 속도를 개선.
properties - Content Delivery Network (CDN):
- 정적 리소스를 CDN에 배포하여 전 세계적으로 빠르게 제공.
- 캐싱:
- 브라우저 캐싱을 활용하여 불필요한 네트워크 요청을 줄임.
server.compression.enabled=true
server.compression.mime-types=text/html,text/xml,text/plain,text/css,application/javascript
요약
- 정적 리소스는 서버가 변경 없이 그대로 반환하는 콘텐츠입니다.
- Spring Boot는 /static, /public 등 기본 경로에서 정적 리소스를 자동으로 제공합니다.
- 정적 리소스는 속도가 빠르고 서버 부하가 적으므로, 이미지, CSS, JS 등의 파일 전송에 최적입니다.
- 필요 시 경로와 캐싱 설정을 커스터마이징할 수 있습니다.
- Spring Boot의 정적 리소스 경로
- 아래 경로들에 정적 리소스가 존재하면 서버에서 별도의 처리 없이 파일 그대로 반환된다.
- /static
- /public
- /META-INF/resources
- src/main/resources
- /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 (동적 리소)
📌 웹 애플리케이션에서 서버가 클라이언트에 응답으로 제공할 HTML 페이지를 동적으로 생성하기 위해 사용하는 템플릿 파일입니다. 데이터를 표시하기 위해 동적인 콘텐츠와 정적인 HTML 구조를 결합하는 데 사용됩니다.
- 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들이 자동으로 등록된다.
- SSR(Server Side Rendering)을 사용할 때 View가 반환된다.
View Template의 역할
- 정적 HTML과 동적 데이터 결합:
- 서버에서 HTML 파일에 동적 데이터를 삽입하여 사용자 맞춤 콘텐츠를 생성.
- 서버 사이드 렌더링 (SSR):
- 브라우저에 표시될 HTML을 서버에서 렌더링하고 클라이언트로 전송.
- UI 레이아웃 관리:
- 레이아웃, 반복 구조, 조건부 표시 등과 같은 동적 UI 요소를 효율적으로 관리.
Spring MVC에서 View Template
Spring MVC에서는 Model-View-Controller 패턴을 기반으로 View Template 엔진을 사용하여 HTML을 생성합니다.
Spring MVC에서의 동작 흐름
- Controller:
- 클라이언트의 요청을 처리하고, 데이터를 Model 객체에 담아 View로 전달.
- View Template:
- Model 데이터를 기반으로 HTML을 렌더링.
- Client:
- 완성된 HTML 페이지를 클라이언트로 전송하여 브라우저에 표시.
pring Boot에서 지원하는 View Template 엔진
Thymeleaf | Spring Boot에서 가장 널리 사용되는 템플릿 엔진. 자연스러운 HTML과의 통합 제공. |
JSP | Java 기반의 전통적인 템플릿 엔진. Servlet Container에서 실행. |
Freemarker | 강력한 기능의 템플릿 엔진. 다양한 커스터마이징 가능. |
Mustache | 간단하고 가벼운 템플릿 엔진. JavaScript에서도 동일 문법 사용 가능. |
Groovy Templates | Groovy 언어 기반의 템플릿 엔진. |
Thymeleaf 예제 (Spring Boot 기본 설정)
a. Maven 의존성 추가
Spring Boot Starter를 사용하면 Thymeleaf가 기본적으로 포함됩니다:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
b. 프로젝트 구조
c. Controller 코드
@Controller
public class HomeController {
@GetMapping("/")
public String home(Model model) {
model.addAttribute("title", "Welcome to Thymeleaf");
model.addAttribute("message", "Hello, Thymeleaf!");
return "home"; // home.html을 렌더링
}
}
d. Thymeleaf View Template (home.html)
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title th:text="${title}">Default Title</title>
</head>
<body>
<h1 th:text="${message}">Default Message</h1>
</body>
</html>
결과
- 클라이언트가 /로 요청.
- Controller가 Model에 데이터를 담아 home.html로 전달.
- Thymeleaf가 데이터를 HTML에 삽입.
- 클라이언트로 다음과 같은 HTML 응답이 전송:
<!DOCTYPE html>
<html>
<head>
<title>Welcome to Thymeleaf</title>
</head>
<body>
<h1>Hello, Thymeleaf!</h1>
</body>
</html>
@Controller의 응답으로 String을 반환하는 경우
- @ResponseBody 가 없으면 View Resolver가 실행되며 View를 찾고 Rendering한다.
@Controller
public class ViewTemplateController {
@RequestMapping("/response-view")
public String responseView(Model model) {
// key, value
model.addAttribute("data", "sparta");
return "thymeleaf-view";
}
}
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Hello</title>
</head>
<body>
<h1>Thymeleaf</h1>
<h2 th:text="${data}"></h2>
</body>
</html>
ex) http://localhost:8080/response-view
- @ResponseBody 가 있으면 HTTP Message Body에 return 문자열 값이 입력된다.
반환 타입이 void인 경우
- 잘 사용하지 않는다.
- @Controller + (@ResponseBody, HttpServletResponse, OutputStream)과 같은 HTTP Message Body를 처리하는 파라미터가 없으면 RequestMapping URL을 참고하여 View Name으로 사용한다.
@Controller
public class ViewTemplateController {
// thymeleaf-view.html 과 Mapping된다.
@RequestMapping("/thymeleaf-view")
public void responseViewV2(Model model) {
model.addAttribute("data", "sparta");
}
}
- 예시와 같은 경우에는 viewTemplate(viewName)을 RequestMapping URL 주소로 찾는다.
HTTP Message Body
📌 HTTP Message Body는 HTTP 요청(Request) 또는 응답(Response)에서 실제 데이터를 담는 부분입니다.
- REST API를 만드는 경우 Server에서 Client로 HTML을 전달하는 방식이 아닌 HTTP Message Body에 직접 Data를 JSON 형식으로 담아 전달한다.
- 정적 HTML, View Template 또한 HTTP Message Body에 담겨서 전달된다. 현재 설명하는 Response의 경우는 정적 HTML, View Template을 거치지 않고 직접 HTTP Response Message를 만들어 전달하는 경우를 말하는것.
HttpServletResponse 사용
@Controller
public class ResponseBodyController {
@GetMapping("/v1/response-body")
public void responseBodyV1(
HttpServletResponse response
) throws IOException {
response.getWriter().write("data");
}
}
- Response Body에 data 라는 문자열이 입력되어 응답된다.
- 기존 Servlet을 다룰 때 코드와 형태가 같다.
ResponseEntity<> 사용
@GetMapping("/v2/response-body")
public ResponseEntity<String> responseBodyV2() {
return new ResponseEntity<>("data", HttpStatus.OK);
}
- Response Body에 data라는 문자열과 HttpStatus.OK에 해당하는 상태 코드를 반환한다.
- ResponseEntity는 HttpEntity 를 상속받았다.
- HttpEntity는 HTTP Message의 Header, Body 모두 가지고 있다.
@ResponseBody(TEXT, JSON) 사용
@Data
@NoArgsConstructor // 기본 생성자
@AllArgsConstructor // 전체 필드를 인자로 가진 생성자
public class Tutor {
private String name;
private int age;
}
// TEXT 데이터 통신
@ResponseBody
@GetMapping("/v3/response-body-text")
public String responseBodyText() {
return "data"; // HTTP Message Body에 "data"
}
// JSON 데이터 통신
@ResponseBody
@GetMapping("/v3/response-body-json")
public Tutor responseBodyJson() {
Tutor tutor = new Tutor("wonuk", 100);
return tutor; // HTTP Message Body에 Tutor Object -> JSON
}
- View를 사용하는 것이 아닌 HTTP Message Converter를 통해 HTTP Message Body를 직접 입력할 수 있다. → ResponseEntity와 같음
- @ResponseStatus 를 사용하여 상태 코드를 지정할 수 있다.
@ResponseStatus(HttpStatus.OK)
@ResponseBody
@GetMapping("/v4/response-body")
public Tutor responseBodyV4() {
Tutor tutor = new Tutor("wonuk", 100);
return tutor;
}
- 단, 응답 코드를 조건에 따라서 동적으로 변경할 수는 없다.
ex) 1번의 경우 OK, 2번의 경우 Created
ResponseEntity<Object>(JSON)
@ResponseBody
@GetMapping("/v5/response-body")
public ResponseEntity<Tutor> responseBody() {
Tutor tutor = new Tutor("wonuk", 100);
return new ResponseEntity<>(tutor, HttpStatus.OK);
}
- ResponseEntity<>두 번째 파라미터에 Enum을 사용하여 상태 코드를 바꿀 수 있다.
- HTTP Message Converter를 통하여 JSON 형태로 변환되어 반환된다.
- 동적으로 응답 코드를 변경할 수 있다.
@ResponseBody
@GetMapping("/v5/response-body")
public ResponseEntity<Tutor> 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에 담아서 사용한다.
- 사용하는 어노테이션
- @RequestBody
Server(Spring)에서 HTTP 응답을 Client에 전달하는 세가지 방법
- 정적 리소스
- 정적인 HTML, CSS, JS, Image 등을 변경없이 그대로 반환한다.
- View Template
- SSR(Server Side Rendering)을 사용할 때 View가 반환된다.
- 사용하는 어노테이션
- @Controller
- HTTP Message Body
- 응답 데이터를 직접 Message Body에 담아 반환한다.
- 사용하는 어노테이션
- @ResponseBody, ResponseEntity<Object>
- 요청
- @RequestParam, @ModelAttribute, @RequestBody
- 응답
- 정적 리소스, View Template(@Controller), @ResponseBody, ResponseEntity<Object>
'Back-End (Web) > Spring' 카테고리의 다른 글
[Spring] Layered Architecture (2) | 2024.12.20 |
---|---|
[Spring] HTTP Message Body & TEXT (0) | 2024.12.18 |
[Spring] @RequestParam & @ModelAttribute (0) | 2024.12.17 |
[Spring] Request Mapping (1) | 2024.12.16 |
[Spring] Spring Annotation (1) | 2024.12.15 |