[]
        
(Showing Draft Content)

SharedDoc Class

SharedDoc는 공유 문서 인스턴스를 나타내며, 문서 스냅샷(snapshot)과 작업(op)을 관리하고, 연결(Connection)을 통해 서버와 데이터를 동기화하는 데 사용됩니다. 다중 사용자 작업의 일관성을 보장하기 위해 OT(Operational Transformation) 메커니즘을 지원합니다. 이 문서는 클라이언트 측에서 SharedDoc를 사용하는 방법을 다음 항목 중심으로 설명합니다.

  • SharedDoc 초기화

  • 문서 생성 및 삭제

  • 문서 스냅샷 요청 및 업데이트

  • 작업 제출, 수신 및 변환

  • 이벤트 수신

초기화

SharedDoc 초기화

속성

속성 이름

설명

타입

id

공유 문서의 고유 식별자를 반환합니다.

string (읽기 전용)

version

현재 스냅샷의 버전 번호를 나타냅니다.

number | undefined (읽기 전용)

type

스냅샷의 작업 타입(OT 타입)을 나타냅니다.

OT_Type<S, T> | undefined (읽기 전용)

data

현재 스냅샷의 데이터를 나타냅니다.

S | undefined (읽기 전용)

connection

공유 문서의 연결 객체를 반환합니다.

Connection (읽기 전용)

메서드

fetch

문서의 스냅샷 데이터를 가져오며, 결과는 doc.data에 저장됩니다.

fetch(): Promise<void>

반환값

  • Promise<void>: 스냅샷을 가져온 후 resolve되며, 가져온 스냅샷 데이터는 doc.data에 저장됩니다.

예제

try {
    await doc.fetch();
    if (!doc.type) {
        return console.log('문서가 존재하지 않습니다');
    }
    console.log('문서 스냅샷', doc.data);
} catch (error) {
    if (error) {
        return console.error(error);
    }
}

subscribe

문서의 스냅샷 데이터를 가져오고 이후의 업데이트를 수신합니다.

subscribe(): Promise<void>

반환값

  • Promise<void>: 스냅샷 구독이 완료되면 resolve되며, 구독된 스냅샷 데이터는 doc.data에 저장됩니다.

예제

try {
    await doc.subscribe();
    if (!doc.type) {
        return console.log('문서가 존재하지 않습니다');
    }
    console.log('문서 스냅샷', doc.data);
    
    doc.on('op', (op, source) => {
        console.log('문서가 업데이트됨', op, source);
    });
} catch (error) {
    if (error) {
        return console.error(error);
    }
}

submitOp

문서에 작업을 제출합니다.

submitOp(component: T, options?: IOptions): Promise<void>

매개변수

  • component (T): 작업(op) 컴포넌트

  • options (IOptions): 작업 옵션(선택)

반환값

  • Promise<void>: 작업 제출이 완료되면 resolve됩니다.

예제

// 위치 1에 텍스트 'Hi' 삽입
await doc.submitOp({ pos: 1, text: 'Hi' }, { source: doc.connection.id });
console.log('작업이 제출되었습니다');

create

새 문서를 생성합니다.

create(data: S, type: string, options: IOptions): Promise<void>

매개변수

  • data (S): 스냅샷을 초기화하는 데 사용할 데이터

  • type (string): OT 타입의 URI

  • options (IOptions): 작업 옵션

반환값

  • Promise<void>: 문서 생성이 완료되면 resolve됩니다.

예제

try {
    await doc.create('Hello', textType.uri, {});
    console.log('문서가 성공적으로 생성됨:', doc.data); // "Hello"
} catch (err) {
    console.error('생성 실패:', err);
}

fetchHistorySnapshot

문서의 과거 스냅샷 데이터를 가져옵니다.

fetchHistorySnapshot(options: IHistorySnapshotRequestOptions): Promise<ISnapshot<S>>

매개변수

  • options (IHistorySnapshotRequestOptions): 과거 스냅샷 요청 옵션

반환값

  • Promise<ISnapshot<S>>: 과거 스냅샷을 가져온 후 resolve됩니다.

예제

const snapshot = await doc.fetchHistorySnapshot({ version: 6 }, textType.uri, {});
console.log('과거 스냅샷:', snapshot);

del

문서를 삭제합니다.

del(options: IOptions): Promise<void>

매개변수

  • options (IOptions): 삭제 옵션

반환값

  • Promise<void>: 문서 삭제가 완료되면 resolve됩니다.

restore

문서를 특정 버전으로 복원합니다.

restore(targetVersion: number, options?: IOptions): Promise<void>;

매개변수

  • targetVersion (number): 복원할 대상 버전 번호

  • options (IOptions): 복원 옵션

반환값

  • Promise<void>: 문서 복원이 완료되면 resolve됩니다.

예제

await doc.restore(10); 
console.log('문서가 성공적으로 복원됨:', doc.data); // 버전 10의 데이터

hardRollback

스냅샷 데이터를 최신 버전으로 강제로 롤백합니다.

hardRollback(): Promise<void>

반환값

  • Promise<void>: 롤백이 완료되면 resolve됩니다.

destroy

인스턴스를 제거하고 모든 리소스를 해제합니다.

destroy(): void

이벤트

SharedDocon, once, off 메서드를 통해 다음 이벤트를 지원합니다.

이벤트 이름

설명

매개변수

error

오류가 발생했을 때 트리거됩니다.

err: OTError 객체

load

스냅샷을 가져오거나 구독한 후 트리거됩니다.

없음

create

문서가 생성될 때 트리거됩니다.

source: 작업 출처

beforeOp

작업이 적용되기 전에 트리거됩니다.

op: 작업 데이터, source: 출처

op

작업이 적용된 후 트리거됩니다.

op: 작업 데이터, source: 출처

del

문서가 삭제될 때 트리거됩니다.

data: 삭제 전 데이터, source: 출처

restore

문서가 복원될 때 트리거됩니다.

version: 복원된 버전, source: 출처

hardRollback

강제 롤백 중에 트리거됩니다.

없음

on

이벤트 리스너를 등록합니다.

on<NAME extends keyof ISharedDocEvents<S, T>>(name: NAME, f: ISharedDocEvents<S, T>[NAME]): ISharedDocEvents<S, T>[NAME];

매개변수

  • name (NAME): 이벤트 이름 (ISharedDocEvents<S, T> 인터페이스의 키)

  • f (ISharedDocEvents<S, T>[NAME]): 이벤트 처리 함수

반환값

  • ISharedDocEvents<S, T>[NAME]: 등록된 이벤트 처리 함수

예제

doc.on('op', (op, source) => {
    if (source !== doc.connection.id) {
        console.log('서버로부터 작업 수신:', op);
    }
});

once

한 번만 실행되는 이벤트 리스너를 등록합니다.

once<NAME extends keyof ISharedDocEvents<S, T>>(name: NAME, f: ISharedDocEvents<S, T>[NAME]): void;

매개변수

  • name (NAME): 이벤트 이름

  • f (ISharedDocEvents<S, T>[NAME]): 이벤트 처리 함수

예제

doc.once('op', (op, source) => {
    console.log('op', op, source);
});

off

특정 이벤트 리스너를 제거합니다.

off<NAME extends keyof ISharedDocEvents<S, T>>(name: NAME, f: ISharedDocEvents<S, T>[NAME]): void;

매개변수

  • name (NAME): 이벤트 이름

  • f (ISharedDocEvents<S, T>[NAME]): 제거할 이벤트 처리 함수

UI 컴포넌트와의 연동

다음 그림은 동시 작업 처리 과정을 보여줍니다.

sharedoc_class.6c68f4.png

// UI 컴포넌트 초기화. xxx.uiComponent는 가상의 예시이며,
// 실제로는 Quill 등의 실제 UI 컴포넌트로 대체해야 합니다.
const uiComponent = new xxx.uiComponent();

// 문서 구독
doc.subscribe().then(async () => {
    // 문서가 존재하지 않으면 생성
    if (!doc.type) {
        try {
            await doc.create('Hello', textType.uri, {});
            console.log('성공적으로 생성됨:', doc.data);
        } catch (error) {
            console.error('생성 실패:', error);
            return;
        }
    }

    uiComponent.setText(doc.data);

    // 작업 수신
    doc.on('op', (op, source) => {
        if (source === doc.connection.id) {
            return;
        }
        console.log('작업 수신:', op, '현재 데이터:', doc.data);

        uiComponent.applyOp(op.pos, op.text); // 점진적 업데이트 권장
        // 또는 uiComponent.setText(doc.data); // 전체 업데이트
    });

    // 복원 이벤트 수신 시 UI 동기화
    doc.on('restore', (targetVersion) => {
        console.log(`문서가 버전 ${targetVersion}으로 복원됨`);
        uiComponent.setText(doc.data); // 스냅샷과 일치하도록 전체 업데이트
    });

    // UI에서 발생한 작업을 서버로 제출
    uiComponent.on('op', async (op) => {
        await doc.submitOp(op, { source: doc.connection.id });
    });
});

실시간 동시 작업 텍스트 편집기를 직접 만들어 보세요:

튜토리얼: 실시간 동시 작업 텍스트 편집기