웹브라우저의 이미지 캐싱 이슈 해결하기

안녕하세요. 화해팀 프론트엔드 개발자 박찬민입니다.

 

얼마 전에 비즈니스 센터의 ‘이미지 다운로드 기능’이 동작하지 않는 문제가 있었습니다. 개인적으로는 처음 겪는 이슈였는데 ‘이런 경우도 있구나!’라는 생각이 들어서 글로 정리하게 되었습니다.

 

 

 

 

어떤 이슈가 발생하는가?

이슈가 발생한 비즈니스 센터의 웹페이지에서는 아래의 기능을 제공했습니다.

  • 이미지를 사용자가 볼 수 있게 화면에서 보여준다.
  • ‘다운로드’ 버튼을 누르면 화면에 보이는 이미지를 다운로드할 수 있다.

 

 

비즈니스 센터 웹페이지 화면

 

 

 

 

일단 화면에는 이미지가 잘 나타났습니다. 그런데 ‘다운로드’ 버튼을 누르면 이미지 다운로드가 계속 실패했습니다. 개발자 도구를 열어서 확인해보니 아래처럼 CORS 이슈로 다운로드가 실패하고 있었습니다.

 

 

 

 

 

 

이슈의 원인이 무엇인가?

일단 원인을 파악하기 위해서 현재 상황을 정리해보았습니다.

  • 이미지 파일은 AWS S3를 이용해서 서빙되고 있다.
  • html의 img 태그에 넣은 이미지 링크는 잘 작동해서 개발자 도구에서 정상적으로 다운로드하는 게 보이고, 화면에도 잘 나타난다.
  • 콘솔 에러 메시지는 CORS 이슈라고 나타난다.
  • 크롬뿐만 아니라 다른 브라우저에서도 같은 이슈가 발생한다.
  • 최근에 작업한 부분이 아니고 오랫동안 문제가 제보된 적 없는 페이지이다.

 

 

특히 에러 메시지 상으로는 CORS 이슈라서 처음에는 파일서버의 Access-Control-Allow-Origin 헤더 설정이 변경되었다고 생각했습니다. 알아보니 S3의 Access-Control-Allow-Origin 헤더 설정은 잘 작성되어 있었고 이와 관련된 수정이나 배포 이력도 없었습니다. 생각해보면 html의 img 태그에서는 이미지가 잘 보이니 이미지를 브라우저로 다운로드하는 것은 문제가 없다는 것이고 파일서버의 설정은 문제가 없다는 것을 의미했습니다.

 

이때부터 조금 당황했습니다. 같은 링크의 이미지 파일인데 html의 img 태그에서는 잘 다운로드가 되고, javascript 내에서 xhr로 다운로드하는 건 에러가 발생하는데 너무 이해되지 않았습니다. img 태그와 xhr의 차이점이 있는 건가 싶어서 검색도 하고 관련 커뮤니티에도 Q&A를 하던 차에 아주 중요한 사실을 깨달았습니다.

 

바로 브라우저가 HTTP 요청을 캐싱할 때는 HTTP 응답 그 자체를 캐싱한다는 것입니다. 많은 경우에 응답의 본문 데이터만 관심을 가지다 보니 간과하고 있었는데 HTTP 응답에는 본문 데이터뿐만 아니라 헤더도 포함되어 있습니다.

 

이에 따르면 img 태그로 다운로드한 이미지를 브라우저가 캐싱할 때 단순히 파일만 캐싱하는 게 아니라 헤더까지 함께 캐싱하게 되는데 img 태그로 이미지를 다운로드할 때는 응답 헤더에 Access-Control-Allow-Origin 정보가 포함되지 않습니다.

 

이슈가 발생한 페이지는 처음에 이미지를 화면에 보이기 위해서 img 태그로 먼저 이미지를 다운받았기 때문에 Access-Control-Allow-Origin 헤더가 없는 채로 이미지가 캐싱 됩니다. 그 이후에 같은 이미지 파일 링크로 xhr 요청을 하니 브라우저 캐싱 데이터를 그대로 쓰는데 거기에는 Access-Control-Allow-Origin 헤더가 없으니 브라우저가 CORS 에러를 발생시키는 것이었습니다.

 

 

 

 

어떻게 해결할 수 있는가?

근본적으로는 img 태그 캐싱 되는 데이터를 xhr로 그대로 사용하는 게 원인이기 때문에 캐싱을 회피하는 여러 가지 방법으로 이슈를 해결할 수 있습니다. 예를 들면, img 태그에 사용하는 파일명과 다운로드에 사용하는 파일명을 다르게 하거나, 이미지 파일의 헤더 설정을 통해서 캐싱이 되지 않게 하는 방법 등이 있을 것입니다.

 

저는 그중에서 단순한 수정으로 빠르게 문제를 해결하는 방법을 선택하였습니다. img 태그에서 사용하는 이미지 링크와 xhr에서 사용하는 이미지 링크를 다르게 만들어서 xhr 요청을 할 때 캐싱 된 이미지를 사용하지 않도록 하여 이슈를 해결하였습니다. 구체적으로는 img 태그의 src에 링크를 넣을 때 Date 정보를 이용한 부가적인 쿼리스트링을 붙였습니다.

 

 

 

 

 

 

이번 이슈를 해결하는 과정에서 (1) 브라우저 캐싱이 이루어지는 대상 데이터의 범위 (2) 브라우저에서의 캐시 데이터 핸들링 방법 (3) xhr을 이용할 때의 캐싱 처리 고려사항에 대해 공부하는 좋은 경험이었습니다.

 

 

 

 


 

 

 

 

 

채용정보 확인하기

 

 

11
by nc nd