- 웹 애플리케이션의 성능을 높이기 위한 방법
- 브라우저나 프록시 서버가 응답을 저장하고 재사용할 수 있게 도와주는 매커니즘
1. Cache-Control
- 클라이언트나 프록시에게 응답을 어떻게 캐시될 지 알리는 HTTP 헤더 (응답 헤더)
흐름
- 클라이언트가 자원을 요청
- 서버는 응답 시, Cache-Control 헤더를 포함해서 응답
- 클라이언트가 해당 설정에 따라 캐싱 자원으로 응답할 지 결정
예시) 뉴스 기사 요청하기
더보기
더보기
GET /news/123
HTTP/1.1 200 OK
Cache-Control: max-age=60
Content-Type: text/html
- 브라우저에 응답을 캐싱함
GET /news/123
- 60초 이내 재요청 시, 서버로 요청이 가지 않음. (캐시 사용)
- 60초 이후 재요청 시, 서버로 새 요청 (캐시 만료)
Spring
- WebMvcConfigurer에서 Interceptor or ResourceHandler를 설정할 수 있습니다.
- ResonseEntity로 직접 응답할 수 있습니다.
설정) WebMvcConfigurer
더보기
더보기
핸들러에 적용
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
WebContentInterceptor interceptor = new WebContentInterceptor();
interceptor.addCacheMapping(
CacheControl.maxAge(3600, TimeUnit.SECONDS),
"/api/public/**"
);
registry.addInterceptor(interceptor);
}
}
정적 리소스에 적용
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static/")
.setCacheControl(CacheControl.maxAge(30, TimeUnit.DAYS));
}
예제) ResonseEntity로 응답하기
더보기
더보기
@GetMapping("/book/{id}")
public ResponseEntity<Book> showBook(@PathVariable Long id) {
Book book = findBook(id);
String version = book.getVersion(); // 예: "v1.2"
// "Cache-Control: max-age=3600" (1시간 동안 캐시)
CacheControl cc1 = CacheControl.maxAge(1, TimeUnit.HOURS);
// "Cache-Control: no-store" (캐시하지 않음)
CacheControl cc2 = CacheControl.noStore();
// "Cache-Control: max-age=864000, public, no-transform" (10일 동안 캐시, 공용 캐시 가능, 변형 금지)
CacheControl cc3 = CacheControl.maxAge(10, TimeUnit.DAYS).noTransform().cachePublic();
return ResponseEntity
.ok()
.cacheControl(cc3) // 원하는 cache control 선택
.eTag(version)
.body(book);
}
2. Last-Modified
- 리소스가 마지막으로 변경된 날짜와 시간을 나타내는 HTTP 헤더 (요청 헤더)
- 불필요한 응답을 줄여줍니다
흐름
- 클라이언트가 자원을 요청합니다.
- 서버는 리소스의 가장 최신에 있었던 수정 날짜를 Last-Modified 헤더로 응답합니다.
- 클라이언트는 다음 요청 시, 응답받은 Last-Modified 헤더값을 If-Modified-Since 헤더에 포함시켜 요청합니다.
- 서버는 이 값과 리소스의 최근 수정 시각을 비교하고, 변경되지 않았다면 304 응답 코드를 내려줍니다.
예제) 자원 요청하기
더보기
더보기
GET /resource
200 OK
Last-Modified: Fri, 12 Apr 2024 12:00:00 GMT
GET /resource
If-Modified-Since: Fri, 12 Apr 2024 12:00:00 GMT
304 Not Modified
Spring
- WebRequest, HttpServletRequest는 If-Modified-Since 헤더를 접근 기능을 제공합니다.
예제) HttpServletRequest
더보기
더보기
@GetMapping("/api/book/{id}")
public ResponseEntity<Book> getBook(@PathVariable Long id, WebRequest request) {
Book book = findBook(id);
long lastModified = book.getUpdatedAt().toEpochMilli();
if (request.checkNotModified(lastModified)) {
return ResponseEntity.status(HttpStatus.NOT_MODIFIED).build();
}
return ResponseEntity
.ok()
.lastModified(lastModified)
.body(book);
}
3. ETag
ShallowEtagHeaderFilter
- 응답 내용을 기반으로 자동으로 ETag를 생성해주는 필터입니다.
설정) WebInitliaizer#onStartup
더보기
더보기
FilterRegistration.Dynamic ETagHeaderFilter = servletContext.addFilter("eTagHeaderFilter", new ShallowEtagHeaderFilter());
ETagHeaderFilter.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), false, "/*");
출처
'Spring > Spring MVC' 카테고리의 다른 글
[Tomcat] 1. Introduction (0) | 2025.04.14 |
---|---|
[Spring MVC] 6. Error Response (0) | 2025.04.12 |
[Spring MVC] 3. HTTP Message Conversion (0) | 2025.04.12 |
[Spring MVC] 2. Filters (0) | 2025.04.11 |
[Spring MVC] 4-3. Handler Methods: Controller Advice (0) | 2023.10.17 |