반응형

현재 제가 운영하는 devlogmoa 서비스는 캐시처리가 필요할만큼 많은 파일이 존재하지는 않습니다.
하지만 okky에서 피드백을 받게되어 이참에 한 번도 해보지 못했던 캐싱 처리를 해보려고 합니다.
(캐시란??)

✔️ 무엇을 캐싱할까?

아주 간단하지만 사진과 같이 bootstrap.css와 bootstrap.js를 캐시 정책을 적용하려고 합니다. 이런 정적파일은 자주 변화가 일어나지 않는 것이기 때문에 굳이 매번 서버에서 가져올 필요 없습니다.
지금은 파일이 몇개 없어 성능에 영향이 없겠지만, 네이버 같이 방대한 양의 정적파일이 존재한다면, 성능에 영향을 끼치게 됩니다.
일단 캐시 사용 전의 상태를 보겠습니다.
보시는 바와 같이 재접속을 계속해도 Cache-Control이 no-store로 되어있습니다.

✔️ 캐시정책

캐시는 http 응답헤더에 있는 Cache-Control로 통신하게 됩니다.

  • no-store : 캐시사용 안함.
  • no-cache : 매번 서버에 바뀐 내용이 있는지 확인하여 바뀐 내용이 있다면 가져오고, 없다면 그대로 사용
  • max-age : 캐시 유지 시간을 초단위로 정하고, 정한 시간만큼 캐시를 사용하고,
    만료되면, 다시 서버에 재요청하여 304를 반환 받아 해당 데이터를 사용하고,
    바뀐 내용이 없다면, 일부만 가져와 사용하게 됩니다.
    0으로 설정하면 no-cache와 동일한 기능을 하게 됩니다.
  • must-revalidate : no-cache 정책을 프록시 서버에 요청하는 것입니다.
    (이해가 잘 안되어, 그냥 넘어가겠습니다.)

캐시를 사용하지 않기 위해서는 아래와 같이 해주는 것이 완벽한 방지법입니다.
Cache-Control: no-cache, no-store, must-revalidate

✔️ 캐시 적용하기

🔍 구현코드

package com.devlogmoa.config;

import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.CacheControl;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.concurrent.TimeUnit;

@RequiredArgsConstructor
@Configuration
public class WebConfig implements WebMvcConfigurer {

    // 캐시 정책 적용
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        CacheControl cacheControl = CacheControl
//                .noCache();
                .maxAge(5, TimeUnit.SECONDS);

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

🔍적용된 내용 확인하기(maxAge)

maxAge(5, TimeUnit.SECONDS);를 이와 같이 설정했습니다.
5초동안은 브라우저에 있는 캐시를 사용하고 이후에는 서버에 재요청을 하여 변경내용이 있는지 확인하게 됩니다.
아래 사진에서 Cache-Control을 보면 max-age=5라고 되어있습니다.

처음 접속 시 200코드를 반환하고, 실제 데이터를 가져옵니다.
파일 사이즈를 봐도 온전하게 다 가져오게 됩니다.

이제 여기서 재접속을 하게되면 5초 이전에는 동일하게 200을 반환합니다.
하지만 파일 사이즈는 없습니다(memory cache). 캐시를 사용했기 때문입니다.
즉, 서버에서 가져온 파일이 아닙니다.

다시 재접속을 하면 304코드를 반환합니다.
설정한 5초가 지났으므로 서버에 재요청을 하게됩니다.
하지만 사이즈가 이전과 다르게 굉장히 작습니다. 이유는 변경된 내용이 없기 때문에
서버에서 전부 가져온 것이 아니기 때문입니다.

응답헤더의 Last-Modified, 요청헤더의 if-Modeified-Since를 보면
일자가 있습니다. 이걸로 판단을 하게 되고, 동일하기 때문에 변경된 내용이 없다고 판단하게 됩니다.
그로인해 서버에서 본문 데이터를 가져오지 않고, 헤더 데이터만 사용하기 때문에 사이즈가 굉장히 작은 것입니다.

🔍적용된 내용 확인하기(no-cache)

no-cache로 설정 시 max-age=0과 동일하기 때문에 크게 다른 점은 없습니다.
다만 다른 점은 memory cache를 사용하지 않고, 매번 요청을 하기 때문에
소량의 데이터만 사용합니다. 즉 304를 매번 응답 받습니다.

🔍 E-Tag

아직 여기까지 알 필요가 없어서 간단하게만 알아보겠습니다.

  • 수정 시간을 시분초로만 판단하면 안되는 경우 사용하게 됩니다. 더 정밀한 상황에 필요한 것입니다.
  • 최근 수정된 날짜로 비교하게 되면 컨텐츠를 A -> B -> A로 변경하면 컨텐츠가 변경되었다고 인식하게 된다. 이 같은 문제를 해결하기 위해
    E-Tag에 해시 알고리즘과 같이 컨텐츠의 내용에 따라 키를 발급하여 저장하게 된다.
    그리고 브라우저는 요청 헤더의 if-None-Match에 E-Tag를 전달하고 E-Tag의 키로 판단을 하게 되어 이슈를 해결할 수 있다.
    E-Tag가 같다면 304를 반환하게 된다.

🔍 정책 결정 기준은?

요기 참고!!

참고

생활코딩
개인 블로그

반응형
복사했습니다!