RFC(Request for Comments)
직역하면 비평을 기다리는 문서. IETF는 RFC로 발표된 일부 제안을 인터넷 표준으로 채택함. 모든 내용이 표준인 것은 아님.
IETF(Internet Engineering Task Force)
인터넷 표준 기구. 프로토콜을 구성하는 기술 표준을 담당함.
https://en.wikipedia.org/wiki/Internet_Engineering_Task_Force
인터넷 표준(Internet Standard, STD)
인터넷에 적용되는 기술이나 방법론을 표준으로 제정한 규격.
참고 : https://en.wikipedia.org/wiki/Internet_Standard
공식문서 : https://www.rfc-editor.org/standards
NAT (Network Address Translation)
여러 대의 컴퓨터가 IP 주소를 공유하도록 하는 기술 : https://developer.mozilla.org/ko/docs/Glossary/NAT
공인 IP 부족을 해결하는 기술 : https://en.wikipedia.org/wiki/Network_address_translation
but. 얘 때문에 P2P 연결이 까다로워짐.
P2P 네트워킹에서 두 컴퓨터가 가능한 한 직접적으로 서로 통신할 수 있는 방법을 찾기 위해 컴퓨터 네트워킹에 사용되는 기술

공식문서 기반 Gemini 설명
일단 개념부터 잡고 가자. ICE는 Interactive Connectivity Establishment의 약자야. 우리말로 하면 '상호 연결성 확립' 정도 되겠네.
쉽게 비유를 들어볼게.
네가 아파트 단지(사설망, Private Network)에 사는 친구(Peer)에게 전화를 걸고 싶다고 해보자.
ICE는 바로 이 모든 방법을 다 시도해서, 너와 친구가 통신할 수 있는 가장 빠르고 효율적인 경로를 찾아내는 프로토콜이야. 핵심은 '될 때까지 다 해본다'는 아주 적극적인 방식이라는 거지.
ICE는 크게 4단계로 동작해. RFC 8445 문서의 핵심 내용이기도 하지.
각 클라이언트(Peer)는 자신이 통신에 사용할 수 있는 모든 주소, 즉 후보(Candidate)들을 수집해. 위 비유에서 말한 방법들이 다 동원돼.
이렇게 수집한 후보 리스트를 만들어. 각 후보는 우선순위(priority)를 가지는데, 보통 Host > Server-Reflexive > Relayed 순으로 높아. 직접 연결하는 게 가장 좋으니까.
이제 각자 수집한 후보 리스트를 상대방에게 알려줘야 해. 이건 ICE 프로토콜 자체의 역할은 아니고, SIP나 WebSocket 같은 신호(Signaling) 프로토콜을 통해 이뤄져. 보통 SDP(Session Description Protocol)라는 형식에 담아서 교환하지.
나(Peer A): "안녕? 나랑 통화하려면 여기로 연락해봐. 내 후보들은 A, B, C야."
너(Peer B): "오케이! 내 후보들은 X, Y, Z야. 너도 참고해."
이제 양쪽 모두 자신과 상대방의 모든 후보 주소 목록을 갖게 됐어.
이 단계가 ICE의 핵심이야. 서로의 후보들을 조합해서 후보 쌍(Candidate Pair)을 만들어. 예를 들면 (A, X), (A, Y), (B, X), (B, Y) ... 이런 식으로 모든 조합을 만드는 거지.
그리고 우선순위가 높은 후보 쌍부터 차례대로 STUN 프로토콜을 이용해서 연결을 시도해봐.
나(A) -> 너(X) 에게: "STUN 요청 보낸다! 들리니?"
너(X) -> 나(A) 에게: "어, 잘 받았어! STUN 응답 보낸다!"
이 요청과 응답이 성공적으로 오가면, 해당 후보 쌍은 유효(Valid)하다고 판단하고 '유효 리스트(Valid List)'에 추가해. 이 과정에서 새로운 후보가 발견되기도 하는데, 이걸 Peer-Reflexive Candidate라고 해. 내가 보낸 요청을 받은 상대방이 "어? 네가 나한테 보낸 주소는 내가 아는 네 공인 주소랑 다른데? 실제로는 이 주소로 왔어" 라고 알려주는 거지. 이것도 아주 중요한 통신 경로가 될 수 있어.
연결성 검사를 통해 유효한 경로들을 여러 개 찾았을 수 있잖아? 그럼 이제 둘 중 하나의 제어 에이전트(Controlling Agent)가 최종적으로 사용할 경로를 하나 지명(Nominate) 해야 해.
나(Controlling): "여러 경로를 테스트해보니 (B, Y) 경로가 제일 좋은 것 같아. 앞으로 이걸로 통신하자!"
제어 에이전트는 STUN 요청에 USE-CANDIDATE 라는 특별한 플래그를 붙여서 보내. 이 요청을 받은 상대방(Controlled Agent)도 동의하면, 이 후보 쌍이 선택된 쌍(Selected Pair)이 되고, 앞으로 모든 데이터는 이 경로를 통해 오가게 돼.
ICE 프로세스가 성공적으로 끝나면, 다른 후보들은 정리하고 선택된 경로로만 통신을 유지하는 거야.
RFC 문서를 읽다 보면 '이건 왜 이렇게 복잡하게 만들었지?' 싶은 부분이 있을 거야. 몇 가지 중요한 것들을 짚어줄게.
priority = (2^24)*(type preference) + (2^8)*(local preference) + (2^0)*(256 - component ID) 을 사용해.Keepalive 메시지를 보낼까?Lite 구현과 Full 구현은 왜 나뉘어 있나?Lite 버전만 구현해서, 들어오는 연결성 검사에 응답만 잘 해주면 돼. 반면, 일반 사용자 PC나 스마트폰은 언제 어디서든 접속해야 하니 모든 기능을 갖춘 Full 버전을 구현해야 하는 거지. 이렇게 역할을 나눠서 구현의 부담을 줄여주는 거야.ice2 옵션은 무엇이고 왜 필요한가?ice2 옵션은 후보 교환 시 "나는 새로운 RFC 8445 규격을 따르는 에이전트야"라고 상대방에게 알려주는 신호야. 이 신호를 받은 구버전 에이전트는 호환되지 않는 기능을 사용하지 않게 되어 통신 오류를 막을 수 있어.192.168.1.10 이라는 IP를 쓰는 직원이 있을 수 있어. A사의 '철수'가 B사의 '영희'에게 연결을 시도하는데, 신호가 잘못 전달되어 같은 A사에 있는 '민수'의 후보 정보가 전달됐다고 생각해봐. 철수는 영희의 주소라고 생각하고 192.168.1.10으로 연결성 검사를 보냈는데, 그게 민수에게 도착할 수 있어. 이때, 후보 교환 시 주고받은 무작위 username 값이 다르면 민수의 ICE 클라이언트는 "어? 이거 내 거 아닌데?" 하고 요청을 거부해. 만약 이 장치가 없다면, 철수는 영희가 아닌 민수와 연결될 뻔한 거지!ICE는 네트워크 환경의 불확실성을 극복하기 위해 만들어진 아주 똑똑하고 실용적인 프로토콜이야. 처음에는 용어도 많고 절차도 복잡해 보이지만, 각 단계와 기능이 왜 필요한지 이해하고 나면 전체 그림이 보일 거야. 궁금한 거 있으면 언제든지 다시 물어보라고.
추가 참고 공식문서
https://www.rfc-editor.org/rfc/rfc7742.html