개요 · 범위
@ppi/shared는 web(apps/web)과 socket(apps/socket)이 공유하는 상수·타입·유틸의 SSOT(single source of truth). 소켓 이벤트명·mediasoup/WebRTC 설정·세션 타입·로거·에러 클래스가 여기 모여 양쪽이 동일 정의를 쓴다.
왜 공유 패키지인가: 이벤트명 하나가 web emit과 socket on에서 어긋나면 조용히 동작 안 함. 문자열을 양쪽에 중복 선언하지 않고 SOCKET_EVENTS 한 곳에서 import해 drift를 원천 차단한다.
상수 utils/constants.ts
| export | 내용 |
MEDIASOUP_CONFIG | ROUTER_MEDIA_CODECS(opus/VP8/VP9/H264), 포트 40000–40099, 대역폭, 워커 로그(#2) |
WEBRTC_CONFIG | ICE/미디어 제약 등 WebRTC 공통 |
SESSION_CONFIG | 세션 타임아웃·기본값 |
SOCKET_EVENTS | 전 소켓 이벤트명(연결/룸/peer/SFU/legacy P2P/세션/알림…) |
REALTIME_MODEL_VERSIONS / DEFAULT_REALTIME_MODEL_VERSION | "v1.0"/"v1.5", 기본 v1.0(#1) |
API_ENDPOINTS, MONITOR_CONFIG | 엔드포인트·모니터 설정 |
SOCKET_EVENTS 분류
connection(connect/disconnect/error)
room(create/join/leave-room, room-created/closed)
peer(peer-joined/left/state-changed)
mediasoup SFU(create/connect-transport, produce, consume, resume/pause-consumer, close-*)
legacy P2P(sdp-offer/answer, ice-candidate) // V1 #11
session(session-start/stop, lesson-session-expired …)
alert / monitoring / avatar …
타입 types/
| 파일 | 주요 타입 |
mediasoup.ts | PeerRole, InterruptMode(off/early/on), TransportDirection, GuestState, VadSettings, InputAudioNoiseReduction(far/near), ManualReadyState, RoomListItem |
webrtc.ts | RTC*State, RTCIceServerConfig, MediaConstraints, TrackInfo, NetworkQuality, ConnectionStats |
session.ts | SessionRole(host/guest/monitor), SessionState, AlertType/Severity, SessionInfo, RoomConfig |
auto-response.ts | 자동 응답('응') 타입 |
서버의 MediasoupRoom.guestState(#5), 클라 GuestState 갱신(updateGuestState)이 모두 이 GuestState 타입을 공유 → cross-instance 직렬화 정합의 기준.
유틸 utils/
| export | 역할 |
createLogger(prefix) / logger | 구조화 로거. 서버=JSON Lines(Loki), 브라우저=human-readable(typeof window 분기) |
PPIError + MediasoupError/WebRTCError/SessionError | 코드(ERROR_CODES) 동반 에러 클래스. handleError로 표준화 |
parseUserIdFromRoomId/parseLessonIndexFromRoomId/createRoomId | roomId({userId}_{lessonIndex}) 파싱·생성 |
createRoomId/parse*가 roomId 규칙(#2/#15)의 단일 정의. roomId 포맷을 바꾸려면 여기만 고치면 양쪽 반영.
함정 · 주의
- 이벤트명은 반드시 SOCKET_EVENTS: 문자열 하드코딩 금지. web emit과 socket on이 다른 문자열이면 조용히 누락(타입 체크도 못 잡음).
- legacy P2P 이벤트는 prefix 별도: use-web-rtc(#11)는 role 접두사(`${role}-sdp-offer`)를 동적으로 쓰므로 SOCKET_EVENTS 상수와 별개 — 혼동 주의.
- GuestState 직렬화: 타입 변경 시 Redis 직렬화/cross-instance hydration(#5)·broadcast에 영향. 필드 추가는 양쪽 default 동기화.
- 로거 환경 분기: 같은 createLogger가 서버/브라우저에서 다른 포맷. 서버 JSON Lines 의존 파서(Loki) 깨지 않게.
- MEDIASOUP_CONFIG 단일: 코덱/포트/대역폭이 서버에서만 쓰이지만 shared에 둔다. 변경 시 #2 SFU 서버 영향.
- 패키지 빌드: shared 변경 후 web/socket 양쪽 재빌드 필요(Turborepo). 타입만 바꿔도 소비처 재컴파일.
파일 · 라인 레퍼런스
| 파일 | 역할 |
| utils/constants.ts | MEDIASOUP/WEBRTC/SESSION_CONFIG, SOCKET_EVENTS, 모델 버전, API_ENDPOINTS |
| types/{mediasoup,webrtc,session,auto-response}.ts | 공유 타입 |
| utils/{logger,error,room}.ts | 로거·에러·roomId 유틸 |
| index.ts | barrel export(@ppi/shared) |