0. 온라인 스터디 플랫폼, Focussu 백엔드 아키텍처 설계기
― 실시간 스트리밍, Kafka, 그리고 Docker Compose까지
캡스톤 프로젝트에서 "실시간 집중도 분석이 가능한 온라인 스터디 플랫폼"을 개발하게 되었다.
단순히 영상 전화를 넘어서, 각 사용자들의 스트리밍 데이터를 AI 서버로 전달하고, 그 분석 결과를 기반으로 각 사람의 집중도를 실시간으로 보여주는 플랫폼이다.
이 글은 백엔드 개발자로서 내가 어떤 기술을 선택했고, 왜 그런 선택을 하게 되었는지를 정리한 기록이다.
또, 각종 트러블 슈팅을 시리즈 별로 정리할 예정이다.
1. 핵심 요구사항 정리
- 사용자의 비디오/오디오 스트리밍 데이터를 AI 분석 서버로 보내야 한다.
- 따라서 WebRTC의 P2P 방식은 사용할 수 없고, 중계 서버(SFU 기반)가 필요하다.
- 인증/인가(Spring Security)는 비즈니스 로직과 분리해서 깔끔하게 구성해야 한다.
- AI 분석 결과는 Kafka를 통해 비동기적으로 받아야 하며, 백엔드에서 consume 후 DB에 저장해야 한다.
1.1 아키텍쳐(초안)
2. 기술 스택 선정과 고민의 흔적
2.1 Mediasoup – 스트리밍 중계 서버
처음엔 WebRTC를 활용해서 P2P 구조로 만들까도 생각했다. 하지만 이 구조는 클라이언트끼리 직접 연결되기 때문에, 중간에서 데이터를 가로채서 AI 분석 서버로 전달하는 게 불가능했다.
그래서 서버 기반의 SFU 구조로 방향을 틀었고, 여러 옵션 중에서 mediasoup를 선택했다.
mediasoup는 Node.js 기반 SFU로, 커스터마이징 자유도도 높고 성능도 괜찮다.
가장 좋았던 점은 서버가 모든 클라이언트의 stream을 받아 중계해줄 수 있다는 점이었다.
동시에, 이 stream을 그대로 AI 서버에 포워딩할 수 있어 요구사항과 완벽히 맞아떨어졌다.
2.2 Kafka – 집중도 분석 결과 수신을 위한 메시지 큐
AI 분석 서버는 실시간 스트리밍 데이터를 받아 집중도를 분석한다. 그런데 이 결과를 HTTP로 받아 처리하는 건 너무 비효율적이고, 분석 시간이 일정하지 않아 비동기 구조가 필수적이었다.
그래서 Kafka를 도입했다.
- AI 분석 서버는 Kafka topic에 집중도 결과를 발행(publish)
- Spring Boot 백엔드는 Kafka를 구독(consume)하고, 결과를 DB에 저장
Kafka 덕분에 AI 서버와 백엔드가 완전히 decoupling되었다.
처리량이 많아져도 쉽게 스케일링할 수 있고, 분석 지연에도 유연하게 대응 가능하다.
2.3 Spring Boot – 인증과 비즈니스 로직의 허브
Spring Boot는 다음 역할들을 맡는다.
- JWT 기반 사용자 인증 처리
- 스터디룸 입장 요청 시, 중계 서버에 요청을 보내 접속 정보 생성
- 이 정보를 사용자에게 전달해, 스트리밍 서버 연결까지 연결되는 흐름을 만든다.
- Kafka 구독 후 집중도 데이터를 DB에 저장하는 역할도 수행한다.
TDD로 개발하여, 단위 테스트 별로 안전하게 검증된 API를 만들어보고자 한다.
3. Docker Compose로 인프라 구성
이 모든 걸 안정적으로 구동시키기 위해 Docker Compose를 사용해서 전체 인프라를 컨테이너화했다. 구조는 다음과 같다.
├── docker-compose.yml
├── backend # Spring Boot 서버
│ ├── Dockerfile
│ └── src, build, ...
├── mediasoup-server # Node.js 기반 SFU 서버 (별도 디렉토리 존재)
└── kafka
- backend: JWT 인증, 스터디룸 입장 처리, Kafka consumer, DB 연동 등 비즈니스 로직 담당
- mediasoup-server: 클라이언트 스트림을 받아 다른 사용자들에게 중계, AI 서버로 스트림 포워딩
- kafka + zookeeper: 비동기 메시지 브로커
Docker Compose 덕분에 로컬 환경에서도 전체 시스템을 한 줄로 띄울 수 있어서 개발이 수월했고,
이후 배포 시에도 docker swarm이나 k8s로 자연스럽게 확장 가능하다.
꿀팁
필자는 이런 스크립트로 서버 재가동을 자동화하는 습관이 있다.
$ sh rerun.sh
#!/bin/sh
echo "Stopping and removing containers, networks, volumes..."
docker compose down -v
echo "Starting containers in detached mode..."
docker compose up -d
4. 실제 흐름 요약
- 클라이언트가 Spring Boot 서버로 JWT 기반 인증 + 스터디룸 입장 요청
- Spring Boot 서버가 mediasoup 서버에 접속 정보 요청
- 생성된 접속 정보를 클라이언트에게 반환
- 클라이언트는 mediasoup에 접속하고, 스트림을 업로드
- mediasoup는 이 스트림을 다른 사용자들에게 중계, 동시에 AI 분석 서버로 전달
- 분석 서버는 집중도 분석 후, Kafka에 메시지 전송
- Spring Boot 서버는 Kafka를 구독해서 메시지를 받고, DB에 저장
- 사용자 요청 시 집중도 데이터를 API로 반환
5. 마치며: "설계는 전략이다"
이 프로젝트 초기 아키텍쳐 설계를 하고, 각 요구사항을 반영하는 과정을 통해 "아키텍처는 전략이다"라는 말을 다시 한 번 느꼈다.
기술 하나하나가 서로 잘 맞물려 돌아가도록 설계하고, 문제가 생겨도 쉽게 디버깅하고 확장할 수 있게 만드는 것.
그게 진짜 서버 개발자의 역할이라는 걸 느꼈다.
하나의 기술을 선택할 때 많은 고민과 설계를 하는 노력이, 러프한 설계 후 개발하며 하는 고생보다 낫다!
'Activities > Focussu 개발일지' 카테고리의 다른 글
[Focussu] Kafka & Redis 통합/단위 테스트 (0) | 2025.04.15 |
---|