캐시(Cache)는 다운로드 받은 데이터나 값을 미리 복사해 놓는 임시 장소를 뜻하며, 데이터에 접근하는 시간이 오래 걸리는 경우나 값을 다시 계산하는 시간을 절약하고 싶은 경우에 사용한다.
브라우저 캐시를 활용하면 다음과 같은 효과를 볼 수 있다.
캐시 유효 시간은 지났지만, 서버에서 다시 받아와야하는 파일이 캐시에 저장되어 있는 파일과 완전히 동일한 경우, 이때도 똑같은 파일을 다시 받아와야하는 경우가 발생한다.
이럴 땐 유효 시간이 지났다고해도 굳이 똑같은 파일을 다시 받아올 필요 없이 서버의 파일과 캐시의 파일이 동일한지 확인해서 재사용하면 더 효율적이다.
이런 상황에서 사용할 수 있는 HTTP 헤더들이 존재한다.
캐시에 저장된 데이터와 서버의 데이터가 동일한지 확인하기 위한 정보를 담은 응답 헤더
Last-Modified
: 데이터가 마지막으로 수정된 시점을 의미하는 응답 헤더로, 조건부 요청 헤더인 If-Modified-Since
와 묶어서 사용합니다.Etag
: 데이터의 버전을 의미하는 응답 헤더로, 조건부 요청 헤더인 If-None-Match
와 묶어서 사용합니다.캐시의 데이터와 서버의 데이터가 동일하다면 재사용하게 해달라는 의미의 요청 헤더
If-Modified-Since
: 캐시된 리소스의 Last-Modified
값 이후에 서버 리소스가 수정되었는지 확인하고, 수정되지 않았다면 캐시된 리소스를 사용합니다.If-None-Match
: 캐시된 리소스의 ETag
값과 현재 서버 리소스의 ETag
값이 같은지 확인하고, 같으면 캐시된 리소스를 사용합니다.말 그대로 나무를 흔들어 잔가지를 털어내듯 불필요한 코드를 제거하는 것을 의미한다.
JavaScript 파일 크기의 증가, 요청 횟수의 증가는 그만큼 파일이 오고 가는 동안 화면 표시가 늦어진다는 것을 뜻하고, 네트워크 속도가 느린 환경에서는 더 큰 병목현상을 유발한다.
따라서 트리쉐이킹을 통해 파일 크기를 가능한 줄이는 것이 최적화에 도움이 된다.
JavaScript 파일이 실행되기 위해서는 여러 과정을 거치게 된다.
다운로드부터 필요한 경우에는 우선 요청을 보내어 파일을 다운받아 온 다음 압축을 해제해야 한다.
그다음에는 JavaScript 코드를 파싱하여 DOM 트리를 생성하고, 파싱이 끝나면 컴파일하여 컴퓨터가 이해할 수 있는 언어로 바꿔줘야 합니다. 이 컴파일 과정까지 거쳐야지 비로소 코드를 실행할 수 있습니다.
이처럼 코드 실행까지 거쳐야 하는 과정이 많기 때문에 JavaScript는 다른 리소스에 비해서 실행까지 상대적으로 많은 시간을 소모하게 된다.
import
구문을 사용해서 라이브러리를 불러와서 사용할 때, 라이브러리 전체를 불러오는 것이 아니라 필요한 모듈만 불러오면 번들링 과정에서 사용하는 부분의 코드만 포함시키기 때문에 트리쉐이킹이 가능해집니다.
import { useState, useEffect } from 'react'
그러면 불러오지 않은 코드는 빌드할 때 제외되므로 코드의 크기를 줄일 수 있게 된다.
Babel은 자바스크립트 문법이 구형 브라우저에서도 호환이 가능하도록 ES5 문법으로 변환하는 라이브러리이다.
이 때 ES5문법은 import
를 지원하지 않기 때문에 commonJS 문법의 require
로 변경시키는데, 이 과정은 트리쉐이킹에 큰 걸림돌이 된다.
이를 방지하기 위해서 Barbelrc 파일에 다음과 같은 코드를 작성해주면 ES5로 변환하는 것을 막을 수 있다.
{
“presets”: [
[
“@babel/preset-env”,
{
"modules": false
}
]
]
}
반대로, modules
값을 true
로 설정하면 항상 ES5 문법으로 변환하므로 주의해서 작성해야 한다.
웹팩은 사이드 이펙트를 일으킬 수 있는 코드의 경우, 사용하지 않는 코드라도 트리쉐이킹 대상에서 제외시킵니다.
package.json 파일에서 sideEffects
를 설정하여 사이드 이펙트가 생기지 않을 것이므로 코드를 제외시켜도 됨을 웹팩에게 알려줄 수 있다.
다음과 같이 작성하면 애플리케이션 전체에서 사이드 이펙트가 발생하지 않을 것이라고 알려준다.
{
"name": "tree-shaking",
"version": "1.0.0",
"sideEffects": false
}
혹은 아래와 같이 작성하여 특정 파일에서는 발생하지 않을 것임을 알려줄 수 있다.
{
"name": "tree-shaking",
"version": "1.0.0",
"sideEffects": ["./src/components/NoSideEffect.js"]
}
ES5 문법을 사용하는 모듈을 통째로 사용하는 상황이라면 상관없지만, 일부만 사용하는 경우라면 해당 모듈을 대체할 수 있으면서 ES6를 지원하는 다른 모듈을 사용하는 것이 트리쉐이킹에 유리하다.
ES6 문법을 사용하는 모듈을 사용하면 해당 모듈에서도 필요한 부분만 import
해서 사용하지 않는 코드는 빌드할 때 제외되기 때문이다.