λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
CS/λ„€νŠΈμ›Œν¬

What's in my bΜΆaΜΆgΜΆ Browser

by kriorsen 2024. 9. 8.

πŸ“Œ μ›Ή μ‚¬μ΄νŠΈκ°€ 빨라야 ν•˜λŠ” 이유


λŠ” ꡳ이 ꡬꡬ절절 말둜 μ„€λͺ…ν•  ν•„μš”κ°€ 없을 μ •λ„λ‘œ λͺ…ν™•ν•˜λ‹€. 화면에 λ‘œλ”© μ•„μ΄μ½˜μ΄ λΉ™κΈ€λΉ™κΈ€ νšŒμ „ν•˜λŠ” 것을 κ΅¬κ²½ν•˜λŠ” μ·¨λ―Έκ°€ μžˆλŠ” μ‚¬λžŒμ€ μ•„λ§ˆ 없을 것이닀. λ•Œλ¬Έμ— μ›Ή κ°œλ°œμžλ“€μ€ μ‚¬μš©μž κ²½ν—˜ κ°œμ„ κ³Ό μ „ν™˜μœ¨ 증가λ₯Ό μœ„ν•΄ μ„±λŠ₯ ν–₯상에 λ§Žμ€ λ…Έλ ₯을 κΈ°μšΈμΈλ‹€.

 

πŸ“Œ HTTP Caching


μΊμ‹œ(not ν˜„κΈˆ)λž€

μΊμ‹œλŠ” ν”„λž‘μŠ€μ–΄ 단어 "Cacher"μ—μ„œ μœ λž˜λ˜μ—ˆλ‹€. "Cacher"λŠ” 감좔닀 λ˜λŠ” μˆ¨κΈ°λ‹€λΌλŠ” 의미λ₯Ό 가진닀. 

 

μΊμ‹œλŠ” 데이터λ₯Ό μΌμ‹œμ μœΌλ‘œ μˆ¨κΈ°κ±°λ‚˜ λ³΄κ΄€ν•˜λŠ” κ°œλ…μ—μ„œ μœ λž˜ν•˜μ—¬, 데이터λ₯Ό λΉ λ₯΄κ²Œ μ ‘κ·Όν•  수 μžˆλ„λ‘ μˆ¨κ²¨λ†“μ€ μž„μ‹œ μ €μž₯μ†Œλ₯Ό κ°€λ¦¬ν‚€λŠ” μš©μ–΄λ‘œ μ‚¬μš©λ˜κ³  μžˆλ‹€. μΊμ‹œλŠ” 자주 μ‚¬μš©λ˜λŠ” λ°μ΄ν„°λ‚˜ μžμ›μ„ μž„μ‹œλ‘œ μ €μž₯ν•΄ 두어, λ™μΌν•œ λ°μ΄ν„°λ‚˜ μžμ›μ— λŒ€ν•œ μš”μ²­μ΄ μžˆμ„ λ•Œ λ°”λ₯΄κ²Œ 응닡할 수 μžˆλ„λ‘ λ•λŠ”λ‹€. μΊμ‹œλ₯Ό μ΄μš©ν•˜λ©΄ 데이터 μ ‘κ·Ό 속도λ₯Ό ν–₯상, μ„œλ²„μ˜ λΆ€ν•˜λ₯Ό 쀄이며, λ„€νŠΈμ›Œν¬ λŒ€μ—­ν­μ„ μ ˆμ•½ν•  수 μžˆλ‹€.

 

HTTP 캐싱

HTTP 캐싱은 μ›Ή μžμ›μ˜ μ„±λŠ₯을 μ΅œμ ν™”ν•˜κΈ° μœ„ν•œ 기술둜, 기본적으둜 μ„œλ²„μ˜ 응닡을 ν΄λΌμ΄μ–ΈνŠΈ λ˜λŠ” 쀑간 μΊμ‹œ μ„œλ²„μ— μ €μž₯ν•˜κ³  λ™μΌν•œ μš”μ²­μ΄ λ“€μ–΄μ˜¬ λ•Œ μ €μž₯된 응닡을 μž¬μ‚¬μš©ν•˜λŠ” 방식이닀. 이λ₯Ό 톡해 μ„œλ²„μ˜ λΆ€ν•˜λ₯Ό 쀄이고 νŽ˜μ΄μ§€ λ‘œλ”© 속도λ₯Ό κ°œμ„ ν•  수 μžˆλ‹€.

 

Private Caches

Private cacheλŠ” νŠΉμ • ν΄λΌμ΄μ–ΈνŠΈμ™€ μ—°κ²°λœ μΊμ‹œλ‘œ, λŒ€ν‘œμ μΈ μ˜ˆμ‹œλŠ” λΈŒλΌμš°μ € μΊμ‹œκ°€ μžˆλ‹€. λ‹€λ₯Έ ν΄λΌμ΄μ–ΈνŠΈμ™€ κ³΅μœ λ˜μ§€ μ•ŠλŠ” μ‘λ‹΅μ΄λ―€λ‘œ, μ‚¬μš©μž λ§žμΆ€ν˜• 섀정이 반영된 νŽ˜μ΄μ§€ μ½˜ν…μΈ λ₯Ό μ €μž₯ν•˜κΈ°μ—λ„ μœ μš©ν•˜λ‹€. 응닡 헀더에 λ‹€μŒκ³Ό 같은 섀정을 톡해 private cacheλ₯Ό ν™œμ„±ν™”ν•  수 μžˆλ‹€.

Cache-Control: private

Shared Cache

Shared cacheλŠ” ν΄λΌμ΄μ–ΈνŠΈμ™€ μ„œλ²„ 사이에 μœ„μΉ˜ν•˜μ—¬, μ—¬λŸ¬ ν΄λΌμ΄μ–ΈνŠΈ 간에 응닡을 κ³΅μœ ν•  수 μžˆλŠ” μΊμ‹œμ΄λ‹€. 이 방식은 λ„€νŠΈμ›Œν¬ νŠΈλž˜ν”½μ„ 쀄이고, μ„œλ²„ λΆ€ν•˜λ₯Ό κ°μ†Œμ‹œν‚¨λ‹€λŠ” μž₯점이 있으며, ISP μΊμ‹œ, CDN 등이 이에 ν•΄λ‹Ήν•œλ‹€.

 

 

μ•žμ„  μ„€λͺ…에 따라, Private CacheλŠ” λΈŒλΌμš°μ €μ— μ €μž₯되고, Shared CacheλŠ” ν”„λ‘μ‹œλ‚˜ CDN, λ¦¬λ²„μŠ€ ν”„λ‘μ‹œ 등에 μΊμ‹œλ˜μ–΄ μžˆλŠ” 것을 확인할 수 μžˆλ‹€.

 

 

πŸ“Œ Heuristic caching


HTTP 캐싱은 Cache-Control 헀더 λͺ…μ‹œλ₯Ό 톡해 지정할 수 μžˆλŠ”λ°, 이 헀더가 λͺ…μ‹œλ˜μ§€ μ•Šμ€ κ²½μš°μ—λ„ μžμ›μ„ μΊμ‹œν•˜κ³  μž¬μ‚¬μš©ν•˜κΈ° μœ„ν•œ 방법이 λ°”λ‘œ νœ΄λ¦¬μŠ€ν‹± 캐싱이닀. νœ΄λ¦¬μŠ€ν‹± 캐싱은 μΊμ‹œ 만료 μ‹œκ°„μ„ λͺ…μ‹œμ μœΌλ‘œ μ„€μ •ν•˜μ§€ μ•Šμ€ μžμ›μ— λŒ€ν•΄μ„œλ„ 일정 κΈ°κ°„ λ™μ•ˆ μžλ™μœΌλ‘œ μΊμ‹œλ₯Ό μ μš©ν•œλ‹€.

 

νœ΄λ¦¬μŠ€ν‹± μΊμ‹±μ˜ λ™μž‘ 원리

  1. 응닡 μ €μž₯: HTTP 응닡이 Cache-Control 헀더 없이 λ°˜ν™˜λœ 경우, μ‘λ‹΅μ˜ Last-Modified 헀더와 같은 정보λ₯Ό λ°”νƒ•μœΌλ‘œ, μΊμ‹œκ°€ 적용될 수 μžˆλŠ”μ§€ νŒλ‹¨ν•œλ‹€.
  2. μžλ™ 만료 κΈ°κ°„ μ„€μ •: μ‘λ‹΅μ˜ μ—…λ°μ΄νŠΈ λ‚ μ§œκ°€ 였래된 경우, 응닡이 일정 κΈ°κ°„ λ™μ•ˆ μœ νš¨ν•  κ²ƒμœΌλ‘œ μΆ”μ •ν•˜κ³ , μ μ •ν•œ 만료 κΈ°κ°„(일반적으둜, 응닡 μ €μž₯ μ‹œμ μ—μ„œλΆ€ν„°μ˜ μ‹œκ°„μ˜ μ•½ 10% 정도)을 μ„€μ •ν•œλ‹€.
  3. μΊμ‹œ μž¬μ‚¬μš©: ν΄λΌμ΄μ–ΈνŠΈλŠ” μ§€μ •λœ 만료 κΈ°κ°„ λ™μ•ˆ μ €μž₯된 응닡을 μž¬μ‚¬μš©ν•˜κ³ , 만료된 κ²½μš°μ—λŠ” μ„œλ²„μ— 응닡을 μš”μ²­ν•œλ‹€.

 

예λ₯Ό λ“€μ–΄, μ›Ή λΈŒλΌμš°μ €κ°€ μ„œλ²„λ‘œλΆ€ν„° μœ„μ™€ 같은 응닡을 λ°›μ•˜λ‹€λ©΄, Last-Modified 헀더가 3λ…„ μ „ λ‚ μ§œλ₯Ό λ‚˜νƒ€λ‚΄κΈ°μ— μΊμ‹œλœ 응닡이 상당 κΈ°κ°„ λ™μ•ˆ μœ νš¨ν•˜λ‹€κ³  μΆ”μ •ν•˜μ—¬ μž¬μ‚¬μš©ν•œλ‹€.

 

πŸ“Œ μœ ν–‰μ— λ’€μ²˜μ§€μ§€ μ•ŠλŠ” ν΄λΌμ΄μ–ΈνŠΈκ°€ λ˜λŠ” 법


If-Modified-Since

ν΄λΌμ΄μ–ΈνŠΈκ°€ λ§ˆμ§€λ§‰μœΌλ‘œ 응닡을 받은 μ‹œμ μ„ μ„œλ²„μ— μ „λ‹¬ν•˜μ—¬, κ·Έ μ‹œμ  이후에 λ¦¬μ†ŒμŠ€κ°€ μˆ˜μ •λ˜μ—ˆλŠ”μ§€ ν™•μΈν•˜λŠ” 방식이닀.

 

1. ν΄λΌμ΄μ–ΈνŠΈλŠ” μ„œλ²„λ‘œλΆ€ν„° 받은 응닡을 μ €μž₯

2. 응닡이 1μ‹œκ°„(Cache-Control의 max-ageκ°€ 1μ‹œκ°„)을 λ„˜μœΌλ©΄ stale μƒνƒœκ°€ 되며, ν΄λΌμ΄μ–ΈνŠΈλŠ” λ³€κ²½ 사항을 ν™•μΈν•˜κΈ° μœ„ν•΄ λ‹€μŒκ³Ό 같은 μš”μ²­μ„ 전솑

3. μ„œλ²„λŠ” μ½˜ν…μΈ κ°€ λ³€κ²½λ˜μ§€ μ•Šμ•˜λ‹€λ©΄ 304 Not Modified μƒνƒœ μ½”λ“œλ‘œ μ‘λ‹΅ν•˜κ³ , λ³€κ²½ 사항이 μžˆλ‹€λ©΄ 200 OK와 ν•¨κ»˜ μ΅œμ‹  μ½˜ν…μΈ λ₯Ό μ‘λ‹΅μœΌλ‘œ λ°˜ν™˜

ETag/If-None-Match

μ„œλ²„λŠ” 응닡 본문에 λŒ€ν•œ ν•΄μ‹œκ°’ λ˜λŠ” 버전 번호 λ“±μœΌλ‘œ ETag에 λŒ€ν•œ 값을 생성할 수 μžˆλ‹€. ν΄λΌμ΄μ–ΈνŠΈλŠ” 이 값을 μ‚¬μš©ν•˜μ—¬ μ„œλ²„μ— λ¦¬μ†ŒμŠ€ μˆ˜μ • μ—¬λΆ€λ₯Ό ν™•μΈν•˜λŠ” 방식이닀. Last-Modified 헀더λ₯Ό μ‚¬μš©ν•˜λŠ” 경우 λ‚ μ§œ ν˜•μ‹μ€ λ³΅μž‘ν•˜κ³  νŒŒμ‹±ν•˜κΈ° μ–΄λ ΅κ³ , λΆ„μ‚° μ„œλ²„ ν™˜κ²½μ—μ„œλŠ” 파일 μˆ˜μ • μ‹œκ°„μ„ λ™κΈ°ν™”ν•˜κΈ° μ–΄λ €μš΄ λ¬Έμ œλ“€μ„ ν•΄κ²°ν•΄ μ€€λ‹€.

 

1. μ„œλ²„λ‘œλΆ€ν„° ETag 헀더가 ν¬ν•¨λœ 응닡을 λ°›λŠ”λ‹€.

 

2. ν΄λΌμ΄μ–ΈνŠΈλŠ” 이 응닡이 stale μƒνƒœκ°€ 되면, μ €μž₯된 ETag 값을 If-None-Match 헀더에 ν¬ν•¨ν•˜μ—¬ μ„œλ²„μ—κ²Œ μš”μ²­μ„ 보낸닀.

3. μ„œλ²„λŠ” If-None-Match κ°’κ³Ό μ„œλ²„μ— μ €μž₯된 λ¦¬μ†ŒμŠ€μ˜ ETag 값을 λΉ„κ΅ν•œλ‹€. Last-Modified 헀더λ₯Ό μ‚¬μš©ν•˜λŠ” κ²½μš°μ™€ λ§ˆμ°¬κ°€μ§€λ‘œ, μ½˜ν…μΈ μ— λ³€κ²½ 사항이 μ—†λ‹€λ©΄ 304λ₯Ό, λ³€κ²½ 사항이 μžˆλ‹€λ©΄ 200을 μ‘λ‹΅ν•œλ‹€.

 

Cache Busting

μΊμ‹œ λ²„μŠ€νŒ…μ€ μ›Ή λ¦¬μ†ŒμŠ€μ˜ 변경을 λΈŒλΌμš°μ € μΊμ‹œμ™€ μ„œλ²„ μΊμ‹œμ—μ„œ 인식할 수 μžˆλ„λ‘ URL을 λ³€κ²½ν•˜λŠ” 기법이닀. 이 방법은 μžμ›μ΄ μ—…λ°μ΄νŠΈλ  λ•Œλ§ˆλ‹€ ν΄λΌμ΄μ–ΈνŠΈκ°€ μ΅œμ‹  버전을 받을 수 μžˆλ„λ‘ 보μž₯ν•œλ‹€.

 

μžμ›μ˜ URL에 버전 λ²ˆν˜Έλ‚˜ ν•΄μ‹œκ°’μ„ ν¬ν•¨μ‹œμΌœ URL이 λ°”λ€” λ•Œλ§ˆλ‹€ μƒˆλ‘œμš΄ μžμ›μ΄ λ‘œλ“œλ˜λ„λ‘ κ°•μ œν•˜μ—¬, μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ UIκ°€ κΉ¨μ§€λŠ” λ“±μ˜ 버그 λ°œμƒμ„ μ˜ˆλ°©ν•œλ‹€.

 

Cache Busting 방법

1. 버전 번호 ν˜Ήμ€ ν•΄μ‹œκ°’μ„ 파일λͺ…에 ν¬ν•¨μ‹œν‚€κΈ°

   ex) bundle.v123.js, build.v123.css

2. 쿼리 λ¬Έμžμ—΄μ— 버전 ν˜Ήμ€ ν•΄μ‹œκ°’μ„ μΆ”κ°€ν•˜κΈ°

   ex) bundle.js?v=123, build.css?v=123

 

WebMvcConfigurer Cache Busting μ„€μ •

@Configuration
public class CacheBustingWebConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(final ResourceHandlerRegistry registry) {
        registry.addResourceHandler(PREFIX_STATIC_RESOURCES + "/" + version.getVersion() + "/**")
                .addResourceLocations("classpath:/static/")
                .setCacheControl(CacheControl.maxAge(Duration.ofDays(365)).cachePublic());
    }
}

 

μœ„μ™€ 같이 μ„€μ •ν•˜μ—¬ 정적 μžμ›μ— λŒ€ν•œ Cache Busting을 μΆ”κ°€ν•  수 μžˆλ‹€.

 

πŸ“Œ κ²°λ‘ 


μˆ˜μ—…μ„ μ—΄μ‹¬νžˆ λ“€μμ‹œλ‹€... πŸ₯²

 

 

 

참고자료

https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching#validation