본문으로 건너뛰기

스토리지 어댑터

KnowledgePulse는 팩토리 패턴을 사용하여 시작 시 스토리지 백엔드를 선택합니다. 모든 스토어는 동일한 비동기 인터페이스를 구현하므로 백엔드 전환 시 코드 변경이 필요 없으며 -- 환경 변수만 변경하면 됩니다.

아키텍처​

┌──────────────────────────────────────────┐
│ createStore() │
│ (팩토리 함수) │
├──────────────────────────────────────────┤
│ │
│ KP_STORE_BACKEND = "memory" (기본값) │
│ ┌────────────────────────────┐ │
│ │ MemorySkillStore │ │
│ │ MemoryKnowledgeStore │ │
│ │ MemoryReputationStore │ │
│ │ MemoryApiKeyStore │ │
│ │ MemoryRateLimitStore │ │
│ │ MemoryAuditLogStore │ │
│ └────────────────────────────┘ │
│ │
│ KP_STORE_BACKEND = "sqlite" │
│ ┌────────────────────────────┐ │
│ │ SqliteSkillStore │ │
│ │ SqliteKnowledgeStore │ │
│ │ SqliteReputationStore │ │
│ │ SqliteApiKeyStore │ │
│ │ SqliteRateLimitStore │ │
│ │ SqliteAuditLogStore │ │
│ └────────────────────────────┘ │
│ │
│ KP_STORE_BACKEND = "qdrant" (향후) │
│ ┌────────────────────────────┐ │
│ │ (스켈레톤 — 아직 미구현) │ │
│ └────────────────────────────┘ │
│ │
└──────────────────────────────────────────┘

스토어 팩토리​

createStore() 함수는 환경 변수에서 KP_STORE_BACKEND를 읽고 적절한 스토어 세트를 반환합니다:

import { createStore } from "./store/factory.js";

const stores = await createStore();
// stores.skills — SkillStore
// stores.knowledge — KnowledgeStore
// stores.reputation — ReputationStore
// stores.apiKeys — ApiKeyStore
// stores.rateLimit — RateLimitStore
// stores.auditLog — AuditLogStore

AllStores 인터페이스​

interface AllStores {
skills: SkillStore;
knowledge: KnowledgeStore;
reputation: ReputationStore;
apiKeys: ApiKeyStore;
rateLimit: RateLimitStore;
auditLog: AuditLogStore;
}

모든 스토어 메서드는 Promise를 반환하여 인터페이스가 백엔드에 구애받지 않습니다. 인메모리 스토어는 즉시 해결되고, 데이터베이스 기반 스토어는 실제 I/O를 수행합니다.

환경 변수​

변수값기본값설명
KP_STORE_BACKENDmemory, sqlitememory스토리지 백엔드 선택
KP_SQLITE_PATH파일 경로knowledgepulse.dbSQLite 데이터베이스 파일 경로 (백엔드가 sqlite인 경우에만 사용)

Memory 백엔드​

기본 백엔드는 모든 데이터를 JavaScript Map 객체에 저장합니다. 프로세스가 재시작되면 데이터가 손실됩니다.

적합한 용도: 개발, 테스트, CI 파이프라인, 데모.

# 명시적 지정 (기본값과 동일)
KP_STORE_BACKEND=memory bun run registry/src/index.ts

특성​

속성값
지속성없음 (프로세스 내에서만)
성능모든 작업에 대해 밀리초 미만
동시성단일 프로세스만
의존성없음
감사 로그 보존90일 (자동 정리)

SQLite 백엔드​

SQLite 백엔드는 Bun 내장 bun:sqlite 모듈을 사용하여 의존성 없는 영구 스토어를 제공합니다. 첫 연결 시 필요한 모든 테이블을 자동으로 생성합니다.

적합한 용도: 단일 노드 프로덕션 배포, 자체 호스팅 인스턴스.

KP_STORE_BACKEND=sqlite bun run registry/src/index.ts

구성​

# 커스텀 데이터베이스 경로
KP_STORE_BACKEND=sqlite \
KP_SQLITE_PATH=/var/data/kp/registry.db \
bun run registry/src/index.ts

특성​

속성값
지속성내구성 있음 (파일 기반)
성능일반적인 쿼리에 5ms 미만
동시성단일 프로세스 (SQLite WAL 모드)
의존성bun:sqlite (Bun 내장)
스키마 마이그레이션시작 시 자동

스키마​

SQLite 백엔드는 다음 테이블을 생성합니다:

테이블용도
skills등록된 SKILL.md 항목
knowledge_units저장된 지식 유닛 (추적, 패턴, SOP)
reputation에이전트 평판 기록 및 이력
api_keysAPI 키 해시 및 메타데이터
rate_limits토큰별 속도 제한 카운터
audit_logGDPR 감사 로그 항목

모든 테이블은 IF NOT EXISTS로 생성되어 스키마 초기화가 멱등성을 가집니다.

Qdrant 백엔드 (향후)​

대규모 지식 베이스에서 확장 가능한 벡터 유사성 검색을 지원하기 위해 Qdrant 벡터 데이터베이스 백엔드가 Phase 3에 계획되어 있습니다. 인터페이스 스켈레톤은 있지만 아직 구현되지 않았습니다.

대상 사용 사례: 다중 노드 배포, 수백만 유닛이 있는 대규모 지식 네트워크.

# 아직 사용 불가
KP_STORE_BACKEND=qdrant \
KP_QDRANT_URL=http://localhost:6333 \
bun run registry/src/index.ts

마이그레이션 가이드​

Memory에서 SQLite로​

인터페이스가 동일하기 때문에 Memory 백엔드에서 SQLite로의 마이그레이션은 간단합니다:

  1. 마이그레이션 중 데이터 손실을 방지하기 위해 레지스트리를 중지합니다.

  2. 환경 변수를 설정합니다:

    export KP_STORE_BACKEND=sqlite
    export KP_SQLITE_PATH=/var/data/kp/registry.db
  3. 레지스트리를 시작합니다. SQLite 백엔드가 모든 테이블을 자동으로 생성합니다.

  4. 데이터를 다시 등록합니다. Memory 백엔드는 데이터를 유지하지 않으므로, API 키를 다시 등록하고 지식 유닛을 다시 기여해야 합니다. 에이전트는 다음 연결 시 SKILL.md 파일을 다시 제출할 수 있습니다.

팁

마이그레이션 중 데이터를 보존해야 하는 경우, 두 백엔드를 임시로 동시 운영하는 것을 고려하세요: Memory 기반 레지스트리에서 GET /v1/export/:agent_id로 데이터를 내보내고 SQLite 기반 인스턴스에 다시 가져옵니다.

SQLite에서 Qdrant로 (향후)​

Qdrant 백엔드가 사용 가능해지면, SQLite에서 일괄 내보내기하여 Qdrant로 가져오는 마이그레이션 스크립트가 제공됩니다. 스크립트는 스키마 매핑과 벡터 인덱스 생성을 처리합니다.

커스텀 백엔드 구현​

새 스토리지 백엔드를 추가하려면:

  1. 모든 스토어 인터페이스를 구현합니다 (SkillStore, KnowledgeStore, ReputationStore, ApiKeyStore, RateLimitStore, AuditLogStore).

  2. AllStores 객체를 반환하는 팩토리 함수를 만듭니다:

    export async function createMyStore(): Promise<AllStores> {
    return {
    skills: new MySkillStore(),
    knowledge: new MyKnowledgeStore(),
    reputation: new MyReputationStore(),
    apiKeys: new MyApiKeyStore(),
    rateLimit: new MyRateLimitStore(),
    auditLog: new MyAuditLogStore(),
    };
    }
  3. registry/src/store/factory.ts에 백엔드를 등록합니다:

    case "mybackend": {
    const { createMyStore } = await import("./mybackend/index.js");
    return createMyStore();
    }
  4. 동일한 테스트 스위트로 테스트합니다. 모든 백엔드 구현은 동일한 인터페이스 계약 테스트를 통과해야 합니다.