[프론트엔드 성능 최적화] (6)

yongkini ·2023년 1월 31일
0

캐시 최적화

: 이부분은 http 관련한 설정으로 이뤄지는 파트이다. 사실 캐시 최적화 같은 경우에는 과거 이미지 사이즈 최적화와 유사하게 백엔드 쪽에서 해줄 작업이긴 하다. 애초에 브라우저에서 캐싱이란

  • 디스크 캐시
  • 메모리 캐시(RAM 메모리)

이렇게 두가지로 나뉘는데, 브라우저 단에서 알아서 처리를 하기 때문에 개발자가 어떻게 컨트롤 할 수 없는 영역이긴 하다(물론 다른 캐싱과 웹개발을 두고 보면 다른 방법들이 있긴하다).

왜 캐싱을 해야할까?

: 사람들도 쓸데없는 반복을 싫어한다. 어제 공부하고 완벽히 숙지했다고 생각되는 부분이 있을때(물론 불가능하지만,,) 다음날 그부분을 또 가르치고, 그 다음날 그 부분을 또 가르친다면 어떨까?. 비싼 돈 주고 쓸데없는 시간을 보내고 있다고 생각이 들 수 있다. 이렇듯 캐싱 또한 서버로부터 브라우저가 데이터를 받아올 때 이미 브라우저에서 다운을 받았던 것과 똑같은 것을 또 보내준다면 이러한 동일 파일의 다운로드는 일종의 리소스 낭비가 될 것이다. 이에 따라 이러한 낭비를 막기 위해 지난번 데이터와 같은 데이터를 다운받으려고 하는 경우 지난번 데이터와 동일한 경우에는 지난번에 다운받아놨던 것을 쓰는(다시 다운을 받지 않는) 것이 더 효율적일 것이다.

어떻게 캐싱을 하면 되나?

: 위에서 말한 것처럼 캐싱은 브라우저가 디스크 캐시, 메모리 캐시 중 선택하여(혹은 비율적으로 나눠서) 알아서 처리를 하는 것이고, 개발자 선에서 할 수 있는건 특정 데이터에 대해서 캐싱을 할지 말지 그리고 캐싱을 한다면 어느 정도 기간동안 캐싱을 할 것인지 등이다.

이에 따라 백엔드에서 response headerCache-Control 세팅을 해줘야 한다. 아래는 Cache-Control의 구체적인 옵션들이다.

  • no-cache : 이름만 보면 캐싱을 하지 않는 것처럼 보일 수 있으나, 실제 의미는 계속해서 서버로 이 데이터가 최신 데이터인지를 확인하고, 최신이라면 다시 다운로드 받고, 그렇지 않으면 캐싱된 데이터를 쓰도록 하는 옵션이다. 캐싱할 데이터는 최대한 static한 데이터를(변동 가능성이 적은) 하는 것이 좋은데, no-cache 옵션의 경우 그렇지 않은 대상에 주로 쓴다(끊임없이 변동성을 체크해야하는 자료).
  • no-store : 이 옵션이 캐싱을 하지 않는다는 옵션이다.
  • public : 프론트 - 백엔드 사이에 api를 보내고, response를 돌려주고 하는식으로 소통하는데 중간에, 예를 들어, CDN 등이 끼게 되면 다양한 중간 매개자가 생기게 된다. 이 때, 캐시를 사용하냐의 측면에서 중간의 CDN 등이 다른 매개체에도 캐시를 허용할거면 public을 옵션으로 해준다.
  • private : 위의 public과는 대조적으로 중간자를 허락하지 않고 브라우저 환경에서만 캐시를 사용하도록 허용한다. 외부 캐시 서버에서는 사용할 수 없도록 하는 옵션이다.
  • max-age : 위에서 말했듯이 캐싱을 만약 쓸거라면 얼마동안 그 데이터를 유지할건지를 세팅해줘야하는데(안하면 null) 그 옵션이 max-age이다(캐시의 유효기간).

그래서 실제 백엔드에서 header에 Cache-Control을 세팅해줄 때 아래와 같은 방법으로 한다.

Cache-Control : private, max-age=60

이 때,

Cache-Control : public, max-age=0

위와 같이 해주면 모든 서버에서(public) 캐시의 유효기간을 0초(초단위로 입력한다)로 세팅하는 것으로, 결과적으로 매번 현재 캐싱된 데이터가 최신인지 체크하도록 하는 옵션이다. 즉, 위의 no-cache 옵션과 결과적으로 같은 로직이다(캐시를 사용하기 전에 서버에 검사후에 사용하는 것).

실제 적용시

const header = {
	setHeaders: (res, path) => {
    	res.setHeader('Cache-Control', 'max-age=10');    
    }
}

NODEJS를 백엔드로 쓴다고 했을 때 위에 처럼 header 세팅에 cache-control을 세팅해줄 수 있다.

이 때, 보통은 HTML에 대한 캐시 옵션으로

res.setHeader('Cache-Control', 'no-cache');    

를 써준다. html 의 경우 SPA인 리액트로 치면 핵심이 되는 로직이 모두 들어가 있기 때문에(js, css에 로직이 들어있다 했을 때 결국 이 js, css도 html에서 load한다), 매번 서버에 최신인지를 체킹해줘야한다. 하지만, 방금 말한 js, css 등은 변경 사항이 생기면 build를 할 때 unique한 이름으로 갱신이 되기 때문에(파일명 자체가 바뀜) html만 no-cache로 해뒀다면 load하는 파일명 자체가 바뀌기에 따로 최신인지를 체크할 필요가 없다. 그래서 js, css는 캐시의 유효기간을 무한정을 해놔도 상관이 없다.

res.setHeader('Cache-Control', 'public, max-age=31536000');    

그리고 그 외에 파일들(캐시를 적용하지 않을 것들)에 대해서는 no-store를 써준다

res.setHeader('Cache-Control', 'no-store');    

결론적으로 위에서 구두로 말한 내용을 간략하게 코딩해보면 아래와 같다.

const header = {
  setHeaders: (res, path) => {
    if (path.endsWith(".html")) {
      res.setHeader("Cache-Control", "no-cache");
    } else if (
      path.endsWith(".js") ||
      path.endsWith(".css")
    ) {
      res.setHeader("Cache-Control", "public, max-age=3153600");
    } else {
      res.setHeader("Cache-Control", "no-store");
    }
  },
};

결론

: ngnix 등으로 fe 빌드 파일을 배포할 때 위와 같은 캐시 컨트롤을 해주면 초기 로딩 속도 최적화를 할 수 있다. 물론 처음 홈페이지를 방문할 경우에는 캐시된 내용이 없겠지만 말이다.

profile
완벽함 보다는 최선의 결과를 위해 끊임없이 노력하는 개발자

0개의 댓글