[]
        
(Showing Draft Content)

Undo

동시 작업 시나리오에서는 실행 취소(Undo)와 다시 실행(Redo) 작업도 지원됩니다. 이 문서에서는 이에 대해 자세히 설명합니다.

Undo 스택 저장 방식

동시 작업 환경에서는 모든 변경 사항이 다른 클라이언트 및 서버와 동기화되어야 하므로, Undo의 결과 또한 동기화되어야 합니다. 즉, Undo 결과는 Ops 형태로 저장됩니다. 따라서 Undo 스택에는 Ops가 저장되며, Ops로 표현할 수 없는 동작(예: 선택 상태)은 실행 취소할 수 없습니다.

Undo 대상 내용

동시 작업 환경에서는 각 사용자가 자신의 변경 작업을 수행하고, 다른 사용자의 변경 작업도 수신합니다. Undo 작업은 다른 사용자의 작업이 아니라, 자신이 수행한 작업만 실행 취소해야 합니다.

Undo 충돌

Undo는 사용자 본인의 작업에만 영향을 주기 때문에, 사용자의 작업이 실행 취소되기 전에 다른 클라이언트의 작업이 먼저 수신된 경우, Undo 작업은 다른 클라이언트의 작업을 기준으로 변환되어야 할 수 있습니다.

예를 들어 다음과 같습니다.

  • Alice가 셀 (1,1)의 값을 "old"에서 "new"로 변경

    sheet.setValue(1,1,'new');

  • Bob이 위치 0에 행을 삽입

    sheet.addRows(0,1);

  • Alice가 Undo를 수행하면, (1,1)이 아닌 (2,1)의 값을 "old"로 변경

    sheet.setValue(2,1,'old');

  • Alice가 Redo를 수행하면, 역시 (1,1)이 아닌 (2,1)의 값을 "new"로 변경

    sheet.setValue(2,1,'new');

이 예제에서 볼 수 있듯이, Undo와 Redo의 결과는 최초 실행 시점과 다를 수 있습니다. Undo와 Redo는 다른 클라이언트의 작업이 반영된 결과를 기준으로 실행됩니다.

사용 방법

동시 작업 Undo는 동시 작업 환경에 특화된 기능입니다. 동시 작업이 아닌 환경에서는 기존의 동시 작업이 아닌 Undo 방식이 그대로 사용됩니다.

Undo의 사용 방법 자체는 변경되지 않으며, 여전히 명령(Command)을 통해 실행됩니다. 다만 일부 차이점이 있습니다. 아래에서는 색상을 변경하는 명령을 예로 설명합니다.

undo.868057.png

Command 내부 코드는 두 부분으로 나뉩니다.

동시 작업이 아닌 환경에서는:

  • do: 코드 영역 1 실행

  • undo: 코드 영역 2 실행

  • redo: 코드 영역 1 실행

동시 작업 환경에서는 Undo/Redo가 Ops를 실행하므로, Command 내부 코드는 실행되지 않습니다. 따라서 다음과 같이 동작합니다.

  • do: 코드 영역 1 실행

  • undo: 다른 코드 실행

  • redo: 다른 코드 실행

Command의 실행 로직은 달라지지만, 동시 작업 Undo는 Command와 호환됩니다. 기존 방식으로 작성된 Command를 수정하지 않고도 동시 작업 Undo를 지원할 수 있습니다.

API

Undo 및 Redo 시에는 Command 내부 로직이 실행되지 않으므로, 기존에 Undo/Redo 중에 발생하던 이벤트도 더 이상 발생하지 않습니다. 사용자가 적절한 시점에 자체 처리(UI 갱신 등)를 할 수 있도록, 동시 작업 Undo를 위한 네 가지 신규 이벤트가 추가되었습니다.

interface IChangeSet {
  ops: IOpComponent[];
}
workbook.bind(GC.Spread.Sheets.Events.CollaborationStartUndo, (sender, args: { changeSet: IChangeSet }) => {
    const changeSet = args.changeSet;
    console.log('undo changeSet is:', changeSet);
});
workbook.bind(GC.Spread.Sheets.Events.CollaborationEndUndo, (sender, args: { changeSet: IChangeSet }) => {
    const changeSet = args.changeSet;
    console.log('undo changeSet is:', changeSet);
});
workbook.bind(GC.Spread.Sheets.Events.CollaborationStartRedo, (sender, args: { changeSet: IChangeSet }) => {
    const changeSet = args.changeSet;
    console.log('redo changeSet is:', changeSet);
});
workbook.bind(GC.Spread.Sheets.Events.CollaborationEndRedo, (sender, args: { changeSet: IChangeSet }) => {
    const changeSet = args.changeSet;
    console.log('redo changeSet is:', changeSet);
});