[동아출판] AI 디지털교과서 뷰어 서비스 개발
1. SSE 기반 실시간성 동기화 기능 구현 (수업집중 모드 / 학생학습모드)
[SSE 기본 구조 설명도]

문제 원인
- 한 반에 최소 10명 이상이 동시에 접속을 하고 실시간성 기능에 대한 예상치 못한 오류 문제 제기
- 개발 시점에서 빠르게 개발가능한 부분과 효율성 문제로 웹소켓과 SSE를 비교해서 적용하게 되었습니다.
해결과정
- 프론트엔드 SSE 구독 로직 구현
- Vue기반의 Viewer 앱에서
EventSource 객체를 사용해 SSE 스트림을 구독했습니다.
- 연결 시 사용자 인증 토큰과 클래스 ID를 전달하여 서버가 올바른 emitter에 등록할 수 있도록 했습니다.
- 메시지 수신, 에러 발생 시 재연결 로직, 연결 성립 이벤트를 정의하여 처리했습니다.
- 집중 모드 진입/해제, 페이지 변경 등 이벤트 타입에 따라 상태관리(store)를 업데이트하고 UI를 즉시 반영하도록 했습니다.
- 교사 측 트리거 처리
- 교사용 Viewer에서는 집중 모드 버튼과 페이지 이동 버튼에 이벤트 핸들러를 추가해 Viewer API로 메시지를 전송하게 했습니다.
- Viewer API는 이를 Redis에 발행(Pub)하도록 구현되어 있어 프론트엔드에서는 API 호출만 담당했습니다.
- UI/UX 개선
- 실시간 업데이트가 이루어질 때 학생 화면에 안내 메시지와 함께 부드러운 전환 애니메이션을 추가해 혼란을 줄였습니다.
- SSE 연결 상태를 표시하는 배지를 추가해 네트워크 문제나 서버 장애 시 사용자가 상태를 파악할 수 있도록 했습니다.
- 테스트와 최적화
- 로컬 환경에서 여러 브라우저 탭을 열어 학생 1, 학생 2, 학생 3 역할을 시뮬레이션하여 동기화 여부를 확인했습니다.
- 네트워크 간섭 및 서버 재시작 상황을 테스트해 재연결 로직이 정상 동작하도록 수정했습니다.
- 불필요한 리렌더링을 방지하기 위해 Vue의
watch를 활용해 상태 변경 시 필요한 컴포넌트만 업데이트했습니다.
결과
- 실시간 동기화: 교사 화면에서 집중 모드를 켜거나 페이지를 이동하면 학생 클라이언트에서 평균 100ms 내외의 지연으로 즉시 화면이 동기화되었습니다.
- 시스템 확장성 향상: Redis Pub/Sub를 사용함으로써 다수의 SSE API 인스턴스가 확장되더라도 메시지 브로커를 통해 일관된 이벤트 전파가 가능해졌습니다.
- 사용자 만족도 증대: 실시간 동기화를 통해 강의 흐름이 끊기지 않아 학생들의 참여도와 집중도가 향상되었으며, 교사도 동시에 여러 학생을 제어하는 부담이 줄었습니다.