[]
        
(Showing Draft Content)

튜토리얼: 동시 작업 클라이언트와 서버를 분리하여 배포하기

SpreadJS 동시 작업 시스템은 Collaboration Client(프론트엔드)와 Collaboration Server(백엔드)를 사용하여 실시간 다중 사용자 편집 환경을 제공합니다.

이 매뉴얼은 프론트엔드(정적 웹사이트)와 백엔드(Node.js WebSocket 서비스)를 완전히 분리하여 각각 독립적으로 배포하는 방법을 설명합니다.

사전 준비 사항

주요 기능

  • 프론트엔드–백엔드 분리를 통한 유연한 배포

  • 여러 사용자가 동시에 SpreadJS 워크북을 편집하는 실시간 동기화

  • Node.js 및 WebSocket 기반의 확장 가능한 백엔드

  • SQLite 기반 문서 상태 영속성 저장

  • 다양한 프론트엔드호스팅 환경(Nginx, Apache, IIS 등) 지원

프로젝트 구조

프로젝트는 두 개의 독립된 디렉터리로 구성됩니다.

collaboration-server/   # 백엔드 전용 – Node.js 환경에 배포
│── server.js
│── init-database.js
│── package.json

collaboration-client/   # 프론트엔드 전용 – 정적 사이트
│── public/
│   ├── index.html
│   ├── client.js
│   └── client.bundle.js  # webpack 빌드로 생성
│── webpack.config.js
│── package.json

세부 단계


Collaboration Server 설정

1단계: 프로젝트 디렉터리 생성

mkdir collaboration-server
cd collaboration-server
npm init -y

2단계: package.json 설정

{
  "name": "collaboration-server",
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "start": "node ./server.js"
  },
  "dependencies": {}
}

3단계: 의존성 설치

npm install @mescius/js-collaboration @mescius/js-collaboration-ot
npm install @mescius/spread-sheets-collaboration
npm install sqlite3 @mescius/js-collaboration-ot-sqlite

4단계: server.js 생성

import http from 'http';
import sqlite3 from 'sqlite3';
import { Server } from '@mescius/js-collaboration';
import * as OT from '@mescius/js-collaboration-ot';
import { type } from '@mescius/spread-sheets-collaboration';
import { SqliteDb } from '@mescius/js-collaboration-ot-sqlite';

// SpreadJS 동시 작업 타입 등록
OT.TypesManager.register(type);

const httpServer = http.createServer();
const server = new Server({ httpServer });
const port = 8080;

// SQLite 데이터베이스 및 어댑터 초기화
const db = new sqlite3.Database("./docs.db");
const sqliteDbAdapter = new SqliteDb(db);

// OT 문서 서비스 구성
const documentServices = new OT.DocumentServices({ db: sqliteDbAdapter });
server.useFeature(OT.documentFeature(documentServices));

// 서버 시작
httpServer.listen(port, () => {
    console.log(`Collaboration server listening on port ${port}`);
});

5단계: 데이터베이스 초기화

init-database.js 파일을 생성합니다.

import sqlite3 from "sqlite3";
const db = new sqlite3.Database("./docs.db");
async function initSqliteDataTables(db) {
    const run = (sql) => {
        return new Promise((resolve, reject) => {
            db.run(sql, (e) => (e ? reject(e) : resolve()));
        });
    };
    await run(
        `CREATE TABLE IF NOT EXISTS documents (
            id TEXT PRIMARY KEY,
            type TEXT NOT NULL,
            version INTEGER NOT NULL,
            snapshot_version INTEGER NOT NULL
        )`
    );
    await run(
        `CREATE TABLE IF NOT EXISTS operations (
            doc_id TEXT NOT NULL,
            version INTEGER NOT NULL,
            operation TEXT NOT NULL,
            PRIMARY KEY (doc_id, version),
            FOREIGN KEY (doc_id) REFERENCES documents (id) ON DELETE CASCADE
        )`
    );
    await run(
        `CREATE TABLE IF NOT EXISTS snapshot_fragments (
            doc_id TEXT NOT NULL,
            fragment_id TEXT NOT NULL,
            data TEXT NOT NULL,
            PRIMARY KEY (doc_id, fragment_id),
            FOREIGN KEY (doc_id) REFERENCES documents (id) ON DELETE CASCADE
        )`
    );
}
// 초기화 함수 호출
initSqliteDataTables(db);

이 단계는 최초 설정 시 또는 데이터베이스를 초기화한 후에만 실행하면 됩니다.

node init-database.js

Collaboration Client 설정

1단계: 프론트엔드 프로젝트 생성

mkdir collaboration-client
cd collaboration-client
npm init -y

2단계: package.json 설정

{
  "name": "collaboration-client",
  "version": "1.0.0",
  "scripts": {
    "build": "webpack"
  },
  "dependencies": {}
}

3단계: 의존성 설치

# SpreadJS 및 동시 작업 클라이언트 패키지
npm install @mescius/spread-sheets @mescius/spread-sheets-collaboration-addon
npm install @mescius/js-collaboration-client @mescius/js-collaboration-ot-client
npm install @mescius/spread-sheets-collaboration-client

# 빌드 도구
npm install --save-dev webpack webpack-cli style-loader css-loader

4단계: public 폴더 및 파일 생성

프론트엔드 HTML 페이지 생성 및 수정: public/index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>SpreadJS Real-Time Collaboration</title>
    <script src="./client.bundle.js"></script>
</head>
<body>
    <div id="ss" style="width:100vw; height:95vh; border:1px solid darkgray;"></div>
</body>
</html>

프론트엔드 JavaScript 코드 생성 및 수정: public/client.js

import * as GC from '@mescius/spread-sheets';
import '@mescius/spread-sheets-collaboration-addon';
import { Client } from "@mescius/js-collaboration-client";
import * as OT from "@mescius/js-collaboration-ot-client";
import { type, bind } from '@mescius/spread-sheets-collaboration-client';
import "@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css";

// SpreadJS 동시 작업 데이터 타입 등록
OT.TypesManager.register(type);

// ===== 중요: 실제 동시 작업 서버 주소로 수정 =====
// 로컬 개발 예시:
const SERVER_URL = "ws://127.0.0.1:8080";

// 운영 환경 예시:
// const SERVER_URL = "wss://collab.yourdomain.com";
// const SERVER_URL = "wss://your-app.herokuapp.com";

window.onload = async function () {
    // SpreadJS 워크북 초기화
    const workbook = new GC.Spread.Sheets.Workbook('ss');

    // 클라이언트 연결 생성 및 동시 작업 룸 참여
    const conn = new Client(SERVER_URL).connect('room1');
    const doc = new OT.SharedDoc(conn);

    // 연결 및 문서 동기화 오류 처리
    doc.on('error', (err) => console.error('Collaboration error:', err));

    // 서버에서 문서 상태 가져오기
    await doc.fetch();

    if (!doc.type) {
        // 초기 콘텐츠로 새 공유 문서 생성
        workbook.getActiveSheet().getCell(0, 0).value("default content");
        await doc.create(workbook.collaboration.toSnapshot(), type.uri, {});

        // 워크북을 공유 문서에 바인딩하여 실시간 동기화
        bind(workbook, doc);
    } else {
        // 이미 공유 문서가 존재하는 경우 바인딩만 수행
        bind(workbook, doc);
    }
};

프론트엔드 프로젝트 설정 생성 및 수정: webpack.config.js

const path = require("path");

module.exports = {
  entry: "./public/client.js",
  output: {
    path: path.resolve(__dirname, "public"),
    filename: "client.bundle.js",
  },
  mode: "development",
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: ["style-loader", "css-loader"],
      },
    ],
  },
};

5단계: 프론트엔드 빌드

npm run build

빌드가 완료되면 public/client.bundle.js 파일이 생성됩니다.

6단계: 프론트엔드 배포

public/ 폴더 전체를 정적 호스팅 서버(Nginx, Apache, IIS 등)에 업로드합니다.


기능 설명

기능

설명

실시간 동기화

하나의 클라이언트에서 수행한 편집이 동일한 문서 룸을 공유하는 모든 사용자에게 즉시 반영됩니다.

문서 영속성

서버는 SQLite를 사용하여 스냅샷과 작업 이력을 저장합니다.

프론트엔드–백엔드 분리

각 구성 요소를 독립적으로 배포 및 확장할 수 있습니다.

WebSocket 통신

가볍고 효율적인 실시간 연결을 제공합니다.

크로스 플랫폼 호스팅

모든 정적 웹 호스트 및 Node.js 환경에서 동작합니다.

사용 방법

1단계: 백엔드 시작

cd collaboration-server
npm run start

예상 출력: Collaboration server listening on port 8080

2단계: 프론트엔드 호스팅

collaboration-client/public/ 디렉터리를 정적 서버에 배포합니다.

3단계: 실시간 동시 작업 테스트

  1. 여러 브라우저 또는 기기에서 프론트엔드 페이지를 엽니다.

  2. 한 인스턴스에서 셀을 편집합니다.

  3. 모든 연결된 클라이언트에 변경 사항이 즉시 반영되는지 확인합니다.