1. 문제
실시간 음성 통화 서비스는 다양한 네트워크 환경에서 사용자 간 직접 연결이 어려운 근본적인 문제에 직면합니다.
대부분의 사용자는 공유기(NAT) 뒤에 존재하며, 이로 인해 상대방과의 직접적인 IP 주소 및 포트 연결이 차단됩니다. 특히 기업 네트워크나 모바일 데이터 환경에서는 더욱 엄격한 방화벽 정책과 NAT 유형으로 인해 WebRTC 기반의 P2P(Peer-to-Peer) 연결 시도가 실패하는 경우가 빈번합니다. 이러한 연결 실패는 사용자 경험을 심각하게 저해하며, Voice-Link와 같은 실시간 커뮤니케이션 서비스의 핵심 가치를 위협합니다.
2. 왜 필요한가
Voice-Link는 사용자 간의 끊김 없는 실시간 음성 통화를 보장하기 위해 TURN/STUN 서버와 LiveKit 기반 SFU(Selective Forwarding Unit) 아키텍처가 필수적입니다.
NAT(Network Address Translation)는 사설망의 여러 기기가 하나의 공인 IP 주소를 공유하게 하면서 보안과 IP 주소 고갈 문제를 해결하지만, 동시에 외부에서 내부 기기로의 직접적인 연결을 어렵게 만듭니다. STUN(Session Traversal Utilities for NAT) 서버는 클라이언트의 공인 IP 주소와 포트를 알려주어 NAT 너머의 다른 피어와 직접 연결할 수 있도록 돕습니다. 하지만 대칭형 NAT와 같이 엄격한 환경에서는 STUN만으로는 연결이 불가능하며, 이때 TURN(Traversal Using Relays around NAT) 서버가 릴레이 역할을 수행하여 미디어 트래픽을 중계함으로써 통화 연결을 보장합니다. Voice-Link는 `livekit.url` 및 `livekit.api-url` 설정을 통해 LiveKit 서버에 연결하여 WebRTC 세션을 관리하며, 이 과정에서 LiveKit은 자체적으로 TURN/STUN 기능을 활용하거나 외부 TURN 서버를 연동하여 NAT traversal을 최적화합니다. 이는 Voice-Link가 어떠한 네트워크 환경에서도 안정적인 통화 연결을 제공하는 핵심 기반이 됩니다.
3. 기대효과
TURN/STUN 서버와 LiveKit의 도입으로 Voice-Link는 네트워크 제약으로 인한 통화 연결 실패율을 극적으로 감소시키고, 사용자에게 탁월한 통화 품질을 제공할 수 있습니다.
복잡한 네트워크 환경에서도 모든 사용자가 안정적으로 통화에 참여할 수 있게 되며, 이는 서비스의 핵심적인 신뢰성으로 이어집니다. 또한, LiveKit의 SFU 아키텍처는 다자간 통화 시 각 참여자에게 필요한 미디어 스트림만 선별적으로 전달하여 서버 및 클라이언트의 부하를 줄이고, 대역폭 효율성을 극대화합니다. `app.call-quality.*` 설정으로 관리되는 통화 품질 측정 및 진단 시스템은 RTT(Round Trip Time), Jitter, Packet Loss와 같은 핵심 지표를 실시간으로 모니터링하여 잠재적인 품질 저하를 사전에 감지하고 대응할 수 있도록 합니다. 이를 통해 Voice-Link는 단순히 연결을 넘어선 고품질의 통화 경험을 사용자에게 약속할 수 있습니다.
4. 구현 방향
Voice-Link는 LiveKit을 핵심 미디어 서버로 활용하며, Spring Boot 백엔드와 연동하여 통화 관리, 품질 측정, 이벤트 스트리밍 기능을 구현합니다.
LiveKit 인프라에 coturn과 같은 TURN 서버를 통합하여 NAT traversal 기능을 강화합니다. `infra/coturn/turnserver.conf`와 `docs/turn-stun-flow.md` 문서는 TURN 서버의 설정과 동작 흐름을 정의하여 안정적인 미디어 릴레이를 보장합니다. 백엔드에서는 `kr.co.voicelink.livekit.LiveKitWebhookService`를 통해 LiveKit으로부터 `room_finished`, `participant_left`, `participant_disconnected`, `participant_joined`와 같은 웹훅 이벤트를 수신하고 처리합니다. 이 이벤트들을 기반으로 `kr.co.voicelink.callquality.service.CallQualityService`는 Redis 리스트(`spring.data.redis.*` 설정 활용)에 실시간 통화 품질 스냅샷을 저장하고 관리합니다. 통화 중 RTT, Jitter, Packet Loss 등 품질 지표를 주기적으로 수집하여 Redis에 기록하며, 이를 통해 통화 종료 후 상세 진단 리포트를 생성하거나 실시간으로 이상 징후를 감지할 수 있습니다. 또한 `kr.co.voicelink.match.service.CallEventStreamingService`는 SSE(Server-Sent Events)를 활용하여 통화 종료/연장과 같은 이벤트를 클라이언트에게 실시간으로 전파합니다. 20초마다 Heartbeat 메시지를 보내어 연결을 유지하고, 클라이언트가 통화 상태 변화를 즉시 인지하고 UI를 업데이트할 수 있도록 합니다. 이러한 구조는 통화의 시작부터 종료, 그리고 그 안에서 발생하는 모든 품질 관련 이벤트를 유기적으로 관리합니다.
// kr.co.voicelink.livekit.LiveKitWebhookService.java (부분)
@Service
public class LiveKitWebhookService {
private final CallQualityService callQualityService;
private final CallEventStreamingService callEventStreamingService;
public LiveKitWebhookService(CallQualityService callQualityService, CallEventStreamingService callEventStreamingService) {
this.callQualityService = callQualityService;
this.callEventStreamingService = callEventStreamingService;
}
public void handleWebhook(LiveKitWebhookEvent event) {
switch (event.getEvent()) {
case "room_finished":
// 룸 종료 시 통화 품질 리포트 생성 및 이벤트 스트리밍
callQualityService.generateReport(event.getRoom().getName());
callEventStreamingService.sendCallEndEvent(event.getRoom().getName());
break;
case "participant_joined":
// 참가자 입장 시 로직
break;
case "participant_left":
// 참가자 퇴장 시 로직
break;
default:
// 기타 이벤트 처리
}
}
}
5. 비즈니스 가치
Voice-Link의 TURN/STUN 및 LiveKit 기반 실시간 통화 최적화 전략은 사용자 신뢰도와 서비스 경쟁력을 강화하는 핵심 비즈니스 가치를 제공합니다.
다양한 네트워크 환경에서 통화 연결 실패를 최소화함으로써 사용자 이탈을 방지하고, 서비스 만족도를 극대화합니다. 안정적인 연결은 고객 상담, 비즈니스 미팅, 원격 협업 등 Voice-Link가 제공하는 다양한 커뮤니케이션 시나리오에서 핵심적인 성공 요인이 됩니다. 또한, 통화 품질 측정 및 녹취/자막/음성 이벤트 처리 기능은 사용자 경험을 향상시킬 뿐만 아니라, 통화 내용 분석 및 서비스 개선을 위한 귀중한 데이터를 제공합니다. 이는 Voice-Link가 단순한 음성 통화를 넘어선 스마트한 커뮤니케이션 플랫폼으로 진화할 수 있는 기반을 마련하며, 결과적으로 시장에서의 독보적인 위치를 확보하는 데 기여합니다.
Voice-Link는 WebRTC, TURN/STUN, LiveKit SFU 아키텍처를 통해 네트워크 복잡성을 극복하고 안정적인 실시간 음성 통화를 제공합니다. Spring Boot 백엔드와 Redis, SSE를 활용하여 통화 관리, 품질 측정, 이벤트 스트리밍을 구현함으로써 서비스 신뢰도를 높이고 사용자 경험을 최적화합니다. 이러한 기술적 기반은 Voice-Link가 끊김 없는 고품질 커뮤니케이션 서비스를 제공하며 비즈니스 경쟁력을 강화하는 핵심 동력입니다.