SQLite를 사용하여 웹에서 모든 스토리지 요구사항을 성능적으로 처리하세요.
SQLite는 널리 사용되는 오픈소스 경량 삽입형 관계형 데이터베이스 관리 시스템입니다. 많은 개발자가 이를 사용하여 사용하기 쉬운 구조화된 방식으로 데이터를 저장합니다. 크기가 작고 메모리 요구사항이 낮기 때문에 SQLite는 휴대기기, 데스크톱 애플리케이션, 웹브라우저에서 데이터베이스 엔진으로 사용되는 경우가 많습니다.
SQLite의 주요 기능 중 하나는 서버리스 데이터베이스이기 때문에 별도의 서버 프로세스가 없어도 작동한다는 것입니다. 대신 데이터베이스가 사용자 기기의 단일 파일로 저장되므로 애플리케이션에 쉽게 통합할 수 있습니다.
WebAssembly 기반 SQLite
웹 어셈블리(Wasm)를 기반으로 하는 여러 비공식 SQLite 버전이 있으며 이를 통해 웹브라우저에서 사용할 수 있습니다(예: sql.js). sqlite3 WASM/JS 하위 프로젝트는 SQLite 프로젝트와 공식적으로 연결된 최초의 작업으로, 라이브러리의 WASM 빌드를 지원되는 SQLite 결과물 제품군의 구성원으로 확립했습니다. 이 프로젝트의 구체적인 목표는 다음과 같습니다.
- 사용 측면에서 C에 최대한 근접한 하위 수준 sqlite3 API를 바인딩합니다.
- sql.js 및 Node.js 스타일 구현과 더 유사하며 하위 수준 API와 직접 통신하는 상위 수준의 객체 지향 API입니다. 이 API는 하위 수준 API와 동일한 스레드에서 사용해야 합니다.
- Worker 메시지를 통해 이전 API와 통신하는 Worker 기반 API입니다. 이 메서드는 작업자 스레드에 하위 수준 API가 설치되어 작업자 메시지를 통해 통신하는 기본 스레드에서 사용하기 위한 것입니다.
- Worker API의 Promise 기반 변형으로, 교차 스레드 통신 측면을 사용자에게 완전히 숨깁니다.
- 사용 가능한 JavaScript API(예: 출처 비공개 파일 시스템(OPFS))를 사용하는 영구 클라이언트 측 저장소 지원
출처 비공개 파일 시스템 지속성 백엔드에서 SQLite Wasm 사용
npm에서 라이브러리 설치
다음 명령어를 사용하여 npm에서 @sqlite.org/sqlite-wasm 패키지를 설치합니다.
npm install @sqlite.org/sqlite-wasm
출처 비공개 파일 시스템
File System Access API의 일부인 OPFS (Origin Private File System)는 데이터에 대한 고성능 액세스를 제공하는 특별한 노출 영역으로 보강됩니다. 이 새로운 노출 영역은 파일 콘텐츠에 대한 인플레이스 및 독점 쓰기 액세스를 제공한다는 점에서 기존 노출 영역과 다릅니다. 이 변경사항은 플러시되지 않은 수정사항을 일관되게 읽을 수 있는 기능과 전용 작업자에서 동기 변형을 사용할 수 있는 기능과 함께 성능을 크게 개선하고 새로운 사용 사례를 차단 해제합니다.
짐작할 수 있듯이 프로젝트 목표의 마지막 사항인 사용 가능한 JavaScript API를 사용한 영구 클라이언트 측 저장소 지원에는 데이터베이스 파일에 데이터를 영구 저장하는 것과 관련된 엄격한 성능 요구사항이 있습니다.
여기에서 출처 비공개 파일 시스템, 더 구체적으로는 FileSystemFileHandle
객체의 createSyncAccessHandle()
메서드가 사용됩니다. 이 메서드는 동기식으로 파일에서 읽고 쓰는 데 사용할 수 있는 FileSystemSyncAccessHandle
객체로 확인되는 프로미스를 반환합니다. 이 메서드의 동기적 특성은 성능 이점을 가져오지만, 기본 스레드가 차단되지 않도록 하려면 출처 비공개 파일 시스템 내 파일의 전용 웹 워커 내에서만 사용할 수 있습니다.
필수 헤더 설정
여러 파일 중에서 다운로드한 SQLite Wasm 보관 파일에는 sqlite3 WASM/JS 빌드를 구성하는 sqlite3.js
파일과 sqlite3.wasm
파일이 포함되어 있습니다. jswasm
디렉터리에는 핵심 sqlite3 결과물이 포함되어 있고 최상위 디렉터리에는 데모 및 테스트 앱이 포함되어 있습니다. 브라우저는 file://
URL에서 Wasm 파일을 제공하지 않으므로 이로 빌드하는 모든 앱에는 웹 서버가 필요하며 서버는 파일을 제공할 때 응답에 다음 헤더를 포함해야 합니다.
Cross-Origin-Opener-Policy
는same-origin
디렉티브로 설정되어 탐색 컨텍스트를 동일 출처 문서로만 격리합니다. 교차 출처 문서는 동일한 탐색 컨텍스트에서 로드되지 않습니다.Cross-Origin-Embedder-Policy
이require-corp
디렉티브로 설정되어 있으므로 문서는 동일한 출처의 리소스 또는 다른 출처에서 로드할 수 있다고 명시적으로 표시된 리소스만 로드할 수 있습니다.
이러한 헤더가 필요한 이유는 SQLite Wasm이 SharedArrayBuffer
에 종속되며 이러한 헤더를 설정하는 것이 보안 요구사항의 일부이기 때문입니다.
DevTools로 트래픽을 검사하면 다음 정보가 표시됩니다.
Speedtest
SQLite팀은 지원 중단된 Web SQL과 비교하여 WebAssembly 구현에 관한 몇 가지 벤치마크를 실행했습니다. 이 벤치마크는 SQLite Wasm이 일반적으로 웹 SQL과 거의 비슷한 속도를 보인다는 것을 보여줍니다. 때로는 조금 느려지고 때로는 조금 빨라집니다. 결과 페이지에서 모든 세부정보를 확인하세요.
시작 코드 샘플
앞서 언급한 바와 같이 출처 비공개 파일 시스템 지속성 백엔드가 있는 SQLite Wasm은 Worker 컨텍스트에서 실행되어야 합니다. 좋은 소식은 라이브러리가 이 모든 작업을 자동으로 처리하며 기본 스레드에서 바로 사용할 수 있다는 점입니다.
import { sqlite3Worker1Promiser } from '@sqlite.org/sqlite-wasm';
(async () => {
try {
console.log('Loading and initializing SQLite3 module...');
const promiser = await new Promise((resolve) => {
const _promiser = sqlite3Worker1Promiser({
onready: () => {
resolve(_promiser);
},
});
});
console.log('Done initializing. Running demo...');
let response;
response = await promiser('config-get', {});
console.log('Running SQLite3 version', response.result.version.libVersion);
response = await promiser('open', {
filename: 'file:worker-promiser.sqlite3?vfs=opfs',
});
const { dbId } = response;
console.log(
'OPFS is available, created persisted database at',
response.result.filename.replace(/^file:(.*?)\?vfs=opfs$/, '$1'),
);
await promiser('exec', { dbId, sql: 'CREATE TABLE IF NOT EXISTS t(a,b)' });
console.log('Creating a table...');
console.log('Insert some data using exec()...');
for (let i = 20; i <= 25; ++i) {
await promiser('exec', {
dbId,
sql: 'INSERT INTO t(a,b) VALUES (?,?)',
bind: [i, i * 2],
});
}
console.log('Query data with exec()');
await promiser('exec', {
dbId,
sql: 'SELECT a FROM t ORDER BY a LIMIT 3',
callback: (result) => {
if (!result.row) {
return;
}
console.log(result.row);
},
});
await promiser('close', { dbId });
} catch (err) {
if (!(err instanceof Error)) {
err = new Error(err.result.message);
}
console.error(err.name, err.message);
}
})();
데모
데모에서 위 코드가 실행되는 모습을 확인하세요. Glitch에서 소스 코드를 확인해야 합니다. 아래의 삽입된 버전은 OPFS 백엔드를 사용하지 않지만 별도의 탭에서 데모를 열면 사용합니다.
출처 비공개 파일 시스템 디버그
SQLite Wasm의 원본 비공개 파일 시스템 출력을 디버그하려면 OPFS Explorer Chrome 확장 프로그램을 사용하세요.
확장 프로그램을 설치한 후 Chrome DevTools를 열고 OPFS 탐색기 탭을 선택하면 SQLite Wasm이 원본 비공개 파일 시스템에 쓰는 내용을 검사할 수 있습니다.
DevTools의 OPFS Explorer 창에서 파일을 선택하면 로컬 디스크에 저장할 수 있습니다. 그런 다음 SQLite 뷰어와 같은 앱을 사용하여 데이터베이스를 검사하면 SQLite Wasm이 실제로 약속한 대로 작동하는지 확인할 수 있습니다.
도움말 확인 및 의견 보내기
SQLite Wasm은 SQLite 커뮤니티에서 개발하고 유지관리합니다. 지원 포럼에서 검색하고 게시물을 작성하여 도움을 받고 의견을 제공하세요. 전체 문서는 SQLite 사이트에서 확인할 수 있습니다.