본문 바로가기
Tech Notes

localStorage TTL이란?

by miracle-tech 2026. 4. 15.
728x90
반응형

브라우저의 localStorage는 만료 기능이 없습니다. 데이터를 저장하면 명시적으로 삭제하지 않는 한 영구적으로 남아 있어요.

그래서 TTL(Time To Live)을 구현하려면 데이터와 함께 만료 시간을 직접 저장하는 패턴을 사용합니다.


기본 구현 패턴

 
 
javascript
// 저장 (TTL: 밀리초 단위)
function setWithTTL(key, value, ttlMs) {
  const item = {
    value,
    expiresAt: Date.now() + ttlMs,
  };
  localStorage.setItem(key, JSON.stringify(item));
}

// 조회
function getWithTTL(key) {
  const raw = localStorage.getItem(key);
  if (!raw) return null;

  const item = JSON.parse(raw);

  if (Date.now() > item.expiresAt) {
    localStorage.removeItem(key); // 만료 시 자동 삭제
    return null;
  }

  return item.value;
}

사용 예시:

 
 
javascript
setWithTTL("weather_cache", { temp: 24 }, 15 * 60 * 1000); // 15분 TTL

const data = getWithTTL("weather_cache");
// 15분 후엔 null 반환

실전에서 자주 쓰는 패턴들

1. 클래스 래퍼로 관리

 
 
javascript
class LocalStorageWithTTL {
  set(key, value, ttlMs) {
    localStorage.setItem(key, JSON.stringify({
      value,
      expiresAt: Date.now() + ttlMs,
    }));
  }

  get(key) {
    const raw = localStorage.getItem(key);
    if (!raw) return null;

    const { value, expiresAt } = JSON.parse(raw);
    if (Date.now() > expiresAt) {
      this.delete(key);
      return null;
    }
    return value;
  }

  delete(key) {
    localStorage.removeItem(key);
  }

  // 만료된 항목 전체 청소
  purgeExpired() {
    Object.keys(localStorage).forEach((key) => {
      this.get(key); // 내부에서 만료 체크 + 삭제
    });
  }
}

const cache = new LocalStorageWithTTL();

2. React Hook으로 활용

 
 
javascript
function useLocalStorageCache(key, fetchFn, ttlMs) {
  const [data, setData] = useState(null);

  useEffect(() => {
    const cached = getWithTTL(key);
    if (cached) {
      setData(cached);
      return;
    }

    fetchFn().then((result) => {
      setWithTTL(key, result, ttlMs);
      setData(result);
    });
  }, [key]);

  return data;
}

주의사항

항목내용
자동 만료 없음 TTL 체크는 get() 호출 시점에만 발생
용량 제한 보통 5MB, 초과 시 QuotaExceededError
보안 민감한 데이터는 저장 금지 (XSS에 취약)
동기 API 대용량 데이터 저장 시 메인 스레드 블로킹

AeroLayer 같은 앱에 적용한다면

 
 
javascript
// 날씨 데이터 15분 캐싱 (Supabase 호출 절감)
setWithTTL(`weather_${gridId}`, weatherData, 15 * 60 * 1000);

// 미세먼지 1시간 캐싱
setWithTTL(`dust_${region}`, dustData, 60 * 60 * 1000);

서버 요청 비용을 줄이고 싶을 때 클라이언트 TTL 캐시는 꽤 실용적입니다. 다만 민감하지 않은 공개 데이터에만 적용하는 게 좋아요.

 
 
 
 

 

728x90