티스토리 뷰

안녕하세요. 한장현입니다.

 

최근에 로컬 스토리지를 사용하려고 찾아봤더니 이제는 로컬 스토리지를 사용하지 않는것이 좋다는 Google Chrome 팀 개발자의 글을 발견했습니다.

 

요즘 트렌드는 이렇구나 다시 한 번 느끼면서 글을 번역해 봤습니다.

 

 


웹 스토리지

 

브라우저에 데이터를 저장하는 방법은 많습니다. 이중에 무엇을 사용해야 할까요? 인터넷 연결은 불안정하며 언제든 끊어질 수 있습니다. 그래서 오프라인에서도 동작하며 불안정한 상황을 안정되게 유지하기 위해 PWA(Progressive Web App)를 사용하기도 합니다. 연결이 완벽한 무선 환경에서도 캐시나 스토리지 기술을 적절하게 활용하면 사용자가 느끼는 앱 성능을 향상시킬 수 있습니다. 애플리케이션 정적 리소스(HTML, JavaScript, CSS, 이미지 등)나 데이터(사용자 데이터, 기사 글 등)를 캐싱하는 방법은 다양합니다. 이 중에서 어떤 것이 제일 좋을까요? 얼마나 저장할 수 있을까요? 데이터가 유실되는 것을 방지하려면 어떻게 해야 할까요?

 

무엇을 사용해야 하나요?

리소스를 저장할 때는 이런 방법을 추천합니다:

 

최근 브라우저들은 IndexedDB와 캐시 스토리지 API를 모두 지원합니다. 이 스토리지들은 모두 비동기(asynchronous)로 동작하기 때문에 메인 스레드 연산에 영향을 주지 않습니다. 그리고 window 객체로 접근할 수 있으며 웹 워커나 서비스 워커에서도 접근할 수 있기 때문에 자유롭게 활용할 수 있습니다.

 

다른 스토리지는 어떤가요?

브라우저에서 사용할 수 있는 스토리지는 두 가지 외에도 더 있습니다. 하지만 저장용량에 제한이 있거나 심각한 성능 이슈가 있습니다.

 

  • 세션 스토리지(SessionStorage)는 탭 안에서만 유효하며 탭이 닫히면 스토리지도 종료됩니다. 세션 스토리지는 현재 탭에서만 사용하는 IndexedDB 키를 잠시 저장하는 것과 같이 작은 용량 데이터를 저장할 때는 좋습니다. 하지만 이 스토리지는 동기(synchronous) 방식으로 동작하기 때문에 메인 스레드 연산을 중단시키기 때문에 조심해야 합니다. 용량 제한은 5MB이며 문자열만 저장할 수 있습니다. 그리고 탭 안에서만 유효하기 때문에 웹 워커나 서비스 워커가 접근할 수 없습니다.

  • 로컬 스토리지(LocalStorage)도 동기 방식으로 동작하며 메인 스레드 연산을 중단시키기 때문에 사용하지 않는 것이 좋습니다. 용량 제한은 5MB이며 문자열만 저장할 수 있습니다. 그리고 웹 워커나 서비스 워커에서 접근할 수 없습니다.

  • 쿠키(Cookies)는 본연의 역할이 있기 때문에 스토리지로 사용하지 않는 것이 좋습니다. 그리고 쿠키는 HTTP 요청이 있을 때마다 외부로 함께 전달되기 때문에 데이터를 조금만 저장해도 소모하는 전체 데이터 양이 급격하게 늘어날 수 있습니다. 쿠키는 비동기로 동작하지만 웹 워커에서는 접근할 수 없으며, 로컬 스토리지나 세션 스토리지와 마찬가지로 문자열만 저장할 수 있습니다.

  • 파일 시스템 API나 FileWriter API를 활용하면 파일 시스템에 샌드박스 형태로 파일을 읽고 쓸 수 있습니다. 이 스토리지는 비동기로 동작하지만 Chromium 기반 브라우저에서만 동작하기 때문에 권장하지 않습니다.

  • 파일 시스템 접근 API는 로컬 파일 시스템에 있는 파일을 쉽게 읽고 쓰기 위해 설계된 API입니다. 하지만 로컬 파일을 읽거나 쓸 때 반드시 권한을 받아야 하며 한 세션 안에서만 유효합니다.

  • WebSQL은 사용하면 안됩니다. 이미 사용하고 있다면 IndexedDB로 전환하는 것이 좋습니다. 왜냐하면 WebSQL은 최근 브라우저들에서 지원이 중단되었으며, W3C는 2010년에 WebSQL 스펙 관리를 중단했습니다. 더 이상 업데이트될 계획도 없습니다.

  • 애플리케이션 캐시는 사용하면 안 됩니다. 이미 사용하고 있다면 서비스 워커나 캐시 API로 전환하는 것이 좋습니다. 이 기능은 지원이 중단되었으며 앞으로는 브라우저에서 제거될 수 있습니다.

얼마나 저장할 수 있나요?

간단하게 말해서 많이 저장할 수 있습니다. MB 단위부터 GB 단위 이상도 가능합니다. 브라우저마다 다를 수 있지만, 일반적으로 스토리지에 저장할 수 있는 양은 디바이스 스토리지 크기에 따라 달라집니다.

 

  • Chrome 기반 브라우저는 원래 디스크 전체 용량의 80%까지 저장할 수 있지만, 공식 Chrome은 디스크 전체 용량의 60%까지 저장할 수 있습니다.
    StorageManage API를 활용하면 저장할 수 있는 최대 용량이 얼마나 되는지 확인할 수 있습니다.
    크로미움 기반의 다른 브라우저들은 사용할 수 있는 용량이 조금 더 많습니다.
    Chrome은 왜 다른지 확인하려면 이 이슈를 참고하세요.

  • Internet Explorer는 10 버전부터 250MB까지 저장할 수 있으며, 저장된 용량이 10MB를 넘어가면 정말 저장할 것인지 물어보는 팝업이 뜹니다.

  • FireFox는 디스크 빈 용량의 50%까지 저장할 수 있습니다.
    그리고 example.com이나 www.example.com, foo.bar.example.com과 같은 eTLD+1 그룹은 2GB까지 저장할 수 있습니다.
    얼마나 저장할 수 있는지 확인하려면 StorageManager API를 활용하면 됩니다.

  • Safari(데스크탑, 모바일)는 1GB까지 저장할 수 있습니다.
    이 용량을 다 사용하면 용량 제한을 200MB 더 늘릴 것인지 물어보는 팝업이 뜹니다.
    관련 문서는 찾지 못했습니다.

이전에는 저장할 수 있는 용량 제한을 넘어가면 더 많은 데이터를 저장할 것인지 물어보는 팝업이 떴습니다. 50MB를 저장하고 나면 100MB까지 늘릴 것인지 물어보는 식인데, 이 팝업은 저장 용량이 50MB를 넘어갈 때마다 반복해서 뜹니다.

 

하지만 요즘 브라우저들은 사용할 수 있는 용량을 다 채울 때까지 사용자에게 물어보지 않습니다. Safari만 다릅니다. Safari는 750MB를 저장하고 나면 1.1GB까지 저장 공간을 사용할 것인지 물어보는 팝업이 뜹니다. 용량 제한을 넘어간 상태에서 새로운 데이터를 쓰려고 하면 오류가 발생합니다.

스토리지를 얼마나 사용할 수 있는지 확인하는 방법

요즘 브라우저들은 StorageManager API를 활용해서 현재 저장 공간을 얼마나 사용하고 있는지, 총 얼마나 저장할 수 있는지 확인할 수 있습니다. 이 API를 활용하면 IndexedDB와 캐시 API가 사용하고 있는 용량을 바이트(byte) 단위로 확인할 수 있으며, 앞으로 얼마나 더 사용할 수 있는지도 확인할 수 있습니다.

if (navigator.storage && navigator.storage.estimate) {
  const quota = await navigator.storage.estimate();
  // quota.usage -> 사용 중인 용량(byte)
  // quota.quota -> 사용할 수 있는 전체 용량(byte)
  const percentageUsed = (quota.usage / quota.quota) * 100;
  console.log(`사용할 수 있는 용량의 ${percentageUsed}%를 사용하고 있습니다.`);
  const remaining = quota.quota - quota.usage;
  console.log(`앞으로 ${remaining} 바이트를 더 사용할 수 있습니다.`);
}

다만, 모든 브라우저가 StorageManager API를 지원하는 것은 아닙니다. 그래서 StorageManager API를 활용하는 코드를 작성하려면 대상 브라우저가 StorageManager API를 지원하는지 확인해야 합니다. 그리고 브라우저가 StorageManager API를 지원하더라도 사용할 수 있다고 하는 용량이 실제로 사용할 수 있는 용량을 넘어가는 경우가 있으니 주의해야 합니다. 이 내용은 아래 "사용량을 넘어가는 에러(over-quota errors)" 섹션에서 살펴봅시다.

 

크로미움 기반 브라우저에서 사용할 수 있는 용량을 확인하면 현재 디스크 용량의 비율로 용량을 표시합니다.
하지만 공식 Chrome은 언제나 실제 디스크 전체 용량의 60%라고 표시합니다.
저장된 리소스의 크기를 확실히 알 수 있다는 점에서는 좋습니다.

디버깅하기

개발 단계에서 브라우저 개발자 도구를 열면 스토리지가 여러 종류로 제공되는 것을 확인할 수 있습니다. 저장된 데이터도 간단하게 지울 수 있습니다.

 

 

이 글을 작성하면서 스토리지를 테스트해볼 수 있는 을 만들어 봤습니다. 스토리지들이 어떻게 동작하는지 간단하게 확인할 수 있으며, 용량 제한을 넘어가면 어떤 일이 발생하는지도 확인할 수 있습니다.

용량 제한 에러(over-quota errors)를 처리하는 방법

저장할 수 있는 용량을 모두 사용하면 어떻게 될까요? 이런 경우에는 QuotaExceededError와 같은 에러가 발생하기 때문에 이 에러를 계속 처리해야 합니다. 이 문제를 해결하는 방법은 앱을 어떻게 설계했느냐에 따릅니다. 오랫동안 사용하지 않는 데이터를 지우거나, 저장된 용량을 확인하면서 데이터를 조금씩 지울 수도 있고, 사용자가 지정한 데이터를 지우는 방법도 사용할 수 있습니다.

 

용량 제한을 넘어가면 IndexedDB와 캐시 API는 모두 QuotaExceededError라는 DOMError를 발생시킵니다.

IndexedDB

공식 Chrome에서 용량 제한을 넘어가면 IndexedDB 쓰기 동작이 실패합니다. 이때 onabort() 핸들러가 실행되면서 에러 이벤트가 인자로 전달되는데, 이 에러 이벤트의 이름은 QuotaExceededError이고 에러 이벤트 객체에서 DomException을 확인할 수 있습니다.

const transaction = idb.transaction(['entries'], 'readwrite');

transaction.onabort = function(event) {
  const error = event.target.error; // DOMException
  if (error.name == 'QuotaExceededError') {
    // 실패했을 때 실행되는 코드
  }
};

캐시 API

공식 Chrome에서 용량 제한을 넘어가면 캐시 API가 프라미스 형태로 QuotaExceededError를 반환합니다.

try {
  const cache = await caches.open('my-cache');
  await cache.add(new Request('/sample1.jpg'));
} catch (err) {
  if (error.name === 'QuotaExceededError') {
    // 실패했을 때 실행되는 코드
  }
}

데이터는 어떻게 지워지나요?

웹 스토리지는 "최적화(Best Effort) 스토리지"와 "데이터 보존(Persistent) 스토리지"로 나눠볼 수 있습니다. 최적화 스토리지는 사용자의 개입 없이 브라우저가 자동으로 데이터를 비우기 때문에 오래 보관할 데이터나 중요한 데이터가 지워질 우려가 있습니다. 데이터 보존 스토리지는 저장 공간을 많이 사용하더라도 데이터가 자동으로 지워지지 않습니다. 브라우저 설정으로 사용자가 직접 데이터를 비워야 합니다.

 

IndexedDB나 캐시 API, 기타 스토리지들도 기본적으로는 최적화 스토리지 방식으로 동작합니다. 따로 데이터를 보존하도록 지정하지 않는 이상 디바이스 용량이 꽉 차면 브라우저가 데이터를 자동으로 지웁니다.

 

최적화 스토리지가 동작하는 방식은 이렇습니다:

  • 크로미움 기반 브라우저들은 디바이스 용량이 부족할 때 가장 오래된 데이터부터 용량 제한을 해결할 때까지 데이터를 지웁니다.

  • Internet Explorer 10 버전부터는 데이터를 자동으로 지우지 않지만, 쓰기 작업을 더 이상 실행할 수 없습니다.

  • Firefox는 디스크 용량이 꽉 찼을 때 가장 오래된 데이터부터 용량 제한을 해결할 때까지 데이터를 지웁니다.

  • Safari 이전 버전은 데이터를 자동으로 지우지 않았지만 요즘에는 최근 7일 데이터를 남겨두고 모든 스토리지를 비웁니다.

iOS와 iPadOS 13.4, macOS용 Safari 13.1 버전부터 스토리지를 7일 분량만 남기는 정책이 적용되었습니다. 이때 스토리지는 IndexedDB, 서비스 워커 저장소, 캐시 API를 모두 포함합니다. 그래서 7일이 지난 데이터는 모두 삭제되기 때문에 더 이상 활용할 수 없습니다. 다만 이 정책은 홈 화면에 추가되어 PWA 형태로 설치된 웹 사이트에는 적용되지 않습니다. 자세한 내용은 WebKit 블로그 서드 파티 쿠키 모두 막기 외 문서를 참고하세요.

 

중요한 사용자 데이터나 애플리케이션 데이터를 유지하려면 데이터 보존 스토리지를 사용하세요.

보너스: 왜 IndexedDB 래퍼(wrapper)를 사용하나요?

IndexedDB는 낮은 계층에서 동작하는(low level) API이기 때문에 아주 간단한 데이터만 저장하려고 해도 복잡한 환경설정을 해야 합니다. 그리고 요즘 유행하는 프라미스 기반 API가 아니라 이벤트 기반으로 제공되는 API입니다. 그래서 idb와 같은 IndexedDB 래퍼를 활용하면 복잡한 환경설정 없이도 IndexedDB 기본 기능은 물론이고, 트랜잭션이나 스키마 버전 관리와 같이 복잡한 IndexedDB 기능을 쉽게 활용할 수 있습니다.

결론

스토리지 용량 제한이 있고 이 용량 제한을 풀기 위해 사용자에게 확인을 받아야 했던 시대는 지났습니다. 이제 웹 사이트는 다양하고 효율적인 방법으로 리소스와 데이터를 저장할 수 있습니다. StorageManager API를 활용하면 지금 데이터를 얼마나 저장하고 있는지 확인할 수 있으며, 앞으로 얼마나 더 저장할 수 있는지도 확인할 수 있습니다. 그리고 데이터 보존 스토리지를 활용하면 사용자가 데이터를 직접 지우지 않는 이상 데이터를 안전하게 보관할 수 있습니다.

참고

Thanks

생략

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/03   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
글 보관함