ICE Candidate는 WebRTC 인프라의 요소로, 장치 간 P2P 연결을 설정하기 위한 잠재적 네트워크 주소(IP + 포트)를 나타냅니다. 각 후보는 미디어 데이터 전송에 사용할 수 있는 전송 경로를 설명합니다. ICE(Interactive Connectivity Establishment) 프로세스에서 장치는 후보 목록을 교환하고 테스트하여 최적의 경로를 선택합니다.Mozilla MDN, 2026에 따르면 ICE Candidate는 복잡한 네트워크 환경에서 연결을 보장하는 WebRTC 스택의 핵심 구성 요소입니다.
핵심 사항
ICE Candidate(Interactive Connectivity Establishment Candidate)는 WebRTC 프로토콜을 통한 P2P 연결 설정 프로세스의 기본 단위입니다. 두 피어 간 데이터 전송에 사용할 수 있는 IP 주소와 포트의 쌍을 나타냅니다. 각 후보는 전송 프로토콜(UDP, TCP), 연결 유형 및 우선순위에 대한 정보를 포함합니다.
ICE Candidate는 각 장치에서 개별적으로 형성됩니다. 장치는 사용 가능한 모든 네트워크 인터페이스를 수집하고 STUN 서버를 통해 외부 주소를 요청하며 TURN 서버에서 릴레이 주소를 추가합니다. 수집된 후보 목록은 SDP(Session Description Protocol) 형식의 시그널링 채널을 통해 원격 피어로 전송됩니다.
RFC 8445(IETF, 2018) 사양에 따르면 ICE는 nominated pairs 메커니즘을 사용합니다. 모든 후보를 수집한 후 STUN 요청을 통해 쌍별 테스트가 수행됩니다. 첫 번째로 검증에 통과한 쌍이 nominated(지정)되어 멀티미디어 전송에 사용됩니다. 나머지 쌍은 연결이 끊어질 경우를 대비해 예비로 유지됩니다.
WebRTC는 P2P 통신의 개방형 표준이지만 NAT(Network Address Translation) 및 방화벽으로 인해 장치 간 직접 연결이 불가능한 경우가 많습니다. ICE Candidate는 여러 대체 연결 경로를 제공하여 이 문제를 해결합니다. ICE(Interactive Connectivity Establishment) 프로토콜은 WebRTC의 필수 구성 요소이며 W3C WebRTC(2025) 사양에 설명되어 있습니다.
많은 모바일 앱 개발자는 Google WebRTC(Android용) 및 iOS용 네이티브 래퍼와 같은 WebRTC 라이브러리를 사용합니다. 각각에서 ICE 프로세스는 자동으로 관리되지만 후보 유형을 이해하면 개발자가 서버 인프라를 구성하고 연결 품질을 최적화할 수 있습니다.
ICE Candidate는 SDP 메시지 내에서 a=candidate 속성으로 전송됩니다. 각 행에는 foundation, component ID, 전송 프로토콜, 우선순위, IP 주소, 포트 및 후보 유형이 포함됩니다. 다음은 다양한 유형의 세 후보가 포함된 SDP 조각의 예입니다.
// ICE 후보가 포함된 SDP 샘플
a=candidate:1 1 UDP 2130706431 192.168.1.10 54321 typ host
a=candidate:2 1 UDP 1694498815 203.0.113.5 54322 typ srflx
a=candidate:3 1 TCP 1019212287 198.51.100.7 54323 typ relay raddr 203.0.113.5 rport 3478
priority 필드는 후보의 테스트 순서를 결정합니다. 우선순위가 높을수록 후보가 더 일찍 확인됩니다. Host 후보는 항상 최우선이며 relay는 최하위 우선순위입니다.
RFC 8445 사양은 4가지 유형의 ICE 후보를 정의하며 각각 원격 피어에 도달하는 특정 방식에 해당합니다. 후보 유형은 우선순위, 연결 설정 시간 및 서버 인프라 요구 사항에 영향을 미칩니다.
| 유형 | 우선순위 | 소스 | 서버 의존성 |
|---|---|---|---|
| host | 최고 | 로컬 네트워크 인터페이스 | 없음 |
| srflx | 높음 | STUN 반사 | STUN |
| prflx | 중간 | 피어 반사(ICE 프로세스 중) | 없음 |
| relay | 최저 | TURN 서버 | TURN |
Host 후보는 장치의 로컬 네트워크 인터페이스 IP 주소에서 형성됩니다. 장치가 피어와 동일한 로컬 네트워크에 있는 경우 host 후보는 최소 지연 시간으로 직접 연결을 제공합니다. 모바일 장치의 경우 host 후보는 WiFi 인터페이스, 셀룰러 LTE/5G 연결 및 필요한 경우 VPN 터널에 대해 생성됩니다.
Host 후보는 최고 우선순위(UDP의 경우 2130706431)를 가지며 먼저 테스트됩니다. 두 피어가 모두 NAT 뒤에 있는 경우 host 후보는 개인 주소(192.168.x.x, 10.x.x.x)가 되며 직접 연결이 불가능합니다. ICE는 srflx 및 relay 후보 테스트로 전환됩니다.
SRFLX(Server Reflexive) 후보는 STUN 서버에서 얻은 외부 IP 주소와 포트입니다. 장치가 STUN 요청을 보내면 서버는 NAT 이후의 공용 주소를 확인하고 반환합니다. 이 후보를 사용하면 NAT 장치가 Hairpinning을 지원하는 경우 서로 다른 NAT 뒤에 있는 피어 간에 직접 연결을 설정할 수 있습니다.
PRFLX(Peer Reflexive) 후보는 한 피어의 STUN 요청이 예상치 못한 주소에 도착할 때 동적으로 감지됩니다. 이 유형은 두 피어가 동시에 요청을 보내고 NAT가 임시 바인딩을 생성할 때 발생합니다. PRFLX 후보는 srflx보다 높은 우선순위를 가지지만 host보다는 낮습니다.
모바일 애플리케이션에서 srflx 후보는 WiFi와 셀룰러 네트워크 간 전환 시 특히 중요합니다. 장치가 네트워크를 변경하면 IP 주소가 변경되고 ICE는 후보를 다시 수집해야 합니다. 이 프로세스를 ICE restart라고 하며 새 SDP를 다시 보내야 합니다.
Relay 후보는 TURN 서버의 주소로, 트래픽이 한 피어에서 다른 피어로 중계됩니다. 이 유형은 직접 P2P 연결이 불가능할 때(대칭 NAT, 기업 방화벽) 대체 옵션으로 사용됩니다. 릴레이 채널은 지연 시간을 추가하고 서버 부하를 증가시키므로 최적 설정에서는 TURN 서버가 전체 세션의 10~15%에만 사용됩니다.
인기 있는 TURN 서버 구현: coturn(오픈 소스), Twilio Network Traversal, Metered TURN. TURN 공급자 선택은 모바일 애플리케이션의 미디어 연결 품질에 영향을 미칩니다. 서버는 사용자와 지리적으로 가까운 위치에 배치되어 추가 지연 시간을 최소화해야 합니다.
ICE 프로세스는 네트워크 토폴로지의 불확실성 속에서 신뢰할 수 있는 P2P 연결을 보장하는 다단계 프로토콜입니다. 알고리즘은 RFC 8445에 설명되어 있으며 후보 수집, 정렬, 테스트 및 지정의 네 가지 필수 단계를 포함합니다.
각 장치는 사용 가능한 모든 네트워크 주소를 수집합니다. WebRTC 엔진은 로컬 인터페이스(host)를 열거하고 STUN 서버(srflx)에 요청을 보내고 TURN 서버에 릴레이 주소를 요청합니다. 동시에 장치는 피어로부터 수신 STUN 요청을 받으면 prflx 후보를 감지할 수 있습니다.
모바일 개발에서 이 단계는 연결 설정 시간에 중요합니다. iOS 및 Android에서 후보 수집은 네트워크 속도, STUN/TURN 서버 가용성 및 활성 네트워크 인터페이스 수에 따라 200ms에서 2초까지 걸릴 수 있습니다.
시그널링 채널을 통해 원격 피어로부터 후보 목록을 받은 후 로컬 ICE 엔진은 가능한 모든 후보 쌍(로컬 + 원격)을 형성합니다. 각 쌍은 RFC 8445의 공식에 따라 두 후보의 우선순위와 방향(incoming/outgoing)을 고려한 우선순위를 받습니다.
쌍은 우선순위 내림차순으로 정렬됩니다. 최상의 쌍이 먼저 테스트됩니다. 이 알고리즘은 host-host 쌍이 host-srflx, host-relay 또는 relay-relay보다 먼저 확인되어 단순한 네트워크 구성에서 연결 지연을 최소화합니다.
ICE는 각 후보 쌍에 STUN-binding 요청을 보냅니다. STUN 응답을 받으면 쌍이 유효한 것으로 간주됩니다. 첫 번째 유효한 쌍이 nominated(지정)되어 기본으로 설정됩니다. WebRTC 엔진은 이 쌍을 통해 미디어 전송을 시작하고 나머지 쌍은 기본이 실패할 경우를 대비해 계속 확인됩니다.
테스트 프로세스는 후보가 많은 경우 몇 초가 걸릴 수 있습니다. WebRTC는 타이머를 사용합니다. host 쌍은 적극적인 타이머(20ms), relay는 더 보수적인 타이머(200ms)입니다. 모바일 앱 개발자는 ICE 서버 수를 제한하거나 iceTransportPolicy를 설정하여 연결 속도를 높일 수 있습니다.
ICE restart는 RTCPeerConnection 전체를 다시 생성하지 않고 ICE 프로세스를 다시 시작하는 것입니다. 네트워크 변경, 연결 끊김 또는 WiFi와 모바일 네트워크 간 전환 시 필요합니다. 다시 시작 시 모든 현재 후보가 재설정되고 새 ufrag 및 pwd 생성부터 프로세스가 새로 시작됩니다.
iOS 개발에서 ICE restart는 RTCPeerConnection의 restartIce() 메서드를 호출하여 수행됩니다. Android에서는 Google WebRTC의 PeerConnection 클래스에 유사한 메서드가 있습니다. ICE restart의 올바른 처리는 불안정한 네트워크 연결에서 작동하는 모바일 장치용 애플리케이션의 중요한 요구 사항입니다.
STUN(Session Traversal Utilities for NAT) 및 TURN(Traversal Using Relays around NAT)은 실제 인터넷 환경에서 ICE Candidate가 성공적인 연결을 보장하기 위한 필수 서버 구성 요소입니다. 올바른 구성은 모바일 애플리케이션의 통화 품질에 직접적인 영향을 미칩니다.
STUN 서버를 통해 장치는 NAT가 발신 연결에 할당한 공용 IP 주소와 포트를 확인할 수 있습니다. STUN 프로토콜은 RFC 8489에 정의되어 있으며 UDP 포트 3478에서 작동하고 TCP도 지원합니다. Google은 무료로 사용할 수 있는 공용 STUN 서버(stun.l.google.com:19302)를 제공합니다.
모바일 개발에서 STUN 요청은 50~200ms가 소요되는 가벼운 작업입니다. 그러나 일부 기업 및 모바일 네트워크는 UDP 트래픽을 차단하여 ICE가 STUN 통신에 TCP를 사용하거나 즉시 TURN으로 전환해야 합니다.
TURN 서버는 미디어 트래픽 중계기입니다. 직접 P2P 연결이 불가능할 때(대칭 NAT, 방화벽) 장치는 데이터를 TURN으로 보내고 TURN이 다른 피어로 전달합니다. TURN은 안정적이지만 비용이 많이 드는 메커니즘으로, 지연 시간(30~100ms)을 추가하고 모든 미디어 세션의 합계와 동일한 대역폭이 필요합니다.
WebRTC Stats Report(2025)에 따르면 모바일 네트워크의 WebRTC 세션 중 약 8~15%가 TURN을 필요로 합니다. TURN 트래픽 비용을 최적화하기 위해 개발자는 사전 연결 테스트를 사용하고 P2P가 실패한 경우에만 TURN 채널을 활성화합니다.
모바일 프로젝트의 ICE 인프라를 선택할 때는 지연 시간 최소화를 위한 서버의 지리적 위치, UDP 및 TCP 지원, TURN 트래픽 비용 및 SLA를 고려합니다. 인기 있는 솔루션: 자체 호스팅용 coturn, 클라우드용 Twilio, Agora, LiveKit.
모바일 개발자에게 ICE Candidate의 이해는 이론을 넘어 음성 및 화상 통화가 있는 애플리케이션을 만들 때 실용적인 필수 사항입니다. iOS 및 Android 플랫폼은 ICE를 자동화하는 네이티브 API를 제공하지만 개발자는 ICE 서버 구성 및 네트워크 변경 이벤트 처리를 담당합니다.
iOS에서 WebRTC는 WebRTC.framework 프레임워크 또는 CocoaPods를 통한 GoogleWebRTC 라이브러리를 통해 사용할 수 있습니다. ICE 서버는 RTCConfiguration 내의 RTCIceServer 배열을 통해 구성됩니다.
let config = RTCConfiguration()
let stunServer = RTCIceServer(urlStrings: ["stun:stun.l.google.com:19302"])
let turnServer = RTCIceServer(urlStrings: ["turn:turn.example.com:3478"],
username: "user",
credential: "pass")
config.iceServers = [stunServer, turnServer]
let pc = RTCPeerConnection(configuration: config)
RTCPeerConnection을 만들고 offer() 또는 answer()를 호출하면 엔진이 자동으로 ICE 후보를 수집합니다. iceGatheringStateChange 이벤트는 수집 상태 변경을 알리고 iceConnectionState는 연결 상태를 알립니다.
Android는 동일한 Google WebRTC 라이브러리를 사용합니다. ICE 서버는 PeerConnection.RTCConfiguration을 통해 설정됩니다. 개발자는 iceTransportsType을 통해 ICE 정책을 관리할 수 있습니다. 릴레이 모드는 TURN만 강제로 사용하여 안정성은 향상되지만 지연 시간이 증가합니다.
val iceServers = listOf(
PeerConnection.IceServer.builder("stun:stun.l.google.com:19302").createIceServer(),
PeerConnection.IceServer.builder("turn:turn.example.com:3478")
.setUsername("user")
.setPassword("pass")
.createIceServer()
)
val config = PeerConnection.RTCConfiguration(iceServers)
config.iceTransportsType = PeerConnection.IceTransportsType.ALL
config.bundlePolicy = PeerConnection.BundlePolicy.MAXBUNDLE
bundlePolicy 매개변수는 ICE 후보 수에 영향을 미칩니다. MAXBUNDLE 모드는 모든 미디어 스트림을 하나의 전송으로 통합하여 총 후보 수를 줄이고 연결 속도를 높입니다.
개발자가 처리해야 할 주요 ICE 이벤트: ICE 연결 상태, ICE 수집 상태 변경, 새 후보 감지입니다. ICE가 수집 및 테스트를 완료하면 상태가 connected 또는 completed로 전환됩니다.
모바일 네트워크에서는 WiFi와 셀룰러 간 전환이 자주 발생합니다. 네트워크 변경 시 ICE가 restart를 실행하지 않으면 미디어 스트림이 중단됩니다. 개발자는 NetworkManager(iOS) 또는 ConnectivityManager(Android) 모니터링을 구현하여 restartIce()를 자동으로 호출합니다.
모바일 애플리케이션에서 ICE의 성공적인 구현에는 다음이 포함됩니다: 신뢰할 수 있는 STUN/TURN 서버 선택, 네트워크 변경 시 ICE restart의 올바른 처리, 연결 상태 UI 표시를 위한 iceConnectionState 설정, RTCStatsReport를 통한 통계 모니터링.
자주 묻는 질문
ICE Candidate는 WebRTC 통화를 위한 “시험 주소”입니다. 친구에게 전화를 걸어야 하지만 어디에 있는지 모른다고 상상해보세요. 집(host), 공통 지인(STUN), 택배(TURN)를 통해 연락을 시도합니다. 각각의 방법이 ICE Candidate입니다.
RFC 8445 사양은 4가지 유형을 정의합니다: host(로컬 인터페이스), srflx(STUN을 통한 외부 주소), prflx(피어의 동적 후보), relay(TURN 서버의 주소). 각 유형에는 고유한 우선순위와 감지 메커니즘이 있습니다.
STUN은 P2P 연결을 위해 자신의 외부 IP 주소를 확인하는 데 도움이 되지만 데이터 전송에는参与하지 않습니다. TURN은 직접 P2P 연결이 불가능할 때 미디어 트래픽을 중계하는 릴레이입니다. TURN은 지연 시간을 추가하고 서버 대역폭을 소비합니다.
ICE restart는 네트워크 변경(WiFi에서 모바일 인터넷으로 전환), 연결 끊김 또는 세션 만료 시 필요합니다. 다시 시작 시 모든 현재 후보가 재설정되고 ICE는 새 ufrag와 pwd로 수집을 다시 시작합니다.
WebRTC에서는 RTCPeerConnection에서 getStats() 메서드를 사용합니다. candidateType 필드가 포함된 RTCStatsReport를 반환합니다. Android 및 iOS에서는 활성 ICE 후보, 해당 유형 및 선택된 쌍의 RTT에 대한 통계를 얻을 수 있습니다.
요약
턴키 방식의 모바일 애플리케이션을 개발해 드립니다
IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.