저장소
AISCouncil는 모든 데이터를 브라우저에 로컬로 저장합니다. 어떤 서버에도 업로드되지 않습니다. 저장 시스템은 두 계층을 사용합니다 -- 부팅 시 필요한 작고 동기적인 읽기를 위한 localStorage와 봇 프로필 및 채팅 기록과 같은 대용량 비동기 데이터를 위한 IndexedDB.
2계층 저장 아키텍처
| 계층 | API | 용량 | 사용 사례 |
|---|---|---|---|
| localStorage | 동기식 | ~5-10 MB | 테마, API 키, 설정 -- 페이지 로드 시 즉시 필요한 데이터 |
| IndexedDB | 비동기식 | ~100 MB - 1 GB+ | 봇 프로필, 채팅 기록, 애드온 매니페스트 -- 대용량 데이터 |
분할은 localStorage가 빠르지만 크기가 제한되어 있고, IndexedDB는 사실상 무제한이지만 비동기 액세스가 필요하기 때문에 존재합니다. 중요한 부팅 시간 값(테마, API 키, 로그인 상태)은 앱이 비동기 읽기를 기다리지 않고 즉시 렌더링할 수 있도록 localStorage에 있습니다.
localStorage 키
모든 localStorage 키는 ais- 접두사를 사용합니다:
| 키 | 유형 | 설명 |
|---|---|---|
ais-theme | string | 현재 테마 (light, dark 또는 system) |
ais-apikey-anthropic | string | Anthropic API 키 |
ais-apikey-openai | string | OpenAI API 키 |
ais-apikey-xai | string | xAI API 키 |
ais-apikey-gemini | string | Google Gemini API 키 |
ais-apikey-openrouter | string | OpenRouter API 키 |
ais-apikey-deepseek | string | DeepSeek API 키 |
ais-apikey-groq | string | Groq API 키 |
ais-apikey-mistral | string | Mistral API 키 |
ais-user | JSON | 로그인한 사용자 정보 (이름, 이메일, 사진, 제공업체) |
ais-idb-migrated | string | localStorage에서 IndexedDB로 마이그레이션 완료 플래그 |
ais-ollama-endpoint | string | 사용자 정의 Ollama 엔드포인트 URL (기본값: http://localhost:11434) |
ais-custom-providers | JSON | 사용자 정의 사용자 정의 제공업체 구성 배열 |
aiscouncil-settings | JSON | 전역 설정 (테마, 글꼴 크기, 기능 등) |
aiscouncil-usage | JSON | 사용량 추적 데이터 (토큰, 제공업체당 비용) |
localStorage의 API 키는 동일한 출처에서 실행되는 모든 JavaScript에 액세스할 수 있습니다. 이것은 브라우저 앱의 표준이지만 신뢰할 수 없는 브라우저 확장을 설치하지 않아야 함을 의미합니다. 키는 URL 내보내기 또는 데이터 백업에 절대 포함되지 않습니다.
IndexedDB 키
IndexedDB는 ais-db라는 데이터베이스(또는 로그인 시 사용자별 데이터베이스) 내의 키-값 객체 저장소에 데이터를 저장합니다:
| 키 패턴 | 유형 | 설명 |
|---|---|---|
ais-bots | array | 모든 봇 세션 메타데이터 (ID, 이름, 구성, 생성 날짜) |
ais-profiles | array | 모든 저장된 프로필 (개별 및 council) |
ais-chat-{botId} | array | 특정 봇 세션의 채팅 메시지 기록 |
ais-addon-manifests | array | 설치된 애드온/플러그인 매니페스트 |
ais-miniprogram-* | varies | 설치된 미니 프로그램 데이터 |
각 봇 세션에는 자체 채팅 키(ais-chat-abc123)가 있으므로 채팅 기록이 격리되어 독립적으로 로드될 수 있습니다.
자동 마이그레이션
첫 부팅 시 AIS.Storage.init()는 이전 버전의 localStorage에 데이터가 있는지 확인하고 자동으로 IndexedDB로 마이그레이션합니다. ais-idb-migrated 플래그는 후속 로드 시 재마이그레이션을 방지합니다.
IndexedDB를 사용할 수 없는 경우(일부 개인정보 보호 브라우저는 차단함) 저장 계층은 투명하게 localStorage로 대체됩니다. 앱은 계속 작동하지만 ~5-10 MB 저장 제한이 있습니다.
선택적 SQLite WASM 계층
대용량 바이너리 데이터(이미지, 첨부 파일)가 포함된 고급 사용 사례의 경우 저장 시스템은 선택적 SQLite WASM 모듈을 로드할 수 있습니다. SQLite는 IndexedDB와 동시에 실행되며 브라우저의 Origin Private File System(OPFS)에 데이터를 저장합니다.
SQLite는 필요할 때만 로드됩니다 -- 명시적으로 요청되거나 blob 저장에 필요하지 않으면 로드되지 않습니다. 활성화하려면 설정 > 일반 > 저장 백엔드로 이동하여 SQLite를 선택하세요.
| 기능 | IndexedDB | SQLite WASM |
|---|---|---|
| 키-값 저장 | 예 | 예 |
| 바이너리 blob 저장 | 제한됨 | 최적화됨 |
| SQL 쿼리 | 아니요 | 예 |
| 지속성 | 브라우저 관리 | OPFS (파일 기반) |
| 로딩 | 즉시 | 지연 (첫 사용 시) |
AIS.Storage API
AIS.Storage 모듈은 활성 백엔드에 관계없이 작동하는 통합 API를 제공합니다:
핵심 작업
// 저장소 초기화 (부팅 시 한 번 호출)
await AIS.Storage.init();
// 값 가져오기
const bots = await AIS.Storage.get("ais-bots");
// 값 설정
await AIS.Storage.set("ais-bots", updatedBots);
// 키 삭제
await AIS.Storage.delete("ais-chat-abc123");
// 모든 키 나열
const allKeys = await AIS.Storage.keys();
// 모든 키-값 쌍 가져오기
const everything = await AIS.Storage.getAll();
// 모든 데이터 지우기
await AIS.Storage.clear();
Blob 저장소 (SQLite)
// 바이너리 blob 저장
await AIS.Storage.putBlob("image-001", arrayBuffer, "image/png");
// blob 검색
const blob = await AIS.Storage.getBlob("image-001");
// { data: Uint8Array, mime: 'image/png', size: 12345 }
유틸리티 함수
// 동기식 localStorage 헬퍼 (부팅 시간 읽기용)
const theme = AIS.Storage.loadJSON("ais-theme");
AIS.Storage.saveJSON("ais-theme", "dark");
// TTL 캐시 팩토리 (레지스트리 캐싱용)
const cache = AIS.Storage.cache("ais-models-cache", "ais-models-ts", 86400000); // 24시간 TTL
const data = cache.load(); // 캐시된 데이터 읽기
cache.save(newData); // 캐시 업데이트
const stale = cache.isStale(); // 캐시 만료 확인
상태 속성
AIS.Storage.isIDB; // IndexedDB가 활성이면 true
AIS.Storage.hasSQLite; // SQLite WASM이 로드되었으면 true
내보내기 및 가져오기
데이터 내보내기
설정 > 개인정보 > 모든 데이터 내보내기로 이동하거나 API 사용:
const backup = await AIS.Storage.exportData();
// 반환: { bcz_version: "1.0.0", exported: "2026-02-19T...", data: {...} }
내보내기에는 모든 봇 프로필, 채팅 기록, 설정 및 애드온 매니페스트가 포함됩니다. 다음을 명시적으로 제외합니다:
- API 키 (절대 내보내지지 않음)
- 프로필의 멤버별 API 키 (제공업체/모델만으로 축소)
내보내기는 ais-backup-YYYY-MM-DD.json으로 저장됩니다.
SQLite blob 저장소가 활성화된 경우 내보내기는 SQLite 데이터베이스가 포함된 별도의 ais-blobs-YYYY-MM-DD.db 파일도 생성합니다.
데이터 가져오기
설정 > 개인정보 > 데이터 가져오기로 이동하거나 API 사용:
const count = await AIS.Storage.importData(jsonBackup);
// 반환: 가져온 항목 수
가져오기는 다음을 허용합니다:
.json파일 (표준 백업 형식).db파일 (SQLite 데이터베이스)
API 키는 파일에 있더라도 절대 가져오지지 않습니다.
저장 할당량
브라우저 저장 할당량은 플랫폼에 따라 다릅니다:
| 브라우저 | IndexedDB 할당량 | 영구 저장소 사용 시 |
|---|---|---|
| Chrome/Edge | 디스크 공간의 ~60% | 동일, 제거되지 않음 |
| Firefox | 디스크 공간의 ~50% | 사용자에게 권한 요청 |
| Safari | 초기 ~1 GB, 사용자가 더 부여 가능 | 동일 |
AISCouncil는 초기화 시 navigator.storage.persist()를 통해 영구 저장소를 요청합니다. 부여되면 저장 공간이 부족할 때 브라우저가 데이터를 자동으로 제거하지 않습니다.
브라우저의 DevTools를 열고 Application > Storage로 이동한 다음 aiscouncil.net 출처를 찾아 현재 저장 사용량 및 할당량을 확인하세요.
개인정보
모든 데이터는 기기에 유지됩니다:
- 서버 업로드 없음 -- 봇 구성, 채팅 기록 및 설정은 어떤 서버에도 전송되지 않음
- 분석 없음 -- 사용량 데이터가 어디에도 전송되지 않음
- 쿠키 없음 -- 앱은 추적 쿠키가 아닌
localStorage와 IndexedDB 사용 (ais-auth쿠키는 교차 하위 도메인 인증 감지에만 사용) - 타사 저장소 없음 -- 데이터는
aiscouncil.net출처 아래에만 저장됨
데이터 지우기
모든 저장된 데이터를 지우려면:
- 설정 > 개인정보 > 모든 데이터 지우기 -- 모든 IndexedDB 데이터, 프로필 및 채팅 기록 제거
- 브라우저 DevTools > Application > Clear Storage -- 핵 옵션, localStorage 포함 모든 것 제거
- 개별 채팅 삭제 -- 사이드바에서 봇을 마우스 오른쪽 버튼으로 클릭하고 삭제 선택
모든 데이터 지우기는 되돌릴 수 없습니다. 백업을 원하면 먼저 데이터를 내보내세요. localStorage에 저장된 API 키도 브라우저 DevTools를 통해 지울 때 제거됩니다.
미니 프로그램용 봇별 저장소
설치된 각 미니 프로그램은 자체 격리된 저장소 네임스페이스를 얻습니다. 미니 프로그램은 IndexedDB의 앱별 접두사 키에 매핑되는 ais.storage SDK API를 통해 저장소에 액세스합니다. 한 미니 프로그램은 다른 미니 프로그램의 데이터에 액세스할 수 없습니다.
// 미니 프로그램 내부
await ais.storage.set("my-key", "my-value");
const val = await ais.storage.get("my-key");
const keys = await ais.storage.keys();
await ais.storage.remove("my-key");
미니 프로그램용 저장소는 미니 프로그램이 제거될 때 삭제됩니다.