IndexedDB와 널리 사용되는 상태 관리 라이브러리 간에 애플리케이션 상태를 동기화하기 위한 권장사항을 알아봅니다.
사용자가 웹사이트 또는 애플리케이션을 처음 로드할 때는 UI를 렌더링하는 데 사용되는 초기 애플리케이션 상태를 구성하는 데 상당한 작업이 필요할 수 있습니다. 예를 들어 앱이 페이지에 표시해야 하는 모든 데이터를 가져오기 전에 클라이언트 측에서 사용자를 인증한 다음 여러 API 요청을 해야 하는 경우가 있습니다.
애플리케이션 상태를 IndexedDB에 저장하면 재방문 시 로드 시간을 단축할 수 있습니다. 그러면 앱은 백그라운드에서 API 서비스와 동기화하고 stale-while-revalidate 전략을 사용하여 새로운 데이터로 UI를 지연 업데이트할 수 있습니다.
하지만 IndexedDB를 사용할 때는 API를 처음 접하는 개발자에게는 바로 이해되지 않을 수 있는 중요한 고려사항이 많이 있습니다. 이 문서에서는 일반적인 질문에 답변하고 IndexedDB에서 애플리케이션 상태를 유지할 때 유의해야 할 가장 중요한 몇 가지 사항을 설명합니다.
앱의 예측 가능성 유지
IndexedDB와 관련된 많은 복잡성은 개발자가 제어할 수 없는 요소가 너무 많다는 사실에서 비롯됩니다. 이 섹션에서는 IndexedDB를 사용할 때 염두에 두어야 하는 여러 가지 문제를 살펴봅니다.
스토리지에 쓰기가 실패할 수 있음
IndexedDB에 쓸 때 발생하는 오류는 다양한 이유로 발생할 수 있으며, 경우에 따라 이러한 이유는 개발자가 제어할 수 없습니다. 예를 들어 일부 브라우저는 비공개 탐색 모드일 때 IndexedDB에 쓰기를 허용하지 않습니다. 또한 사용자가 디스크 공간이 거의 없는 기기를 사용하고 있을 가능성이 있으며 브라우저에서는 아무것도 저장하지 못하도록 제한합니다.
따라서 IndexedDB 코드에서 항상 적절한 오류 처리를 구현하는 것이 매우 중요합니다. 또한 일반적으로 애플리케이션 상태를 저장하는 것 외에도 메모리에 유지하는 것이 좋습니다. 그러면 비공개 브라우징 모드에서 실행하거나 저장용량을 사용할 수 없는 경우에도 UI가 중단되지 않습니다(저장소가 필요한 다른 앱 기능 중 일부가 작동하지 않는 경우에도 마찬가지임).
저장된 데이터가 사용자가 수정했거나 삭제했을 수 있습니다.
무단 액세스를 제한할 수 있는 서버 측 데이터베이스와 달리 클라이언트 측 데이터베이스는 브라우저 확장 프로그램 및 개발자 도구에서 액세스할 수 있으며 사용자가 삭제할 수 있습니다.
사용자가 로컬에 저장된 데이터를 수정하는 경우는 드물지만 데이터를 삭제하는 경우는 흔합니다. 애플리케이션에서 오류 없이 이러한 두 사례를 모두 처리할 수 있어야 합니다.
저장된 데이터가 최신 상태가 아닐 수 있음
이전 섹션과 마찬가지로 사용자가 데이터를 직접 수정하지 않았더라도 저장소에 있는 데이터가 이전 버전의 코드(버그가 있는 버전일 수 있음)로 작성되었을 수 있습니다.
IndexedDB는 IDBOpenDBRequest.onupgradeneeded()
메서드를 사용하여 스키마 버전 및 업그레이드를 지원합니다. 하지만 이전 버전(버그가 있는 버전 포함)에서 오는 사용자를 처리할 수 있도록 업그레이드 코드를 작성해야 합니다.
가능한 모든 업그레이드 경로와 사례를 수동으로 테스트할 수 없는 경우가 많으므로 단위 테스트가 매우 유용할 수 있습니다.
앱 성능 유지
IndexedDB의 주요 기능 중 하나는 비동기 API이지만 이를 사용한다고 해서 성능에 대해 걱정할 필요가 없다고 생각해서는 안 됩니다. 부적절한 사용으로 인해 여전히 기본 스레드가 차단되어 응답이 없는 경우가 많이 있습니다.
일반적으로 IndexedDB에 대한 읽기 및 쓰기는 액세스하는 데이터에 필요한 크기보다 크지 않아야 합니다.
IndexedDB를 사용하면 대용량의 중첩된 객체를 단일 레코드로 저장할 수 있지만 개발자의 관점에서 보면 매우 편리합니다. 하지만 이 방법은 피해야 합니다. 이는 IndexedDB가 객체를 저장할 때 먼저 해당 객체의 구조화된 클론을 만들어야 하고 구조화된 클론 생성 프로세스가 기본 스레드에서 실행되기 때문입니다. 객체가 클수록 차단 시간이 길어집니다.
따라서 IndexedDB에 애플리케이션 상태를 유지하는 방법을 계획할 때 몇 가지 문제가 발생합니다. 대부분의 인기 있는 상태 관리 라이브러리(예: Redux)는 전체 상태 트리를 단일 JavaScript 객체로 관리하여 작동하기 때문입니다.
이러한 방식으로 상태를 관리하면 많은 이점이 있으며 전체 상태 트리를 IndexedDB에 단일 레코드로 저장하는 것이 유혹적이고 편리할 수 있지만, 제한/디바운스된 경우에도 모든 변경 후에 이 작업을 수행하면 기본 스레드가 불필요하게 차단되고, 경우에 따라 브라우저 탭이 다운되거나 응답하지 않을 수도 있습니다.
전체 상태 트리를 단일 레코드에 저장하는 대신 개별 레코드로 분할하고 실제로 변경되는 레코드만 업데이트해야 합니다.
대부분의 권장사항과 마찬가지로 이 규칙은 '전부 또는 전혀' 적용되는 규칙이 아닙니다. 상태 객체를 분할하고 최소 변경 집합만 작성하는 것이 불가능한 경우에는 데이터를 하위 트리로 분할한 후 하위 트리만 작성하는 것이 항상 전체 상태 트리를 작성하는 것이 좋습니다. 개선이 거의 없는 것이 전혀 개선되지 않는 것보다 낫습니다.
마지막으로 항상 작성하는 코드의 성능 영향 측정을 해야 합니다. IndexedDB에 대한 작은 쓰기가 대량 쓰기보다 성능이 우수한 것은 사실이지만 이는 애플리케이션에서 수행하는 IndexedDB에 대한 쓰기로 인해 실제로 기본 스레드를 차단하고 사용자 환경을 저하시키는 장기 작업이 발생하는 경우에만 중요합니다. 무엇을 최적화하는지 파악할 수 있도록 측정하는 것이 중요합니다.
결론
개발자는 IndexedDB와 같은 클라이언트 스토리지 메커니즘을 사용하여 세션 간에 상태를 유지할 뿐만 아니라 재방문 시 초기 상태를 로드하는 데 걸리는 시간을 줄여 애플리케이션의 사용자 환경을 개선할 수 있습니다.
IndexedDB를 올바르게 사용하면 사용자 환경을 크게 개선할 수 있지만, 잘못 사용하거나 오류 사례를 처리하지 못하면 앱이 손상되고 사용자가 불만족하게 될 수 있습니다.
클라이언트 저장소에는 개발자가 제어할 수 없는 많은 요소가 포함되므로 코드가 충분히 테스트되고 처음에는 발생할 것 같지 않은 오류도 제대로 처리하는 것이 중요합니다.