WXT 스토리지
확장 프로그램 스토리지 API를 간소화한 래퍼입니다.
Installation
WXT와 함께
이 모듈은 WXT에 내장되어 있어서 별도로 설치할 필요가 없습니다.
import { storage } from 'wxt/storage';
자동 임포트를 사용한다면 storage
가 자동으로 임포트되므로, 직접 임포트할 필요조차 없습니다!
WXT 없이 사용하기
NPM 패키지를 설치하세요:
npm i @wxt-dev/storage
pnpm add @wxt-dev/storage
yarn add @wxt-dev/storage
bun add @wxt-dev/storage
import { storage } from '@wxt-dev/storage';
스토리지 권한
wxt/storage
API를 사용하려면 매니페스트에 "storage"
권한을 추가해야 합니다:
// wxt.config.ts
export default defineConfig({
manifest: {
permissions: ['storage'],
},
});
기본 사용법
모든 스토리지 키는 스토리지 영역을 접두사로 붙여야 합니다.
// ❌ 이 코드는 에러를 발생시킵니다
await storage.getItem('installDate');
// ✅ 올바른 사용법
await storage.getItem('local:installDate');
local:
, session:
, sync:
, 또는 managed:
를 사용할 수 있습니다.
타입스크립트를 사용한다면, 대부분의 메서드에 타입 매개변수를 추가하여 키 값의 예상 타입을 지정할 수 있습니다:
await storage.getItem<number>('local:installDate');
await storage.watch<number>(
'local:installDate',
(newInstallDate, oldInstallDate) => {
// ...
},
);
await storage.getMeta<{ v: number }>('local:installDate');
사용 가능한 모든 메서드 목록은 API 참조를 확인하세요.
Watchers
스토리지 변경 사항을 감지하려면 storage.watch
함수를 사용하세요. 이 함수를 통해 특정 키에 대한 리스너를 설정할 수 있습니다:
const unwatch = storage.watch<number>('local:counter', (newCount, oldCount) => {
console.log('Count changed:', { newCount, oldCount });
});
리스너를 제거하려면 반환된 unwatch
함수를 호출하세요:
const unwatch = storage.watch(...);
// 나중에...
unwatch();
메타데이터
wxt/storage
는 키에 대한 메타데이터 설정도 지원하며, 이는 key + "$"
에 저장됩니다. 메타데이터는 키와 관련된 속성들의 모음입니다. 버전 번호나 마지막 수정 날짜 등이 될 수 있습니다.
버전 관리 외에도, 여러분은 필드의 메타데이터를 관리할 책임이 있습니다:
await Promise.all([
storage.setItem('local:preference', true),
storage.setMeta('local:preference', { lastModified: Date.now() }),
]);
여러 번의 호출로 메타데이터의 서로 다른 속성을 설정할 때, 속성들은 덮어쓰지 않고 결합됩니다:
await storage.setMeta('local:preference', { lastModified: Date.now() });
await storage.setMeta('local:preference', { v: 2 });
await storage.getMeta('local:preference'); // { v: 2, lastModified: 1703690746007 }
키와 관련된 모든 메타데이터를 제거하거나 특정 속성만 제거할 수 있습니다:
// 모든 속성 제거
await storage.removeMeta('local:preference');
// "lastModified" 속성만 제거
await storage.removeMeta('local:preference', 'lastModified');
// 여러 속성 제거
await storage.removeMeta('local:preference', ['lastModified', 'v']);
스토리지 아이템 정의하기
같은 키와 타입 파라미터를 반복해서 작성하는 것은 번거로울 수 있습니다. 이를 대체하기 위해 storage.defineItem
을 사용하여 "스토리지 아이템"을 생성할 수 있습니다.
스토리지 아이템은 storage
변수와 동일한 API를 포함하지만, 타입, 기본값 등을 한 곳에서 설정할 수 있습니다:
// utils/storage.ts
const showChangelogOnUpdate = storage.defineItem<boolean>(
'local:showChangelogOnUpdate',
{
fallback: true,
},
);
이제 storage
변수를 사용하는 대신, 생성한 스토리지 아이템의 헬퍼 함수를 사용할 수 있습니다:
await showChangelogOnUpdate.getValue();
await showChangelogOnUpdate.setValue(false);
await showChangelogOnUpdate.removeValue();
const unwatch = showChangelogOnUpdate.watch((newValue) => {
// ...
});
사용 가능한 모든 속성과 메서드의 전체 목록은 API 참조를 확인하세요.
버전 관리
저장소 항목이 시간이 지남에 따라 커지거나 변경될 것으로 예상된다면 버전 관리를 추가할 수 있습니다. 항목의 첫 번째 버전을 정의할 때는 버전 1부터 시작합니다.
예를 들어, 확장 프로그램에서 무시하는 웹사이트 목록을 저장하는 저장소 항목을 생각해 보겠습니다.
type IgnoredWebsiteV1 = string;
export const ignoredWebsites = storage.defineItem<IgnoredWebsiteV1[]>(
'local:ignoredWebsites',
{
fallback: [],
version: 1,
},
);
import { nanoid } from 'nanoid';
type IgnoredWebsiteV1 = string;
interface IgnoredWebsiteV2 {
id: string;
website: string;
}
export const ignoredWebsites = storage.defineItem<IgnoredWebsiteV1[]>(
export const ignoredWebsites = storage.defineItem<IgnoredWebsiteV2[]>(
'local:ignoredWebsites',
{
fallback: [],
version: 1,
version: 2,
migrations: {
// v1에서 v2로 마이그레이션할 때 실행됨
2: (websites: IgnoredWebsiteV1[]): IgnoredWebsiteV2[] => {
return websites.map((website) => ({ id: nanoid(), website }));
},
},
},
);
import { nanoid } from 'nanoid';
type IgnoredWebsiteV1 = string;
interface IgnoredWebsiteV2 {
id: string;
website: string;
}
interface IgnoredWebsiteV3 {
id: string;
website: string;
enabled: boolean;
}
export const ignoredWebsites = storage.defineItem<IgnoredWebsiteV2[]>(
export const ignoredWebsites = storage.defineItem<IgnoredWebsiteV3[]>(
'local:ignoredWebsites',
{
fallback: [],
version: 2,
version: 3,
migrations: {
// v1에서 v2로 마이그레이션할 때 실행됨
2: (websites: IgnoredWebsiteV1[]): IgnoredWebsiteV2[] => {
return websites.map((website) => ({ id: nanoid(), website }));
},
// v2에서 v3로 마이그레이션할 때 실행됨
3: (websites: IgnoredWebsiteV2[]): IgnoredWebsiteV3[] => {
return websites.map((website) => ({ ...website, enabled: true }));
},
},
},
);
INFO
내부적으로 이 기능은 값의 현재 버전을 추적하기 위해 v
라는 메타데이터 속성을 사용합니다.
이 경우, 무시된 웹사이트 목록이 미래에 변경될 수 있다고 생각했기 때문에 처음부터 버전 관리가 가능한 저장소 항목을 설정할 수 있었습니다.
현실적으로는 스키마를 변경해야 할 때까지 항목에 버전 관리가 필요한지 알 수 없습니다. 다행히도, 버전 관리가 없는 저장소 항목에 버전 관리를 추가하는 것은 간단합니다.
이전 버전을 찾을 수 없으면 WXT는 버전이 1
이라고 가정합니다. 즉, version: 2
를 설정하고 2
에 대한 마이그레이션을 추가하기만 하면 바로 작동합니다!
이전과 동일한 무시된 웹사이트 예제를 살펴보겠습니다. 이번에는 버전 관리가 없는 항목으로 시작합니다:
export const ignoredWebsites = storage.defineItem<string[]>(
'local:ignoredWebsites',
{
fallback: [],
},
);
import { nanoid } from 'nanoid';
// 첫 번째 버전에 대한 타입을 나중에 추가함
type IgnoredWebsiteV1 = string;
interface IgnoredWebsiteV2 {
id: string;
website: string;
}
export const ignoredWebsites = storage.defineItem<string[]>(
export const ignoredWebsites = storage.defineItem<IgnoredWebsiteV2[]>(
'local:ignoredWebsites',
{
fallback: [],
version: 2,
migrations: {
// v1에서 v2로 마이그레이션할 때 실행됨
2: (websites: IgnoredWebsiteV1[]): IgnoredWebsiteV2[] => {
return websites.map((website) => ({ id: nanoid(), website }));
},
},
},
);
마이그레이션 실행
storage.defineItem
이 호출되면, WXT는 마이그레이션이 필요한지 확인하고 필요한 경우 이를 실행합니다. 스토리지 아이템의 값이나 메타데이터를 가져오거나 업데이트하는 호출(getValue
, setValue
, removeValue
, getMeta
등)은 실제로 값을 읽거나 쓰기 전에 마이그레이션 프로세스가 완료될 때까지 자동으로 대기합니다.
기본값 설정
storage.defineItem
을 사용하면 기본값을 정의하는 여러 방법이 있습니다:
fallback
- 값이 없을 때getValue
에서null
대신 이 값을 반환합니다.이 옵션은 설정에 기본값을 제공할 때 유용합니다:
tsconst theme = storage.defineItem('local:theme', { fallback: 'dark', }); const allowEditing = storage.defineItem('local:allow-editing', { fallback: true, });
init
- 저장소에 값이 아직 저장되지 않았다면 초기화하고 저장합니다.이 방법은 초기화하거나 한 번 설정해야 하는 값에 적합합니다:
tsconst userId = storage.defineItem('local:user-id', { init: () => globalThis.crypto.randomUUID(), }); const installDate = storage.defineItem('local:install-date', { init: () => new Date().getTime(), });
값은 즉시 저장소에 초기화됩니다.
대량 작업
스토리지에서 여러 값을 가져오거나 설정할 때, 개별 스토리지 호출 횟수를 줄여 성능을 향상시키기 위해 대량 작업을 수행할 수 있습니다. storage
API는 대량 작업을 수행하기 위한 여러 메서드를 제공합니다:
getItems
- 여러 값을 한 번에 가져옵니다.getMetas
- 여러 항목의 메타데이터를 한 번에 가져옵니다.setItems
- 여러 값을 한 번에 설정합니다.setMetas
- 여러 항목의 메타데이터를 한 번에 설정합니다.removeItems
- 여러 값(및 선택적으로 메타데이터)을 한 번에 제거합니다.
이 모든 API는 문자열 키와 정의된 스토리지 항목을 모두 지원합니다:
const userId = storage.defineItem('local:userId');
await storage.setItems([
{ key: 'local:installDate', value: Date.now() },
{ item: userId, value: generateUserId() },
]);
모든 대량 API 사용 방법에 대한 타입과 예제는 API 참조를 참조하세요.