IndexedDB를 사용하여 애플리케이션 상태를 유지하는 권장사항

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가 객체를 저장할 때 먼저 해당 객체의 구조화된 클론을 만들어야 하고 구조화된 클론 프로세스가 기본 스레드에서 발생하기 때문입니다. 객체가 클수록 차단 시간이 길어집니다.

대부분의 인기 있는 상태 관리 라이브러리 (예: Redux)는 전체 상태 트리를 단일 JavaScript 객체로 관리하여 작동하므로 애플리케이션 상태를 IndexedDB에 저장하는 방법을 계획할 때 몇 가지 문제가 발생합니다.

이러한 방식으로 상태를 관리하면 많은 이점이 있고 전체 상태 트리를 IndexedDB에 단일 레코드로 저장하는 것이 편리할 수 있지만, 모든 변경 후에 이 작업을 수행하면 (제한/디바운스되더라도) 기본 스레드가 불필요하게 차단되고 쓰기 오류가 발생할 가능성이 높아지며 경우에 따라 브라우저 탭이 비정상 종료되거나 응답하지 않을 수도 있습니다.

전체 상태 트리를 단일 레코드에 저장하는 대신 개별 레코드로 분할하고 실제로 변경되는 레코드만 업데이트해야 합니다.

대부분의 권장사항과 마찬가지로, 이 규칙은 절대적인 것은 아닙니다. 상태 객체를 분할하고 최소 변경 집합만 작성하는 것이 불가능한 경우 데이터를 하위 트리로 분할하고 하위 트리만 작성하는 것이 전체 상태 트리를 항상 작성하는 것보다 좋습니다. 조금이라도 개선하는 것이 전혀 개선하지 않는 것보다 낫습니다.

마지막으로, 작성하는 코드의 성능 영향을 항상 측정해야 합니다. IndexedDB에 대한 작은 쓰기가 큰 쓰기보다 성능이 더 좋은 것은 사실이지만, 이는 애플리케이션이 수행하는 IndexedDB에 대한 쓰기가 실제로 기본 스레드를 차단하고 사용자 환경을 저하시키는 긴 작업으로 이어지는 경우에만 중요합니다. 최적화 대상을 파악할 수 있도록 측정하는 것이 중요합니다.

결론

개발자는 IndexedDB와 같은 클라이언트 저장소 메커니즘을 사용하여 세션 간에 상태를 유지할 뿐만 아니라 반복 방문 시 초기 상태를 로드하는 데 걸리는 시간을 줄여 애플리케이션의 사용자 환경을 개선할 수 있습니다.

IndexedDB를 올바르게 사용하면 사용자 환경을 크게 개선할 수 있지만, 잘못 사용하거나 오류 사례를 처리하지 못하면 앱이 손상되고 사용자가 불만을 가질 수 있습니다.

클라이언트 저장소에는 개발자가 제어할 수 없는 여러 요소가 포함되므로 코드를 철저히 테스트하고 처음에는 발생할 가능성이 낮아 보이는 오류도 적절하게 처리하는 것이 중요합니다.