Spring Boot와 NATS JetStream을 활용한 실시간 M:N(다대다) 협업 캔버스 개념 증명 프로젝트
이 POC는 NATS JetStream의 강력한 실시간 메시징과 지속성 보장 기능을 활용하여, 학교 수업 환경과 같은 실시간 협업 캔버스 시나리오를 구현합니다.
- 실시간성 검증: 1:N (선생님 1명:학생 12명) 환경에서 1초 이내 드로잉 이벤트 동기화
- 상태 동기화 검증: 재접속/늦은 참여 시 캔버스 상태 즉시 복원
순수 WebSocket 대비 NATS JetStream을 선택한 이유:
- 자동 재연결 및 메시지 재전송 (클라이언트 장애 대응)
- 메시지 영속성 보장 (서버 재시작 후에도 데이터 보존)
- 강력한 Replay 기능 (DeliverLast 정책으로 효율적인 상태 동기화)
- 클라이언트 직접 연결 (백엔드 병목 현상 제거)
spring-nats-canvas-poc/
├── backend/ # Spring Boot 백엔드
│ ├── src/
│ │ └── main/
│ │ ├── java/
│ │ │ └── com/example/canvaspoc/
│ │ │ ├── config/ # NATS 연결 설정
│ │ │ ├── controller/ # REST API
│ │ │ ├── service/ # JWT 발급 등 비즈니스 로직
│ │ │ └── domain/ # 도메인 모델
│ │ └── resources/
│ │ └── application.yml # 설정 파일
│ ├── pom.xml # Maven 의존성
│ └── Dockerfile # Docker 이미지 빌드
│
├── frontend/ # Canvas 클라이언트
│ └── src/
│ └── index.html # 웹 클라이언트 (Fabric.js + nats.js)
│
├── infra/ # 인프라 구성
│ ├── docker-compose.yml # 서비스 오케스트레이션
│ ├── nats.conf # NATS 서버 설정
│ └── init-nats-stream.sh # JetStream 스트림 초기화
│
└── docs/
└── PRD.md # 상세 기술 설계 명세서
# 인프라 디렉토리로 이동
cd infra
# Docker Compose로 모든 서비스 시작
docker-compose up -d
# 서비스 상태 확인
docker-compose ps# 스트림 생성 스크립트 실행
./init-nats-stream.sh- Frontend: http://localhost:3000
- Backend API: http://localhost:8080
- NATS Dashboard: http://localhost:8222
역할: 인증/권한 게이트웨이
- 세션 생성 및 참여 관리
- NATS User JWT 동적 발급 (Decentralized JWT)
- 권한 관리 (선생님/학생 역할 분리)
주요 API:
POST /api/session/create- 세션 생성 (선생님용)POST /api/session/join/{sessionId}- 세션 참여 (학생용)
역할: 실시간 캔버스 렌더링
- Fabric.js 기반 캔버스 렌더링
- NATS WebSocket 직접 연결
- JetStream을 통한 상태 동기화
역할: 실시간 메시징 + 지속성 계층
- Core NATS: 고성능 실시간 이벤트 브로드캐스팅
- JetStream: 캔버스 상태 영속성 및 재현
주제(Subject) 구조:
canvas.session.{sessionId}.draw- 실시간 드로잉 이벤트canvas.session.{sessionId}.snapshot- 캔버스 전체 상태 스냅샷canvas.session.{sessionId}.cursor- 실시간 커서 공유 (선택)
- Docker & Docker Compose
- Java 17 (백엔드 로컬 개발 시)
- Maven 3.9+ (백엔드 로컬 개발 시)
cd backend
# Maven 빌드 및 실행
./mvnw spring-boot:run
# 또는 Gradle 사용 시
./gradlew bootRun환경변수 설정 (backend/src/main/resources/application.yml):
nats:
server:
url: nats://localhost:4222
auth:
account-seed: ${NATS_AUTH_ACCOUNT_SEED}cd frontend
# 간단한 HTTP 서버 실행
python3 -m http.server 8000
# 브라우저에서 http://localhost:8000 접속- 선생님 클라이언트에서 세션 생성
- 학생 클라이언트에서 세션 참여
- 선생님이 캔버스에 그림 그리기
- 검증: 학생 캔버스에 1초 이내 렌더링
- 복잡한 그림이 그려진 세션 준비
- 선생님이 스냅샷 발행
- 학생 브라우저 새로고침 (F5)
- 검증: 학생 캔버스에 전체 그림 즉시 복원
- 선생님이 5분간 혼자 그림 그림
- 새로운 학생이 세션 참여
- 검증: 참여 즉시 5분간의 그림 전체 표시
- 학생 클라이언트 콘솔에서 스냅샷 발행 시도
- 검증: NATS 서버가 권한 위반 오류 반환
# NATS 컨테이너 로그 확인
docker logs canvas-nats
# 포트 충돌 확인
lsof -i :4222# Maven 클린 빌드
cd backend
./mvnw clean install
# Docker 이미지 재빌드
cd ../infra
docker-compose build --no-cache spring-backendcd infra
docker-compose down -v
docker-compose up -d
./init-nats-stream.sh- Task 1: 프로젝트 구조 설정
- Task 2: Docker Compose 환경 구성
- Task 3: NATS JetStream 스트림 설정
- Task 4: Spring Boot NATS 연동
- Task 5: JWT 발급 서비스 구현
- Task 6: REST API 구현
- Task 7: Frontend 캔버스 클라이언트 구현
- ...
이 프로젝트는 개념 증명(POC) 목적으로 제작되었습니다.
프로젝트 개선 제안이나 버그 리포트는 이슈로 등록해주세요.
참고: 본 POC는 개발/테스트 환경을 위한 설정입니다. 프로덕션 배포 시 다음 사항을 반드시 적용하세요:
- TLS/SSL 암호화 활성화
- 보안 자격증명 Vault 관리
- NATS 클러스터링 및 고가용성 구성
- 이벤트 Throttling/Debouncing