Accord

팀장 (5인 팀)

5인
팀 규모
5주
개발 기간
7개
마이크로서비스
2025.02
배포

TL;DR

Figma·Discord·Notion을 하나로 통합한 개발자 협업 플랫폼. WebRTC 시그널링·STUN·TURN 서버를 직접 구현하고, Spring Boot + Go 폴리글랏 마이크로서비스에 Consul 서비스 디스커버리를 연동했습니다.

📊 핵심 아키텍처

개요

팀 협업에 필요한 도구가 Figma, Discord, Notion 등으로 분산되어 있다는 문제에서 출발한 개발자 협업 플랫폼입니다. 캔버스, 실시간 채팅, 음성 통화, 칸반 보드, 팀 노트를 하나의 플랫폼에서 제공합니다. 5인 팀이 5주간 개발했으며 2025년 2월에 배포했습니다. Spring Boot 메인 백엔드와 Go(Fiber) 특화 서비스로 역할을 분리하는 폴리글랏 마이크로서비스 구조로 설계했습니다. WebRTC 실시간 통신을 위해 Node.js WebSocket 시그널링 서버, Go + Pion 기반 STUN·TURN 서버를 직접 구현했습니다. Consul 서비스 디스커버리로 각 서비스가 API Gateway를 통해 동적으로 라우팅되며, Prometheus + Grafana로 전체 서비스를 모니터링합니다.

핵심 성과

  • WebSocket 기반 시그널링 서버 구현 — subscribe/publish/unsubscribe 토픽 구조로 다중 피어 Offer/Answer 교환 처리
  • Go + Pion 라이브러리로 STUN 서버 직접 구현 (UDP, XOR-MAPPED-ADDRESS 응답)
  • Go + Pion으로 TURN 서버 구현 — STUN으로 NAT 통과 실패 시 릴레이 연결 제공
  • Consul 서비스 디스커버리 연동 — 시그널링 서버 자동 등록 및 SIGINT/SIGTERM 시 graceful 해제
  • Spring Boot + Go(Fiber) 폴리글랏 마이크로서비스 — 역할별 언어 분리 (팀관리·칸반·채팅 vs 노트·캔버스·오디오)
  • gRPC 기반 서비스 간 공개키 로테이션 구현
  • RabbitMQ 기반 실시간 채팅 메시징 파이프라인 구성
  • MariaDB(관계형) + MongoDB(문서) 폴리글랏 퍼시스턴스 설계
  • Prometheus 메트릭 수집 + Grafana 대시보드로 전 서비스 모니터링 구성
  • GitHub Actions + Docker 기반 CI/CD 파이프라인 구축

회고

WebRTC를 처음 다뤄봤는데, 시그널링·ICE·STUN·TURN이 각각 어떤 역할인지 실제로 구현해보기 전까지는 감이 잡히지 않았다. 서버를 직접 만들면서 WebRTC가 왜 이렇게 복잡하게 설계됐는지를 이해했다.

  • WebRTC 연결이 실패하는 이유의 대부분은 NAT다. STUN은 공인 IP를 알려줄 뿐이고, 대칭형 NAT 환경에서는 결국 TURN 릴레이가 필요하다. 이를 직접 구현하면서 ICE 협상 과정 전체를 코드 레벨에서 이해하게 됐다.
  • Consul 서비스 디스커버리를 쓰면서 서비스가 죽을 때 자동으로 해제되는 것이 얼마나 중요한지 알았다. SIGINT/SIGTERM 핸들러에서 Consul 해제를 빠뜨리면 API Gateway가 존재하지 않는 서비스로 계속 요청을 보낸다.
  • Spring과 Go를 함께 쓰는 폴리글랏 구조는 언어 선택의 자유를 주지만, 서비스 간 계약(gRPC 스키마, API 규격)을 팀 전체가 공유하지 않으면 통합 시점에 병목이 생긴다. 계약을 먼저 정의하고 구현하는 순서가 중요하다는 것을 배웠다.

기술 스택

Spring Boot (Java)Go (Fiber)Node.jsReactWebRTCPionMariaDBMongoDBRedisRabbitMQgRPCConsulAWS (S3 · EC2)Prometheus / GrafanaDockerGitHub Actions