반응형

작성일자 : 2020.12.20

환경 : Spring Boot, Chrome

 

1. 개요

1.1) Web Cache(HTTP Cache)란? 

 

  • 서버 지연을 줄이는 목적으로 정적 리소스 등의 웹 문서들을 임시 저장하여 재활용하기 위한 기술
  • 어디에 적용하느냐에 따라 Browser Cache, Proxy Cache, Gateway Cache 로 구분지을 수 있음

 

- 웹 캐싱 방법

  • Response 에 Cache-Control Header 사용

 

 

1.2) Cache-Control ?

  • 서버와 브라우저 사이의 캐시 정책. 여러 지시자들을 사용하여 옵션을 설정할 수 있음 

 

크롬 개발자 도구에서 Cache-Control 헤더를 아래와 같이 확인 가능하다.

 

 

 

- Cache-Control 기본 지시자 

  • no-cache : 캐시 데이터가 있어도 무조건 서버로부터 유효성을 재검증함 (캐시를 사용하지 않는게 아님)
  • no-store : 캐시 데이터를 저장하지 않음 (캐시를 사용하지 않음)
  • max-age=[sec] : 캐시 데이터가 유효한 시간을 설정. 해당 시간이후에 캐시 데이터가 만료 
  • must-revalidate : 만료된 캐시 데이터를 무조건 서버로부터 유효성을 재검증함

 

- 캐싱 데이터 유효성 검증 방법 (ETag 활용)

  1. 브라우저가 서버로 첫 요청시, 서버는 응답에 해당하는 데이터와과 함께 Etag 를 반환 (이 떄 응답 데이터, Etag 는 캐싱)
  2. 브라우저가 서버로 재요청시, If-None-Match 헤더에 캐싱된 Etag 를 담아서 요청 전송
  3. 서버는 신규 요청에 의해 만들어진 Etag 와 If-None-Match  헤더에 담긴 Etag 를 비교하여, 다르면 새로운 Etag 와 함께 응답 반환. 동일하면 304(Not Modified) Return Code 를 반환

  4. 브라우저는 304(Not Modified) Return Code 반환 시 기존 캐싱 데이터를 활용하며, 200 Return Code 로 반환 시, 1. 으로 돌아감

 

 

1.3)  ETag(Entity Tag) ?

  • 웹 리소스의 특정버전에 할당한 식별자

 

- ETag 사용 예시 :

etag 구현체를 필터로 등록하여 사용. 해당 구현체가 필터에 등록되어 Request, Response 에 etag 를 부여/검증한다.

 

@Bean
public FilterRegistrationBean shallowEtagHeaderFilter() {
    FilterRegistrationBean frb = new FilterRegistrationBean();
    frb.setFilter(new ShallowEtagHeaderFilter());
    frb.addUrlPatterns("MY_PATH/*");
    return frb;
}

 

위처럼 ShallowEtagHeaderFilter 를 등록 시 Etag 를 생성 및 검증해주며, Etag 가 존재하면 동일 URI 재요청 시 자동으로 If-None-Match 헤더에 ETag 가 추가해준다.

 

 

2. 적용 예시

 

2.1 Cache Control 활용

 

* WebMvcConfigurer 를 활용하여 정적 리소스 경로를 설정하였다 가정

 

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        CacheControl cacheControl = CacheControl 
                .maxAge(60, TimeUnit.SECONDS) 
                .mustRevalidate();

        registry.addResourceHandler("**/*.js") 
                .addResourceLocations("classpath:/static/")
                .setCacheControl(cacheControl) 
                ;
    }
}

 

: 위 설정 이후, **/*.js 의 요청은 Cache 이 설정됨

 

 

index.html

 

<script src ="http://localhost:8080/test.js"></script>

 

 

- http://localhost:8080/ 첫 요청 시

 

index.html 반환 및 index.html 에 의해 test.js 요청

 

200 응답코드와 함께 설정한 Cache-Control 반환되며 해당 응답은 캐싱된다

 

 

 

- http://localhost:8080/ 두번째 요청 시

 

index.html 반환 및 index.html 에 의해 test.js 요청

 

요청이 캐싱 이후 60초 이내일 경우(max-age=60) 해당 캐시는 유효하다 판단하며 캐싱 데이터를 재사용한다

 

* 이 경우 서버와 통신하지 않기 때문에 데이터가 변경되더라도 브라우저에서는 알 수없음 

* 단 브라우저 URL 입력창에 직접 호출하는 경우, 무조건 서버와 통신하여 변경 여부를 체크 (Chrome)

* from memory cache, from disk cache 두 종류가 있는데, 일반적인 memory, disk 차이와 비슷하다 어디에 저장할지는 Chrome 이 결정 

 

 

 

2.2 Etag 활용

 

shallowEtagHeaderFilter 필터 설정

 

@Bean
public FilterRegistrationBean shallowEtagHeaderFilter() {
    FilterRegistrationBean frb = new FilterRegistrationBean();
    frb.setFilter(new ShallowEtagHeaderFilter());
    frb.addUrlPatterns("/*");
    return frb;
}

 

: 위 설정 이후, /* 의 요청은 Etag 가 설정됨

 

 

Cache-Control 설정

 

@RequestMapping("/")

public void getIndexPage(... HttpServletResponse response)
{

   ...

   response.setHeader("Cache-Control","no-cache");

   ...

}

 

 

 

 

- http://localhost:8080/ 첫 요청 시

 

Etag 와 함께 응답 반환

 

 

 

- http://localhost:8080/ 두번 째 요청 시

 

Request 에  Etag 를 함께 전송

 

 

 

Etag 검증 후 Not Modified(304) 반환

 

 

반응형

'Java' 카테고리의 다른 글

[SpringBoot] Gradle 변수 Property 활용  (0) 2022.05.30
[MyBatis] List 형식 멤버 변수 조회  (0) 2021.02.12
[SpringBoot] H2 연동  (0) 2020.07.21
[Spring] App 구동 후 자동 작업 실행  (0) 2020.02.23
Stream Example  (0) 2020.01.05

+ Recent posts