[]
        
(Showing Draft Content)

다중 서버 배포

프로덕션 환경에서 SpreadJS Collaboration Server가 높은 동시성을 처리하거나 고가용성을 달성해야 하는 경우, 일반적으로 로드 밸런서 뒤에 여러 서버 인스턴스를 배포합니다.

그러나 사용자가 서로 다른 서버에 연결되어 있을 경우 메시지 브로드캐스팅 문제가 발생할 수 있습니다. 예를 들어, 동일한 동시 작업 룸에 있더라도 “서버 A”에 연결된 사용자는 “서버 B”에 연결된 사용자와 실시간 업데이트를 주고받을 수 없습니다.

이를 해결하기 위해 SpreadJS Collaboration은 Socket.IO Adapter 통합을 지원합니다. 이 어댑터는 모든 동시 작업 이벤트와 메시지를 서버 인스턴스 전반에 걸쳐 원활하게 분산시켜, 어떤 노드에 연결되어 있든 모든 클라이언트 간 실시간 동기화를 가능하게 합니다.

사전 요구 사항

구성 요소

설명

Node.js

v16 이상

Redis Server

v7.0 이상, 모든 동시 작업 서버에서 접근 가능

@mescius/js-collaboration

SpreadJS Collaboration 서버 패키지

@socket.io/redis-adapter

다중 노드 통신을 위한 Redis 어댑터

Load Balancer

Nginx, Kubernetes Service 또는 동등한 구성

기능 설명

확장 가능한 동시 작업 아키텍처

  • Socket.IO Redis Adapter를 사용한 다중 서버 배포 지원

  • 서버 간 실시간 동시 작업 데이터(워크북 업데이트, 선택 상태, 연결 이벤트) 동기화

  • 모든 사용자 세션 전반에 걸친 데이터 일관성 및 동기화 보장

  • 로드 밸런싱 시스템(Nginx, Kubernetes 등)과 호환

Redis Pub/Sub 메커니즘

어댑터는 Redis의 Publish/Subscribe(Pub/Sub) 를 사용하여 다음을 수행합니다.

  • 한 서버에서 발생한 소켓 이벤트를 다른 서버로 브로드캐스트

  • 동일한 동시 작업 룸의 업데이트를 모든 서버에 전달

  • 서로 다른 인스턴스에 연결된 사용자 간 동기화 유지

사용 방법

의존성 설치

서버 프로젝트 디렉터리에서 다음 명령을 실행하고, Redis 서버가 실행 중이며 모든 노드에서 접근 가능한지 확인합니다.

npm install @mescius/js-collaboration
npm install redis
npm install @socket.io/redis-adapter

Socket.IO Redis Adapter 적용

동시 작업 서버 설정 파일(예: server.js)에 다음 코드를 추가합니다.

import { Server } from '@mescius/js-collaboration';
import { createClient } from 'redis';
import { createAdapter } from '@socket.io/redis-adapter';

// 1. Pub/Sub 클라이언트 초기화
const pubClient = createClient({ url: 'redis://localhost:6379' });
const subClient = pubClient.duplicate();
await Promise.all([pubClient.connect(), subClient.connect()]);

// 2. 어댑터 주입
const server = new Server({
    port: 8080,
    socketIoAdapter: createAdapter(pubClient, subClient)
});

로드 밸런서 구성

여러 서버 인스턴스로 사용자 트래픽을 분산하기 위해 로드 밸런서가 필요합니다. 아래는 권장되는 두 가지 구성 예시입니다.

Nginx 배포 예시

Nginx를 리버스 프록시로 사용하여 upstream 블록에 서버 목록을 정의하고, WebSocket 프로토콜 업그레이드(Upgrade) 헤더를 설정할 수 있습니다.

  • Upstream: 백엔드 서버 노드의 IP와 포트를 정의

  • Upgrade 헤더: WebSocket 핸드셰이크를 지원하기 위해 Upgrade, Connection 헤더를 명시적으로 설정해야 함

http {
  # 백엔드 서버 목록 정의
  upstream nodes {
    server 103.32.2.101:3000;
    server 103.32.2.102:3000;
    server 103.32.2.103:3000;
  }

  server {
    listen 3000;
    server_name yourhost.com;

    location /collaboration {
      proxy_pass http://nodes;

      # WebSocket 지원 활성화
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";
      
      # 실제 IP 전달(선택 사항)
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $host;
    }
  }
}

Kubernetes(K8s) 배포 예시

Kubernetes는 replicas서비스 노출을 통해 확장 가능하고 자체 복구가 가능한 배포 방식을 제공합니다.

  • replicas: 다중 서버 배포를 위해 3 이상으로 설정

  • 환경 변수: 모든 Pod가 동일한 Redis 서비스에 연결되도록 env 변수를 통해 Redis 및 데이터베이스 주소 전달

apiVersion: apps/v1
kind: Deployment
metadata:
  name: collaboration-app
spec:
  replicas: 3 # 다중 서버 구성을 위한 레플리카 수
  selector:
    matchLabels:
      app: collaboration-app
  template:
    metadata:
      labels:
        app: collaboration-app
    spec:
      containers:
        - name: collaboration-app
          image: collaboration-app:v1 # 실제 이미지로 교체
          ports:
            - containerPort: 3000
          # 공유 리소스 연결을 보장하기 위한 환경 변수 설정
          env:
            - name: DB_HOST
              value: "postgres-service" # K8s DB 서비스 이름
            - name: REDIS_HOST
              value: "redis-service"    # K8s Redis 서비스 이름
---
apiVersion: v1
kind: Service
metadata:
  name: collaboration-app-service
spec:
  selector:
    app: collaboration-app
  ports:
    - port: 3000
      targetPort: 3000
  type: LoadBalancer