# 마일스톤 데이터베이스 어댑터

## Content

**마일스톤 데이터베이스 어댑터(Milestone Database Adapter)**는 문서 스냅샷을 주기적으로 저장함으로써 과거 스냅샷을 자주 조회하는 경우의 성능을 향상시킵니다.
최신 스냅샷만 유지하는 기본 데이터베이스 어댑터([IDatabaseAdapter](/spreadjs/api/collaboration/js-collaboration-ot/interfaces/IDatabaseAdapter))와 달리, 마일스톤 어댑터([IMilestoneDatabaseAdapter](/spreadjs/api/collaboration/js-collaboration-ot/interfaces/IMilestoneDatabaseAdapter))는 여러 버전의 스냅샷을 저장하여 [fetchHistorySnapshot](/spreadjs/api/collaboration/js-collaboration-ot/classes/DocumentServices#fetchhistorysnapshot)의 성능을 최적화합니다.

**적용 시나리오**: 문서 이력을 빠르게 조회해야 하는 애플리케이션
**기본 구현**: 내장 메모리 기반 어댑터

## 인터페이스: IMilestoneDatabaseAdapter

커스텀 스토리지를 지원하려면 다음 메서드들을 구현해야 합니다.

```typescript
/**
 * 마일스톤 데이터베이스 어댑터를 정의하는 인터페이스.
 */
export interface IMilestoneDatabaseAdapter<S> {
    /**
     * 마일스톤 스냅샷을 저장하는 간격.
     * -1이면 마일스톤 스냅샷 저장이 비활성화됩니다.
     */
    interval: number;
    /**
     * 마일스톤 스냅샷을 저장합니다.
     */
    saveMilestoneSnapshot(snapshot: ISnapshot<S>): Promise<boolean>;
    /**
     * 문서 ID와 버전으로 마일스톤 스냅샷을 조회합니다.
     */
    getMilestoneSnapshot(id: string, version: number): Promise<ISnapshot<S> | null>;
}
```

**`interval` 설명**:
마일스톤 스냅샷을 저장하는 빈도를 제어합니다. 예를 들어 `interval`을 `1000`으로 설정하면 1000개의 연산(`op`)마다 스냅샷이 저장됩니다.

* 작은 값: 저장 공간 사용량은 증가하지만 과거 이력 조회 성능이 향상됩니다.
* 큰 값: 저장 공간 사용량은 감소하지만 이력 재구성에 시간이 더 걸릴 수 있습니다.

## 기본 구현

`js-collaboration-ot` 라이브러리는 내장 메모리 기반 마일스톤 어댑터를 제공합니다.

* **설명**: 데이터는 RAM에 저장되며 재시작 시 사라집니다.
* **용도**: 개발 및 테스트.
* **설정**: 기본 `interval` 값은 `-1`.

>type=warning
> 내장 어댑터 구현은 개발 및 테스트 환경에만 적합합니다.
> 프로덕션 환경에서는 반드시 커스텀 어댑터를 구현하세요.

## 커스텀 어댑터 구현

[IMilestoneDatabaseAdapter](/spreadjs/api/collaboration/js-collaboration-ot/interfaces/IMilestoneDatabaseAdapter) 인터페이스를 구현하여 커스텀 어댑터를 만들 수 있습니다.
아래는 간단한 **메모리 기반 마일스톤 어댑터** 예제입니다.

```typescript
import { IMilestoneDatabaseAdapter } from '@mescius/js-collaboration-ot';

// 커스텀 마일스톤 어댑터
class CustomMilestoneDb implements IMilestoneDatabaseAdapter {
  constructor() {
    this.interval = 1000; // 기본 간격
    this.map = new Map(); // 스냅샷 목록 저장
  }

  async saveMilestoneSnapshot(snapshot) {
    let list = this.map.get(snapshot.id) || [];
    list.push(JSON.parse(JSON.stringify(snapshot)));
    list.sort((a, b) => a.v - b.v); // 버전 기준 정렬
    this.map.set(snapshot.id, list);
    return true;
  }

  async getMilestoneSnapshot(id, version) {
    const list = this.map.get(id) || [];
    let result;
    for (const snapshot of list) {
      if (snapshot.v <= version) {
        result = snapshot;
      } else {
        break;
      }
    }
    return JSON.parse(JSON.stringify(result)) ?? null;
  }
}

const docService = new DocumentServices({
  db: new MemoryDb(),
  milestoneDb: new CustomMilestoneDb()
});
```

## 요약

마일스톤 데이터베이스 어댑터는 스냅샷을 주기적으로 저장하여 과거 이력 접근 성능을 크게 향상시킵니다.
내장 메모리 기반 구현은 테스트 용도로 적합하며, 프로덕션 환경에서는 커스텀 어댑터를 구현하는 것이 권장됩니다.
`DocumentServices`에 마일스톤 어댑터를 통합하면 `fetchHistorySnapshot`의 효율이 크게 개선되어, 이력 데이터를 자주 조회하는 애플리케이션에 특히 유용합니다.