Candidate State
Candidate State
프로젝트를 실제로 구현하다 보면 Candidate의 상태 중 New
와 Completed
만 보게 되는데 찾아보니 더 다양한 상태가 있었다.
state | desc |
---|---|
New (새로운 상태) |
|
Checking (확인 중 상태) |
|
Succeeded (성공 상태) |
|
Failed (실패 상태) |
|
Frozen (동결 상태) |
• 다른 Candidate의 확인이 진행 중일 때, 대기 상태에 있는 Candidate의 상태. • 네트워크 리소스를 효율적으로 사용하기 위해 일시적으로 확인을 미루는 상태. |
Waiting (대기 상태) |
• Frozen 상태에서 전환된 후, 곧 확인될 예정인 Candidate의 상태. • 우선순위에 따라 Checking 상태로 전환되기를 기다린다. |
In Progress (진행 중 상태) |
• 로컬에서 생성된 Candidate가 원격 피어로 전송 중인 상태. |
Completed (완료 상태) |
• 모든 Candidate의 확인이 완료된 상태. • 이 상태에서는 더 이상 새로운 Candidate를 확인하지 않는다. |
정보 수집 과정
PeerConnection을 구현하기 위해서는 순서가 중요하다. 먼저, RTCPeerConnection 객체를 생성한 직후 addTrack을 호출하여 해당 미디어에 대한 정보를 수집한다.
이 과정에서 RTCPeerConnection은 사용 가능한 네트워크 경로와 프로토콜을 파악하게 된다.
그 다음, createOffer 또는 createAnswer 메서드를 호출하여 SDP(Session Description Protocol)를 생성한다. SDP는 미디어 스트림의 속성과 형식을 설명하는 프로토콜이다.
• 컴포넌트가 리렌더링되더라도 useRef의 값은 보존된다.
• useRef의 값이 변경되어도 컴포넌트가 리렌더링되지 않는다.
• 비동기 콜백 내에서도 항상 최신의 RTCPeerConnection 인스턴스에 접근할 수 있다.
• 컴포넌트가 언마운트될 때 peer.current를 통해 RTCPeerConnection을 쉽게 정리할 수 있다.
const peer = useRef(null);
const { getMedia } = useGetMedia(); // get peer stream hook
const stream = await getMedia();
peer.current = new RTCPeerConnection(configuration);
stream.getTracks().forEach((track) => {
if (peer.current) peer.current.addTrack(track, stream);
});
트랙이 추가된 이후 ICE후보 생성이 시작된다. 이 과정에서 onicecandidate
이벤트가 발생하며, 각 ICE 후보가 생성될 때마다 이 이벤트가 트리거된다.
addTrack
을 호출하지 않을경우, peer.current는 null값을 가지게 된다.
peer.current.onicecandidate = (e) => {
if (e.candidate) {
console.log("setupPeerListeners - onicecandidate : ", e.candidate);
socketClient.onEmit("candidate", { candidate: e.candidate });
}
};
다음은 생성된 ICE Candidate에 대해 분석해 본다.
"sdpMid": "3"
• 이 후보와 관련된 미디어 스트림의 식별자.
• “3”은 SDP(Session Description Protocol)에서 이 후보가 네 번째 미디어 섹션에 해당함을 나타낸다.
"sdpMLineIndex":
• SDP의 미디어 라인 인덱. 여기서도 3은 네 번째 미디어 섹션을 가리킨다.
"usernameFragment":
• “h8Lg”은 ICE 프로세스에서 사용되는 사용자 이름 조각.
• 이는 “ufrag” 값과 일치하며, 연결의 특정 세션을 식별하는 데 사용된다
다음으로, 원격 피어의 미디어 스트림(비디오/오디오)을 받아 처리하는 ontrack 핸들러를 설정하여 원격 피어로부터 미디어 스트림을 받을 준비를 한다.
setRemote 함수를 통해 받은 스트림을 애플리케이션의 상태에 저장하여, UI에서 표시할 수 있다.
peer.current.ontrack = (ev) => {
setRemote((prev) => ({ ...prev, stream: ev.streams[0] }));
};