잉크링크 서비스 중 기존의 사용자에게 제공되는
해당 포스팅은 원인 분석과 문제 해결을 중심으로 포스팅을 진행했습니다.
책(pdf)
을 S3
에 업로드pdf
에 접근S3
에 재 업로드(파일명 동일)pdf
에 접근 할 때 수정되지 않은 기존의 pdf
를 제공받음
S3
의 저장된 객체에 대한 캐싱 정책을 적용하지 않았기 때문 !
사용자는 기존에 제공된 pdf
파일이 브라우저에 캐싱이 되어 있어서 아무리 pdf
파일을 수정하더라도 객체 URL이 동일했기 때문에 수정된 파일이 제공되지 않았습니다.
객체 메타데이터
이름-값
페어의 집합으로 객체에 대한 추가 정보를 의미합니다.Cache-Control
이 있는데 이를 통해 객체의 캐싱 정책을 추가할 수 있습니다.Cache-Control 헤더
Cache-Control
는 일반 헤더 필드로, 요청/응답 체인의 모든 캐싱 메커니즘에 반드시 따라야 할 지시문을 지정하는 데 사용됩니다. 이 헤더는 요청이나 응답이 캐싱 방해를 받지 않도록 설계되어있습니다.Cache-Control
헤더는 요청과 응답에 각각 독립적으로 적용됩니다. 요청에 포함된 특정 지시어가 응답에 동일하게 포함되지 않습니다.Cache-Control
는 요청/응답 체인의 모든 수신자에게 적용될 수 있으며, 프록시 서버나 게이트웨이를 통해서도 전달되어야 합니다. 특정 캐시 대상에 대한 지시어를 지정할 수는 없으며, 지시어는 전체 네트워크 경로에 걸쳐 적용됩니다.Cache-Control Directives
여기서 사용할 캐시 지시어는 no-cache
, no-store
, must-revalidate
입니다.
no-cache
no-store
must-revalidate
지시어들을 정리하면서
왜 3개를 같이 사용할까 ?
라는 궁금증이 생겼고 정리해 보았습니다.보안이 중요한 경우
no-store
만 사용하여 데이터가 전혀 저장되지 않도록 할 수 있고
no-cache
,must-revalidate
를 함께 사용해 항상 최신 데이터만 사용되도록 할 수 있습니다.3개를 같이 사용하는 이유
1. 복합적인 요구 사항 충족 : 서비스를 운영하면서 다양한 유형의 데이터와 상호작용을 처리하기 때문에 여러 지시어를 함께 사용하여 각기 다른 캐싱 이슈에 대응하기 위해서
2. 예측 불가능한 사용 환경 : 클라이언트의 환병(ex: 브라우저, 프록시 서버 등)에서 다르게 해석하거나 적용할 수 있기 때문에, 서버 측에서 보다 명확하게 캐싱 정책을 지시하기 위해 여러 지시어를 함께 사용합니다.
다양한
Cache-Control
을 설정한다면
rfc7234 - 공식문서, W3 공식문서 - sec14.9.2를 참고하시면 좋을 것 같아요 !
캐시를 사용하지 않는 경우 증가된 대기 시간
, 높은 네트워크 트래픽
, 비용 증가
, 서버 부하 증가
, 스케일링 문제
가 있습니다. 캐시 제어를 완전히 비활성화 하는 대신, 적절한 캐시 유효 시간(max-age)을 설정하거나, 콘텐츠의 변경을 감지할 수 있는 다른 메커니즘(ex:ETag, Last-Modified 헤더)을 활용할 수 있습니다.
저희 서비스에서는 관리자가 파일을 업로드할 때
no-cache
,no-store
,must-revalidate
지시어를 사용하여 객체의 메타데이터 캐시를 비활성화하였습니다.캐시를 사용하지 않을 경우 단점이 존재하지만, 제공되는 파일은 주로 다운로드 목적으로 접근되기 때문에, 사용자의 접근 빈도가 높지 않을 것으로 예상되어 캐시 제어를 비활성화 하였습니다.
이를 통해 파일이 잘못 업로드되었을 경우 수정 후 즉시 사용자에게 최신 버전을 제공할 수 있습니다.
특정 콘텐츠가 브라우저 캐시 사용 여부는
시스템 제어
또는사용자 제어
의 방법이 있고 두 방법 모두 포스팅해보겠습니다.
시스템 제어는 S3 객체에 직접 메타데이터를 편집하는 방법입니다 !
객체 선택
->메타데이터 편집
메타데이터 추가
시스템 정의
키
:Cache-Control
값
:max-age=0
,no-cache
,no-store
,must-revalidate
private String ebookToS3(String key, MultipartFile file, String mimeType) throws IOException {
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentType(mimeType);
metadata.setContentLength(file.getSize());
metadata.setCacheControl("no-cache, no-store, must-revalidate, max-age=0");
amazonS3Client.putObject("inklink-bucket", key, file.getInputStream(), metadata);
return defaultUrl + key;
}
위 코드에서
metadata.setCacheControl("no-cache, no-store, must-revalidate, max-age=0");
를 통해 S3
객체에 대한 캐시 제어 정책을 설정하였습니다.
해당 설정으로 클라이언트 측에서 해당 객체를 캐시하는 것을 완전히 비활성화하여, 매번 원 서버에서 최신 버전의 데이터를 확인하도록 설정하였습니다.
참고 자료
AWS 공식문서 - S3
AWS 공식문서 - CloudFront
rfc7234 - 공식문서
W3 공식문서 - sec14.9.2