ํ๋ฐํธ์๋ RTCPeerConnection ํ ๊ด๋ฆฌ์๋ฅผ ๊ตฌํํ์ฌ WebRTC ์ ํ๋ฆฌ์ผ์ด์ ์ ์ง์ฐ ์๊ฐ๊ณผ ๋ฆฌ์์ค ์ฌ์ฉ๋์ ๋ํญ ์ค์ด๋ ๋ฐฉ๋ฒ์ ์์๋ณด์ธ์. ์์ง๋์ด๋ฅผ ์ํ ํฌ๊ด์ ์ธ ๊ฐ์ด๋์ ๋๋ค.
ํ๋ฐํธ์๋ WebRTC ์ฐ๊ฒฐ ํ ๊ด๋ฆฌ์: ํผ์ด ์ฐ๊ฒฐ ์ต์ ํ ์ฌ์ธต ๋ถ์
ํ๋ ์น ๊ฐ๋ฐ์ ์ธ๊ณ์์ ์ค์๊ฐ ํต์ ์ ๋ ์ด์ ํ์ ๊ธฐ๋ฅ์ด ์๋๋ผ ์ฌ์ฉ์ ์ฐธ์ฌ์ ์ด์์ ๋๋ค. ๊ธ๋ก๋ฒ ํ์ ํ์ ํ๋ซํผ๊ณผ ๋ํํ ๋ผ์ด๋ธ ์คํธ๋ฆฌ๋ฐ์์๋ถํฐ ํ์ ๋๊ตฌ ๋ฐ ์จ๋ผ์ธ ๊ฒ์์ ์ด๋ฅด๊ธฐ๊น์ง ์ฆ๊ฐ์ ์ด๊ณ ๋ฎ์ ์ง์ฐ ์๊ฐ์ ์ํธ ์์ฉ์ ๋ํ ์์๊ฐ ๊ธ์ฆํ๊ณ ์์ต๋๋ค. ์ด๋ฌํ ํ๋ช ์ ์ค์ฌ์๋ ๋ธ๋ผ์ฐ์ ๋ด์์ ์ง์ ํผ์ด ํฌ ํผ์ด ํต์ ์ ๊ฐ๋ฅํ๊ฒ ํ๋ ๊ฐ๋ ฅํ ํ๋ ์์ํฌ์ธ WebRTC(์น ์ค์๊ฐ ํต์ )๊ฐ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ด ๊ธฐ๋ฅ์ ํจ์จ์ ์ผ๋ก ํ์ฉํ๋ ๋ฐ์๋ ํนํ ์ฑ๋ฅ ๋ฐ ๋ฆฌ์์ค ๊ด๋ฆฌ์ ๊ด๋ จํ์ฌ ๊ณ ์ ํ ๊ณผ์ ๊ฐ ๋ฐ๋ฆ ๋๋ค. ๊ฐ์ฅ ์ค์ํ ๋ณ๋ชฉ ํ์ ์ค ํ๋๋ ๋ชจ๋ WebRTC ์ธ์ ์ ๊ธฐ๋ณธ ๊ตฌ์ฑ ์์์ธ RTCPeerConnection ๊ฐ์ฒด์ ์์ฑ ๋ฐ ์ค์ ์ ๋๋ค.
์๋ก์ด ํผ์ด ํฌ ํผ์ด ๋งํฌ๊ฐ ํ์ํ ๋๋ง๋ค ์๋ก์ด RTCPeerConnection ๊ฐ์ฒด๋ฅผ ์ธ์คํด์คํํ๊ณ , ๊ตฌ์ฑํ๊ณ , ํ์ํด์ผ ํฉ๋๋ค. SDP(Session Description Protocol) ๊ตํ ๋ฐ ICE(Interactive Connectivity Establishment) ํ๋ณด ์์ง์ ํฌํจํ๋ ์ด ํ๋ก์ธ์ค๋ ๋์ ๋๋ ์ง์ฐ ์๊ฐ์ ๋ฐ์์ํค๊ณ ์๋นํ CPU ๋ฐ ๋ฉ๋ชจ๋ฆฌ ๋ฆฌ์์ค๋ฅผ ์๋นํฉ๋๋ค. ์์ฃผ ๋๋ ์๋ง์ ์ฐ๊ฒฐ์ด ํ์ํ ์ ํ๋ฆฌ์ผ์ด์ (์: ์ฌ์ฉ์๊ฐ ๋น ๋ฅด๊ฒ ์๊ทธ๋ฃน ๋ฐฉ์ ์ฐธ์ฌํ๊ณ ๋๊ฐ๋ ๊ฒฝ์ฐ, ๋์ ๋ฉ์ ๋คํธ์ํฌ ๋๋ ๋ฉํ๋ฒ์ค ํ๊ฒฝ)์ ๊ฒฝ์ฐ ์ด๋ฌํ ์ค๋ฒํค๋๋ ๋๋ฆฐ ์ฌ์ฉ์ ๊ฒฝํ, ๋๋ฆฐ ์ฐ๊ฒฐ ์๊ฐ ๋ฐ ํ์ฅ์ฑ ์ ๋ชฝ์ผ๋ก ์ด์ด์ง ์ ์์ต๋๋ค. ์ฌ๊ธฐ์ ์ ๋ต์ ์ธ ์ํคํ ์ฒ ํจํด์ธ ํ๋ฐํธ์๋ WebRTC ์ฐ๊ฒฐ ํ ๊ด๋ฆฌ์๊ฐ ๋ฑ์ฅํฉ๋๋ค.
์ด ํฌ๊ด์ ์ธ ๊ฐ์ด๋์์๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ์ ์ ํต์ ์ผ๋ก ์ฌ์ฉ๋๋ ์ค๊ณ ํจํด์ธ ์ฐ๊ฒฐ ํ ๊ด๋ฆฌ์์ ๊ฐ๋ ์ ํ๊ตฌํ๊ณ , ์ด๋ฅผ ํ๋ฐํธ์๋ WebRTC์ ๊ณ ์ ํ ์ธ๊ณ์ ๋ง๊ฒ ์กฐ์ ํ ๊ฒ์ ๋๋ค. ๋ฌธ์ ๋ฅผ ๋ถ์ํ๊ณ , ๊ฒฌ๊ณ ํ ์๋ฃจ์ ์ ์ค๊ณํ๊ณ , ์ค์ฉ์ ์ธ ๊ตฌํ ํต์ฐฐ๋ ฅ์ ์ ๊ณตํ๋ฉฐ, ๊ธ๋ก๋ฒ ์ฒญ์ค์ ์ํ ๊ณ ์ฑ๋ฅ, ํ์ฅ์ฑ ๋ฐ ๋ฐ์์ฑ์ด ๋ฐ์ด๋ ์ค์๊ฐ ์ ํ๋ฆฌ์ผ์ด์ ๊ตฌ์ถ์ ์ํ ๊ณ ๊ธ ๊ณ ๋ ค ์ฌํญ์ ๋ํด ๋ ผ์ํ ๊ฒ์ ๋๋ค.
ํต์ฌ ๋ฌธ์ ์ดํด: RTCPeerConnection์ ๊ฐ๋น์ผ ์๋ช ์ฃผ๊ธฐ
์๋ฃจ์ ์ ๊ตฌ์ถํ๊ธฐ ์ ์ ๋ฌธ์ ๋ฅผ ์์ ํ ํ์ ํด์ผ ํฉ๋๋ค. RTCPeerConnection์ ๊ฐ๋ฒผ์ด ๊ฐ์ฒด๊ฐ ์๋๋๋ค. ์๋ช ์ฃผ๊ธฐ๋ ๋ฏธ๋์ด๊ฐ ํผ์ด ๊ฐ์ ํ๋ฅด๊ธฐ ์ ์ ์๋ฃ๋์ด์ผ ํ๋ ์ฌ๋ฌ ๋ณต์กํ๊ณ ๋น๋๊ธฐ์ ์ด๋ฉฐ ๋ฆฌ์์ค ์ง์ฝ์ ์ธ ๋จ๊ณ๋ฅผ ํฌํจํฉ๋๋ค.
์ผ๋ฐ์ ์ธ ์ฐ๊ฒฐ ์ฌ์
๋จ์ผ ํผ์ด ์ฐ๊ฒฐ์ ์ค์ ํ๋ ๊ฒ์ ์ผ๋ฐ์ ์ผ๋ก ๋ค์ ๋จ๊ณ๋ฅผ ๋ฐ๋ฆ ๋๋ค:
- ์ธ์คํด์คํ: new RTCPeerConnection(configuration)์ ์ฌ์ฉํ์ฌ ์ ๊ฐ์ฒด๊ฐ ์์ฑ๋ฉ๋๋ค. ๊ตฌ์ฑ์๋ NAT ์ํ๋ฅผ ์ํด ํ์ํ STUN/TURN ์๋ฒ(iceServers)์ ๊ฐ์ ํ์ ์ธ๋ถ ์ ๋ณด๊ฐ ํฌํจ๋ฉ๋๋ค.
- ํธ๋ ์ถ๊ฐ: addTrack()์ ์ฌ์ฉํ์ฌ ๋ฏธ๋์ด ์คํธ๋ฆผ(์ค๋์ค, ๋น๋์ค)์ด ์ฐ๊ฒฐ์ ์ถ๊ฐ๋ฉ๋๋ค. ์ด๋ก์จ ์ฐ๊ฒฐ์ด ๋ฏธ๋์ด๋ฅผ ๋ณด๋ผ ์ค๋น๊ฐ ๋ฉ๋๋ค.
- ์คํผ ์์ฑ: ํ ํผ์ด(ํธ์ถ์)๊ฐ createOffer()๋ฅผ ์ฌ์ฉํ์ฌ SDP ์คํผ๋ฅผ ์์ฑํฉ๋๋ค. ์ด ์คํผ๋ ํธ์ถ์์ ๊ด์ ์์ ๋ฏธ๋์ด ๊ธฐ๋ฅ ๋ฐ ์ธ์ ๋งค๊ฐ๋ณ์๋ฅผ ์ค๋ช ํฉ๋๋ค.
- ๋ก์ปฌ ์ค๋ช ์ค์ : ํธ์ถ์๋ setLocalDescription()์ ์ฌ์ฉํ์ฌ ์ด ์คํผ๋ฅผ ๋ก์ปฌ ์ค๋ช ์ผ๋ก ์ค์ ํฉ๋๋ค. ์ด ์์ ์ ICE ์์ง ํ๋ก์ธ์ค๋ฅผ ํธ๋ฆฌ๊ฑฐํฉ๋๋ค.
- ์๊ทธ๋๋ง: ์คํผ๋ ๋ณ๋์ ์๊ทธ๋๋ง ์ฑ๋(์: WebSockets)์ ํตํด ๋ค๋ฅธ ํผ์ด(ํผํธ์ถ์)์๊ฒ ์ ์ก๋ฉ๋๋ค. ์ด๊ฒ์ ๊ตฌ์ถํด์ผ ํ๋ ๋์ญ ์ธ ํต์ ๊ณ์ธต์ ๋๋ค.
- ์๊ฒฉ ์ค๋ช ์ค์ : ํผํธ์ถ์๋ ์คํผ๋ฅผ ์์ ํ๊ณ setRemoteDescription()์ ์ฌ์ฉํ์ฌ ์ด๋ฅผ ์๊ฒฉ ์ค๋ช ์ผ๋ก ์ค์ ํฉ๋๋ค.
- ์๋ต ์์ฑ: ํผํธ์ถ์๋ createAnswer()๋ฅผ ์ฌ์ฉํ์ฌ SDP ์๋ต์ ์์ฑํ๊ณ , ์คํผ์ ๋ํ ์๋ต์ผ๋ก ์์ ์ ๊ธฐ๋ฅ์ ์์ธํ ์ค๋ช ํฉ๋๋ค.
- ๋ก์ปฌ ์ค๋ช ์ค์ (ํผํธ์ถ์): ํผํธ์ถ์๋ ์ด ์๋ต์ ๋ก์ปฌ ์ค๋ช ์ผ๋ก ์ค์ ํ์ฌ ์์ฒด ICE ์์ง ํ๋ก์ธ์ค๋ฅผ ํธ๋ฆฌ๊ฑฐํฉ๋๋ค.
- ์๊ทธ๋๋ง(ํ์ ): ์๋ต์ ์๊ทธ๋๋ง ์ฑ๋์ ํตํด ํธ์ถ์์๊ฒ ๋ค์ ์ ์ก๋ฉ๋๋ค.
- ์๊ฒฉ ์ค๋ช ์ค์ (ํธ์ถ์): ์๋ ํธ์ถ์๋ ์๋ต์ ์์ ํ๊ณ ์ด๋ฅผ ์๊ฒฉ ์ค๋ช ์ผ๋ก ์ค์ ํฉ๋๋ค.
- ICE ํ๋ณด ๊ตํ: ์ด ํ๋ก์ธ์ค ์ ๋ฐ์ ๊ฑธ์ณ ์์ชฝ ํผ์ด๋ ICE ํ๋ณด(์ ์ฌ์ ๋คํธ์ํฌ ๊ฒฝ๋ก)๋ฅผ ์์งํ๊ณ ์๊ทธ๋๋ง ์ฑ๋์ ํตํด ๊ตํํฉ๋๋ค. ์ด๋ค์ ์๋ํ๋ ๊ฒฝ๋ก๋ฅผ ์ฐพ๊ธฐ ์ํด ์ด๋ฌํ ๊ฒฝ๋ก๋ฅผ ํ ์คํธํฉ๋๋ค.
- ์ฐ๊ฒฐ ์ค์ : ์ ์ ํ ํ๋ณด ์์ด ๋ฐ๊ฒฌ๋๊ณ DTLS ํธ๋์ ฐ์ดํฌ๊ฐ ์๋ฃ๋๋ฉด ์ฐ๊ฒฐ ์ํ๊ฐ 'connected'๋ก ๋ณ๊ฒฝ๋๊ณ ๋ฏธ๋์ด๊ฐ ํ๋ฅด๊ธฐ ์์ํ ์ ์์ต๋๋ค.
๋ ธ์ถ๋ ์ฑ๋ฅ ๋ณ๋ชฉ ํ์
์ด ์ฌ์ ์ ๋ถ์ํ๋ฉด ๋ช ๊ฐ์ง ์ค์ํ ์ฑ๋ฅ ๋ฌธ์ ์ ์ด ๋๋ฌ๋ฉ๋๋ค:
- ๋คํธ์ํฌ ์ง์ฐ ์๊ฐ: ์ ์ฒด ์คํผ/์๋ต ๊ตํ ๋ฐ ICE ํ๋ณด ํ์์ ์๊ทธ๋๋ง ์๋ฒ๋ฅผ ํตํ ์ฌ๋ฌ ๋ฒ์ ์๋ณต์ ํ์๋ก ํฉ๋๋ค. ์ด ํ์ ์๊ฐ์ ๋คํธ์ํฌ ์กฐ๊ฑด ๋ฐ ์๋ฒ ์์น์ ๋ฐ๋ผ 500ms์์ ์์ด๊น์ง ์ฝ๊ฒ ๊ฑธ๋ฆด ์ ์์ต๋๋ค. ์ฌ์ฉ์์๊ฒ๋ ์ด๋ ํตํ๊ฐ ์์๋๊ฑฐ๋ ๋น๋์ค๊ฐ ๋ํ๋๊ธฐ ์ ๊น์ง์ ๋์ ๋๋ ์ง์ฐ์ธ ๋ฐ๋ ์์ด(dead air)์ ๋๋ค.
- CPU ๋ฐ ๋ฉ๋ชจ๋ฆฌ ์ค๋ฒํค๋: ์ฐ๊ฒฐ ๊ฐ์ฒด๋ฅผ ์ธ์คํด์คํํ๊ณ , SDP๋ฅผ ์ฒ๋ฆฌํ๊ณ , ICE ํ๋ณด๋ฅผ ์์ง(๋คํธ์ํฌ ์ธํฐํ์ด์ค ๋ฐ STUN/TURN ์๋ฒ ์ง์๋ฅผ ํฌํจํ ์ ์์)ํ๊ณ , DTLS ํธ๋์ ฐ์ดํฌ๋ฅผ ์ํํ๋ ๊ฒ์ ๋ชจ๋ ๊ณ์ฐ ์ง์ฝ์ ์ ๋๋ค. ๋ง์ ์ฐ๊ฒฐ์ ๋ํด ์ด๋ฅผ ๋ฐ๋ณต์ ์ผ๋ก ์ํํ๋ฉด CPU ์คํ์ดํฌ๊ฐ ๋ฐ์ํ๊ณ , ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ด ์ฆ๊ฐํ๋ฉฐ, ๋ชจ๋ฐ์ผ ์ฅ์น์ ๋ฐฐํฐ๋ฆฌ๋ฅผ ์๋ชจํ ์ ์์ต๋๋ค.
- ํ์ฅ์ฑ ๋ฌธ์ : ๋์ ์ฐ๊ฒฐ์ด ํ์ํ ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ด ์ค์ ๋น์ฉ์ ๋์ ํจ๊ณผ๋ ์น๋ช ์ ์ ๋๋ค. ์๋ก์ด ์ฐธ๊ฐ์์ ์ง์ ์ด ๋ธ๋ผ์ฐ์ ๊ฐ ๋ค๋ฅธ ๋ชจ๋ ์ฐธ๊ฐ์์ ์์ฐจ์ ์ผ๋ก ์ฐ๊ฒฐ์ ์ค์ ํด์ผ ํ๊ธฐ ๋๋ฌธ์ ์ง์ฐ๋๋ ๋ค์๊ฐ ๋น๋์ค ํตํ๋ฅผ ์์ํด ๋ณด์ญ์์ค. ๋๋ ์๋ก์ด ๊ทธ๋ฃน์ ์ฌ๋๋ค์๊ฒ ์ด๋ํ๋ฉด ์ฐ๊ฒฐ ์ค์ ์ ํญํ์ด ํธ๋ฆฌ๊ฑฐ๋๋ ์์ VR ๊ณต๊ฐ์ ์์ํด ๋ณด์ญ์์ค. ์ฌ์ฉ์ ๊ฒฝํ์ ์ํํจ์์ ๋ถ์์ฐ์ค๋ฌ์์ผ๋ก ๋น ๋ฅด๊ฒ ์ ํ๋ฉ๋๋ค.
ํด๊ฒฐ์ฑ : ํ๋ฐํธ์๋ ์ฐ๊ฒฐ ํ ๊ด๋ฆฌ์
์ฐ๊ฒฐ ํ์ ์ค๋น๋ ๊ฐ์ฒด ์ธ์คํด์ค(์ด ๊ฒฝ์ฐ RTCPeerConnection ๊ฐ์ฒด)์ ์บ์๋ฅผ ์ ์ง ๊ด๋ฆฌํ๋ ๊ณ ์ ์ ์ธ ์ํํธ์จ์ด ์ค๊ณ ํจํด์ ๋๋ค. ์๋ก์ด ์ฐ๊ฒฐ์ด ํ์ํ ๋๋ง๋ค ์ฒ์๋ถํฐ ์ ์ฐ๊ฒฐ์ ๋ง๋๋ ๋์ , ์ ํ๋ฆฌ์ผ์ด์ ์ ํ์์ ์ฐ๊ฒฐ์ ์์ฒญํฉ๋๋ค. ์ ํด ์ํ์ ๋ฏธ๋ฆฌ ์ด๊ธฐํ๋ ์ฐ๊ฒฐ์ด ์ฌ์ฉ ๊ฐ๋ฅํ๋ฉด ๊ฐ์ฅ ์๊ฐ์ด ๋ง์ด ๊ฑธ๋ฆฌ๋ ์ค์ ๋จ๊ณ๋ฅผ ์ฐํํ์ฌ ๊ฑฐ์ ์ฆ์ ๋ฐํ๋ฉ๋๋ค.
ํ๋ฐํธ์๋์์ ํ ๊ด๋ฆฌ์๋ฅผ ๊ตฌํํจ์ผ๋ก์จ ์ฐ๋ฆฌ๋ ์ฐ๊ฒฐ ์๋ช ์ฃผ๊ธฐ๋ฅผ ๋ณํ์ํต๋๋ค. ๊ฐ๋น์ผ ์ด๊ธฐํ ๋จ๊ณ๋ ๋ฐฑ๊ทธ๋ผ์ด๋์์ ์ฌ์ ์ ์ํ๋์ด ์ฌ์ฉ์์ ๊ด์ ์์ ์๋ก์ด ํผ์ด์ ๋ํ ์ค์ ์ฐ๊ฒฐ ์ค์ ์ด ๋ฒ๊ฐ์ฒ๋ผ ๋นจ๋ผ์ง๋๋ค.
์ฐ๊ฒฐ ํ์ ํต์ฌ ์ด์
- ์ง์ฐ ์๊ฐ์ ๋ํญ ๊ฐ์: ์ฐ๊ฒฐ์ ๋ฏธ๋ฆฌ ์์ด(์ธ์คํด์คํํ๊ณ ๋๋ก๋ ICE ์์ง๊น์ง ์์)ํจ์ผ๋ก์จ ์๋ก์ด ํผ์ด์ ๋ํ ์ฐ๊ฒฐ ์๊ฐ์ด ๋จ์ถ๋ฉ๋๋ค. ์ฃผ์ ์ง์ฐ ์๊ฐ์ ์ ์ฒด ํ์์์ *์๋ก์ด* ํผ์ด์์ ์ต์ข SDP ๊ตํ ๋ฐ DTLS ํธ๋์ ฐ์ดํฌ๋ก๋ง ์ด๋ํ๋ฉฐ, ์ด๋ ํจ์ฌ ๋น ๋ฆ ๋๋ค.
- ๋ ๋ฎ๊ณ ๋ถ๋๋ฌ์ด ๋ฆฌ์์ค ์๋น: ํ ๊ด๋ฆฌ์๋ ์ฐ๊ฒฐ ์์ฑ ์๋๋ฅผ ์ ์ดํ์ฌ CPU ์คํ์ดํฌ๋ฅผ ์ํํ ์ ์์ต๋๋ค. ๊ฐ์ฒด ์ฌ์ฌ์ฉ์ ๋ํ ๋น ๋ฅธ ํ ๋น ๋ฐ ๊ฐ๋น์ง ์์ง์ผ๋ก ์ธํ ๋ฉ๋ชจ๋ฆฌ ๋ณ๋์ ์ค์ฌ ๋ ์์ ์ ์ด๊ณ ํจ์จ์ ์ธ ์ ํ๋ฆฌ์ผ์ด์ ์ผ๋ก ์ด์ด์ง๋๋ค.
- ์ฌ์ฉ์ ๊ฒฝํ(UX)์ ์์ฒญ๋ ๊ฐ์ : ์ฌ์ฉ์๋ ๊ฑฐ์ ์ฆ๊ฐ์ ์ธ ํตํ ์์, ํต์ ์ธ์ ๊ฐ์ ์ํํ ์ ํ, ์ ๋ฐ์ ์ผ๋ก ๋ ๋ฐ์์ฑ์ด ๋์ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฒฝํํฉ๋๋ค. ์ด ์ธ์๋ ์ฑ๋ฅ์ ๊ฒฝ์์ด ์น์ดํ ์ค์๊ฐ ์์ฅ์์ ์ค์ํ ์ฐจ๋ณํ ์์์ ๋๋ค.
- ๋จ์ํ๋๊ณ ์ค์ ์ง์คํ๋ ์ ํ๋ฆฌ์ผ์ด์ ๋ก์ง: ์ ์ค๊ณ๋ ํ ๊ด๋ฆฌ์๋ ์ฐ๊ฒฐ ์์ฑ, ์ฌ์ฌ์ฉ ๋ฐ ์ ์ง ๊ด๋ฆฌ์ ๋ณต์ก์ฑ์ ์บก์ํํฉ๋๋ค. ์ ํ๋ฆฌ์ผ์ด์ ์ ๋๋จธ์ง ๋ถ๋ถ์ ๊น๋ํ API๋ฅผ ํตํด ์ฐ๊ฒฐ์ ์์ฒญํ๊ณ ํด์ ํ ์ ์์ผ๋ฏ๋ก ๋ ๋ชจ๋ํ๋๊ณ ์ ์ง ๊ด๋ฆฌํ๊ธฐ ์ฌ์ด ์ฝ๋๋ก ์ด์ด์ง๋๋ค.
์ฐ๊ฒฐ ํ ๊ด๋ฆฌ์ ์ค๊ณ: ์ํคํ ์ฒ ๋ฐ ๊ตฌ์ฑ ์์
๊ฒฌ๊ณ ํ WebRTC ์ฐ๊ฒฐ ํ ๊ด๋ฆฌ์๋ ๋จ์ํ ํผ์ด ์ฐ๊ฒฐ์ ๋ฐฐ์ด ์ด์์ ๋๋ค. ์ ์คํ ์ํ ๊ด๋ฆฌ, ๋ช ํํ ํ๋ ๋ฐ ํด์ ํ๋กํ ์ฝ, ์ง๋ฅ์ ์ธ ์ ์ง ๊ด๋ฆฌ ๋ฃจํด์ด ํ์ํฉ๋๋ค. ์ํคํ ์ฒ์ ํ์ ๊ตฌ์ฑ ์์๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
์ฃผ์ ์ํคํ ์ฒ ๊ตฌ์ฑ ์์
- ํ ์ ์ฅ์: RTCPeerConnection ๊ฐ์ฒด๋ฅผ ๋ณด์ ํ๋ ํต์ฌ ๋ฐ์ดํฐ ๊ตฌ์กฐ์ ๋๋ค. ๋ฐฐ์ด, ํ ๋๋ ๋งต์ด ๋ ์ ์์ต๋๋ค. ์ค์ํ๊ฒ๋ ๊ฐ ์ฐ๊ฒฐ์ ์ํ๋ ์ถ์ ํด์ผ ํฉ๋๋ค. ์ผ๋ฐ์ ์ธ ์ํ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค: 'idle' (์ฌ์ฉ ๊ฐ๋ฅ), 'in-use' (ํ์ฌ ํผ์ด์ ํ์ฑ ์ํ), 'provisioning' (์์ฑ ์ค), 'stale' (์ ๋ฆฌ ๋์์ผ๋ก ํ์๋จ).
- ๊ตฌ์ฑ ๋งค๊ฐ๋ณ์: ์ ์ฐํ ํ ๊ด๋ฆฌ์๋ ๋ค์ํ ์ ํ๋ฆฌ์ผ์ด์
์๊ตฌ ์ฌํญ์ ๋ง๊ฒ ๊ตฌ์ฑํ ์ ์์ด์ผ ํฉ๋๋ค. ์ฃผ์ ๋งค๊ฐ๋ณ์๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
- minSize: ํญ์ '์์ด๋' ์ํ๋ก ์ ์งํ ์ ํด ์ฐ๊ฒฐ์ ์ต์ ๊ฐ์์ ๋๋ค. ํ์ ์ด ์ต์๊ฐ์ ์ถฉ์กฑํ๊ธฐ ์ํด ์ฌ์ ์๋ฐฉ์ ์ผ๋ก ์ฐ๊ฒฐ์ ์์ฑํฉ๋๋ค.
- maxSize: ํ์ด ๊ด๋ฆฌํ ์ ์๋ ์ ๋ ์ต๋ ์ฐ๊ฒฐ ๊ฐ์์ ๋๋ค. ์ด๋ ํญ์ฃผํ๋ ๋ฆฌ์์ค ์๋น๋ฅผ ๋ฐฉ์งํฉ๋๋ค.
- idleTimeout: ๋ฆฌ์์ค๋ฅผ ํด์ ํ๊ธฐ ์ํด ์ฐ๊ฒฐ์ด ๋ซํ๊ณ ์ ๊ฑฐ๋๊ธฐ ์ ์ 'idle' ์ํ๋ก ์ ์ง๋ ์ ์๋ ์ต๋ ์๊ฐ(๋ฐ๋ฆฌ์ด)์ ๋๋ค.
- creationTimeout: ICE ์์ง์ด ์ค๋จ๋๋ ๊ฒฝ์ฐ๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํ ์ด๊ธฐ ์ฐ๊ฒฐ ์ค์ ์ ๋ํ ์๊ฐ ์ด๊ณผ์ ๋๋ค.
- ํ๋ ๋ก์ง(์: acquireConnection()): ์ด๊ฒ์ ์ ํ๋ฆฌ์ผ์ด์
์ด ์ฐ๊ฒฐ์ ์ป๊ธฐ ์ํด ํธ์ถํ๋ ๊ณต๊ฐ ๋ฉ์๋์
๋๋ค. ๋ก์ง์ ๋ค์๊ณผ ๊ฐ์์ผ ํฉ๋๋ค:
- ํ์์ 'idle' ์ํ์ ์ฐ๊ฒฐ์ ๊ฒ์ํฉ๋๋ค.
- ์ฐพ์ผ๋ฉด 'in-use'๋ก ํ์ํ๊ณ ๋ฐํํฉ๋๋ค.
- ์ฐพ์ง ๋ชปํ๋ฉด ์ด ์ฐ๊ฒฐ ์๊ฐ maxSize๋ณด๋ค ์์์ง ํ์ธํฉ๋๋ค.
- ์์ผ๋ฉด ์ ์ฐ๊ฒฐ์ ์์ฑํ๊ณ ํ์ ์ถ๊ฐํ๊ณ 'in-use'๋ก ํ์ํ ๋ค์ ๋ฐํํฉ๋๋ค.
- ํ์ด maxSize์ ๋๋ฌํ๋ฉด ์์ฒญ์ ์ํ๋ ์ ๋ต์ ๋ฐ๋ผ ํ์ ๋๊ธฐํ๊ฑฐ๋ ๊ฑฐ๋ถ๋์ด์ผ ํฉ๋๋ค.
- ํด์ ๋ก์ง(์: releaseConnection()): ์ ํ๋ฆฌ์ผ์ด์
์ด ์ฐ๊ฒฐ ์ฌ์ฉ์ ๋ง์น๋ฉด ์ด๋ฅผ ํ๋ก ๋ฐํํด์ผ ํฉ๋๋ค. ์ด๊ฒ์ด ๊ด๋ฆฌ์์ ๊ฐ์ฅ ์ค์ํ๊ณ ๋ฏธ๋ฌํ ๋ถ๋ถ์
๋๋ค. ๋ค์์ ํฌํจํฉ๋๋ค:
- ํด์ ํ RTCPeerConnection ๊ฐ์ฒด ์์ .
- *๋ค๋ฅธ* ํผ์ด์ ์ฌ์ฌ์ฉํ ์ ์๋๋ก '์ฌ์ค์ ' ์์ ์ ์ํํฉ๋๋ค. ์ฌ์ค์ ์ ๋ต์ ๋์ค์ ์์ธํ ๋ ผ์ํ ๊ฒ์ ๋๋ค.
- ์ํ๋ฅผ ๋ค์ 'idle'๋ก ๋ณ๊ฒฝํฉ๋๋ค.
- idleTimeout ๋ฉ์ปค๋์ฆ์ ์ํด ๋ง์ง๋ง ์ฌ์ฉ ํ์์คํฌํ๋ฅผ ์ ๋ฐ์ดํธํฉ๋๋ค.
- ์ ์ง ๊ด๋ฆฌ ๋ฐ ์ํ ํ์ธ: ์ผ๋ฐ์ ์ผ๋ก setInterval์ ์ฌ์ฉํ์ฌ ํ์ ์ฃผ๊ธฐ์ ์ผ๋ก ์ค์บํ์ฌ ๋ค์์ ์ํํ๋ ๋ฐฑ๊ทธ๋ผ์ด๋ ํ๋ก์ธ์ค์
๋๋ค:
- ์ ํด ์ฐ๊ฒฐ ์ ๋ฆฌ: idleTimeout์ ์ด๊ณผํ ๋ชจ๋ 'idle' ์ฐ๊ฒฐ์ ๋ซ๊ณ ์ ๊ฑฐํฉ๋๋ค.
- ์ต์ ํฌ๊ธฐ ์ ์ง: ์ฌ์ฉ ๊ฐ๋ฅํ(์ ํด + ํ๋ก๋น์ ๋) ์ฐ๊ฒฐ ์๊ฐ ์ต์ minSize ์ด์์ธ์ง ํ์ธํฉ๋๋ค.
- ์ํ ๋ชจ๋ํฐ๋ง: ์ฐ๊ฒฐ ์ํ ์ด๋ฒคํธ(์: 'iceconnectionstatechange')๋ฅผ ์์ ํ์ฌ ์คํจํ๊ฑฐ๋ ์ฐ๊ฒฐ์ด ๋๊ธด ์ฐ๊ฒฐ์ ํ์์ ์๋์ผ๋ก ์ ๊ฑฐํฉ๋๋ค.
ํ ๊ด๋ฆฌ์ ๊ตฌํ: ์ค์ฉ์ ์ด๊ณ ๊ฐ๋ ์ ์ธ ์ํฌ์ค๋ฃจ
์ฐ๋ฆฌ์ ์ค๊ณ๋ฅผ ๊ฐ๋ ์ ์ธ JavaScript ํด๋์ค ๊ตฌ์กฐ๋ก ๋ณํํด ๋ด ์๋ค. ์ด ์ฝ๋๋ ํต์ฌ ๋ก์ง์ ๊ฐ์กฐํ๊ธฐ ์ํ ์์์ด๋ฉฐ, ํ๋ก๋์ ์ค๋น๊ฐ ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์๋๋๋ค.
// WebRTC ์ฐ๊ฒฐ ํ ๊ด๋ฆฌ์๋ฅผ ์ํ ๊ฐ๋ ์ ์ธ JavaScript ํด๋์ค
class WebRTCPoolManager { constructor(config) { this.config = { minSize: 2, maxSize: 10, idleTimeout: 30000, // 30 seconds iceServers: [], // Must be provided ...config }; this.pool = []; // { pc, state, lastUsed } ๊ฐ์ฒด๋ฅผ ์ ์ฅํ๋ ๋ฐฐ์ด this._initializePool(); this.maintenanceInterval = setInterval(() => this._runMaintenance(), 5000); } _initializePool() { /* ... */ } _createAndProvisionPeerConnection() { /* ... */ } _resetPeerConnectionForReuse(pc) { /* ... */ } _runMaintenance() { /* ... */ } async acquire() { /* ... */ } release(pc) { /* ... */ } destroy() { clearInterval(this.maintenanceInterval); /* ... ๋ชจ๋ pc ๋ซ๊ธฐ */ } }
1๋จ๊ณ: ํ ์ด๊ธฐํ ๋ฐ ์์ด
์์ฑ์๋ ๊ตฌ์ฑ์ ์ค์ ํ๊ณ ์ด๊ธฐ ํ ์ฑ์ฐ๊ธฐ๋ฅผ ์์ํฉ๋๋ค. _initializePool() ๋ฉ์๋๋ ํ์ด ์ฒ์๋ถํฐ minSize ์ฐ๊ฒฐ๋ก ์ฑ์์ง๋๋ก ํฉ๋๋ค.
_initializePool() { for (let i = 0; i < this.config.minSize; i++) { this._createAndProvisionPeerConnection(); } } async _createAndProvisionPeerConnection() { const pc = new RTCPeerConnection({ iceServers: this.config.iceServers }); const poolEntry = { pc, state: 'provisioning', lastUsed: Date.now() }; this.pool.push(poolEntry); // ๋๋ฏธ ์คํผ๋ฅผ ์์ฑํ์ฌ ICE ์์ง์ ์ ์ ์ ์ผ๋ก ์์ํฉ๋๋ค. // ์ด๊ฒ์ ํต์ฌ ์ต์ ํ์ ๋๋ค. const offer = await pc.createOffer({ offerToReceiveAudio: true, offerToReceiveVideo: true }); await pc.setLocalDescription(offer); // ์ด์ ICE ์์ง์ด ์๋ฃ๋๊ธฐ๋ฅผ ๊ธฐ๋ค๋ฆฝ๋๋ค. pc.onicegatheringstatechange = () => { if (pc.iceGatheringState === 'complete') { poolEntry.state = 'idle'; console.log("์๋ก์ด ํผ์ด ์ฐ๊ฒฐ์ด ์์ด๋์ด ํ์ ์ค๋น๋์์ต๋๋ค."); } }; // ์คํจ ์ฒ๋ฆฌ๋ ํฉ๋๋ค. pc.oniceconnectionstatechange = () => { if (pc.iceConnectionState === 'failed') { this._removeConnection(pc); } }; return poolEntry; }
์ด "์์ด" ํ๋ก์ธ์ค๋ ์ฃผ์ ์ง์ฐ ์๊ฐ ์ด์ ์ ์ ๊ณตํ๋ ๊ฒ์ ๋๋ค. ์ฆ์ ์คํผ๋ฅผ ์์ฑํ๊ณ ๋ก์ปฌ ์ค๋ช ์ ์ค์ ํจ์ผ๋ก์จ ์ฌ์ฉ์๊ฐ ์ฐ๊ฒฐ์ ํ์๋ก ํ๊ธฐ ํจ์ฌ ์ ์ ๋ธ๋ผ์ฐ์ ๊ฐ ๊ฐ๋น์ผ ICE ์์ง ํ๋ก์ธ์ค๋ฅผ ๋ฐฑ๊ทธ๋ผ์ด๋์์ ์์ํ๋๋ก ๊ฐ์ ํฉ๋๋ค.
2๋จ๊ณ: `acquire()` ๋ฉ์๋
์ด ๋ฉ์๋๋ ์ฌ์ฉ ๊ฐ๋ฅํ ์ฐ๊ฒฐ์ ์ฐพ๊ฑฐ๋ ์ ์ฐ๊ฒฐ์ ์์ฑํ์ฌ ํ์ ํฌ๊ธฐ ์ ์ฝ์ ๊ด๋ฆฌํฉ๋๋ค.
async acquire() { // ์ฒซ ๋ฒ์งธ ์ ํด ์ฐ๊ฒฐ ์ฐพ๊ธฐ let idleEntry = this.pool.find(entry => entry.state === 'idle'); if (idleEntry) { idleEntry.state = 'in-use'; idleEntry.lastUsed = Date.now(); return idleEntry.pc; } // ์ ํด ์ฐ๊ฒฐ์ด ์์ผ๋ฉด ์ต๋ ํฌ๊ธฐ๊ฐ ์๋ ๊ฒฝ์ฐ ์ ์ฐ๊ฒฐ ์์ฑ if (this.pool.length < this.config.maxSize) { console.log("ํ์ด ๋น์ด ์์ต๋๋ค. ์๋ก์ด ์จ๋๋งจ๋ ์ฐ๊ฒฐ์ ์์ฑํฉ๋๋ค."); const newEntry = await this._createAndProvisionPeerConnection(); newEntry.state = 'in-use'; // ์ฆ์ ์ฌ์ฉ ์ค์ผ๋ก ํ์ return newEntry.pc; } // ํ์ด ์ต๋ ์ฉ๋์ ๋๋ฌํ๊ณ ๋ชจ๋ ์ฐ๊ฒฐ์ด ์ฌ์ฉ ์ค์ ๋๋ค. throw new Error("WebRTC ์ฐ๊ฒฐ ํ์ด ๊ณ ๊ฐ๋์์ต๋๋ค."); }
3๋จ๊ณ: `release()` ๋ฉ์๋์ ์ฐ๊ฒฐ ์ฌ์ค์ ๊ธฐ์
์ด๊ฒ์ ๊ฐ์ฅ ๊ธฐ์ ์ ์ผ๋ก ์ด๋ ค์ด ๋ถ๋ถ์ ๋๋ค. RTCPeerConnection์ ์ํ๋ฅผ ๊ฐ์ง๋๋ค. ํผ์ด A์์ ์ธ์ ์ด ๋๋๋ฉด ์ํ๋ฅผ ์ฌ์ค์ ํ์ง ์๊ณ ๋ ํผ์ด B์ ์ฐ๊ฒฐํ๋ ๋ฐ ๋จ์ํ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ด๋ป๊ฒ ํ๋ฉด ํจ๊ณผ์ ์ผ๋ก ๊ทธ๋ ๊ฒ ํ ์ ์์๊น์?
๋จ์ํ pc.close()๋ฅผ ํธ์ถํ๊ณ ์ ์ฐ๊ฒฐ์ ๋ง๋๋ ๊ฒ์ ํ์ ๋ชฉ์ ์ ๋ฌดํจํํฉ๋๋ค. ๋์ '์ํํธ ์ฌ์ค์ '์ด ํ์ํฉ๋๋ค. ๊ฐ์ฅ ๊ฒฌ๊ณ ํ ์ต์ ์ ๊ทผ ๋ฐฉ์์ ํธ๋์๋ฒ๋ฅผ ๊ด๋ฆฌํ๋ ๊ฒ์ ํฌํจํฉ๋๋ค.
_resetPeerConnectionForReuse(pc) { return new Promise(async (resolve, reject) => { // 1. ๋ชจ๋ ๊ธฐ์กด ํธ๋์๋ฒ ์ค์ง ๋ฐ ์ ๊ฑฐ pc.getTransceivers().forEach(transceiver => { if (transceiver.sender && transceiver.sender.track) { transceiver.sender.track.stop(); } // ํธ๋์๋ฒ๋ฅผ ์ค์งํ๋ ๊ฒ์ด ๋ ๋ช ํํ ๋์์ ๋๋ค. if (transceiver.stop) { transceiver.stop(); } }); // ์ฐธ๊ณ : ์ผ๋ถ ๋ธ๋ผ์ฐ์ ๋ฒ์ ์์๋ ํธ๋์ ์๋์ผ๋ก ์ ๊ฑฐํด์ผ ํ ์ ์์ต๋๋ค. // pc.getSenders().forEach(sender => pc.removeTrack(sender)); // 2. ๋ค์ ํผ์ด์ ๋ํ ์๋ก์ด ํ๋ณด๋ฅผ ๋ณด์ฅํ๊ธฐ ์ํด ํ์ํ ๊ฒฝ์ฐ ICE๋ฅผ ๋ค์ ์์ํฉ๋๋ค. // ์ด๊ฒ์ ์ฐ๊ฒฐ์ด ์ฌ์ฉ ์ค์ผ ๋ ๋คํธ์ํฌ ๋ณ๊ฒฝ์ ์ฒ๋ฆฌํ๋ ๋ฐ ์ค์ํฉ๋๋ค. if (pc.restartIce) { pc.restartIce(); } // 3. *๋ค์* ํ์์ ์ํด ์ฐ๊ฒฐ์ ์๋ ค์ง ์ํ๋ก ๋๋๋ฆฌ๊ธฐ ์ํด ์๋ก์ด ์คํผ๋ฅผ ์์ฑํฉ๋๋ค. // ์ด๋ ๊ธฐ๋ณธ์ ์ผ๋ก '์์ด๋' ์ํ๋ก ๋๋๋ฆฝ๋๋ค. try { const offer = await pc.createOffer({ offerToReceiveAudio: true, offerToReceiveVideo: true }); await pc.setLocalDescription(offer); resolve(); } catch (error) { reject(error); } }); } async release(pc) { const poolEntry = this.pool.find(entry => entry.pc === pc); if (!poolEntry) { console.warn("์ด ํ์์ ๊ด๋ฆฌ๋์ง ์๋ ์ฐ๊ฒฐ์ ํด์ ํ๋ ค๊ณ ์๋ํ์ต๋๋ค."); pc.close(); // ์์ ์ ์ํด ๋ซ๊ธฐ return; } try { await this._resetPeerConnectionForReuse(pc); poolEntry.state = 'idle'; poolEntry.lastUsed = Date.now(); console.log("์ฐ๊ฒฐ์ด ์ฑ๊ณต์ ์ผ๋ก ์ฌ์ค์ ๋์ด ํ๋ก ๋ฐํ๋์์ต๋๋ค."); } catch (error) { console.error("ํผ์ด ์ฐ๊ฒฐ ์ฌ์ค์ ์ ์คํจํ์ต๋๋ค. ํ์์ ์ ๊ฑฐํฉ๋๋ค.", error); this._removeConnection(pc); // ์ฌ์ค์ ์ ์คํจํ๋ฉด ์ฐ๊ฒฐ์ ์ฌ์ฉ ๋ถ๊ฐ๋ฅํ ๊ฐ๋ฅ์ฑ์ด ๋์ต๋๋ค. } }
4๋จ๊ณ: ์ ์ง ๊ด๋ฆฌ ๋ฐ ๊ฐ์ง์น๊ธฐ
๋ง์ง๋ง ๋ถ๋ถ์ ํ์ ๊ฑด๊ฐํ๊ณ ํจ์จ์ ์ผ๋ก ์ ์งํ๋ ๋ฐฑ๊ทธ๋ผ์ด๋ ์์ ์ ๋๋ค.
_runMaintenance() { const now = Date.now(); const idleConnectionsToPrune = []; this.pool.forEach(entry => { // ๋๋ฌด ์ค๋ซ๋์ ์ ํด ์ํ์๋ ์ฐ๊ฒฐ ๊ฐ์ง์น๊ธฐ if (entry.state === 'idle' && (now - entry.lastUsed > this.config.idleTimeout)) { idleConnectionsToPrune.push(entry.pc); } }); if (idleConnectionsToPrune.length > 0) { console.log(`์ ํด ์ฐ๊ฒฐ ${idleConnectionsToPrune.length}๊ฐ๋ฅผ ๊ฐ์ง์น๊ธฐํฉ๋๋ค.`); idleConnectionsToPrune.forEach(pc => this._removeConnection(pc)); } // ์ต์ ํฌ๊ธฐ๋ฅผ ์ถฉ์กฑํ๋๋ก ํ ๋ณด์ถฉ const currentHealthySize = this.pool.filter(e => e.state === 'idle' || e.state === 'in-use').length; const needed = this.config.minSize - currentHealthySize; if (needed > 0) { console.log(`ํ์ ${needed}๊ฐ์ ์ ์ฐ๊ฒฐ์ ๋ณด์ถฉํฉ๋๋ค.`); for (let i = 0; i < needed; i++) { this._createAndProvisionPeerConnection(); } } } _removeConnection(pc) { const index = this.pool.findIndex(entry => entry.pc === pc); if (index !== -1) { this.pool.splice(index, 1); pc.close(); } }
๊ณ ๊ธ ๊ฐ๋ ๋ฐ ๊ธ๋ก๋ฒ ๊ณ ๋ ค ์ฌํญ
๊ธฐ๋ณธ ํ ๊ด๋ฆฌ์๋ ํ๋ฅญํ ์์์ด์ง๋ง ์ค์ ์ ํ๋ฆฌ์ผ์ด์ ์๋ ๋ ๋ง์ ๋์์ค๊ฐ ํ์ํฉ๋๋ค.
STUN/TURN ๊ตฌ์ฑ ๋ฐ ๋์ ์๊ฒฉ ์ฆ๋ช ์ฒ๋ฆฌ
TURN ์๋ฒ ์๊ฒฉ ์ฆ๋ช ์ ๋ณด์์์ ์ด์ ๋ก ์๋ช ์ด ์งง์ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค(์: 30๋ถ ํ ๋ง๋ฃ). ํ์ ์๋ ์ ํด ์ฐ๊ฒฐ์ ์๊ฒฉ ์ฆ๋ช ์ด ๋ง๋ฃ๋์์ ์ ์์ต๋๋ค. ํ ๊ด๋ฆฌ์๋ ์ด๋ฅผ ์ฒ๋ฆฌํด์ผ ํฉ๋๋ค. RTCPeerConnection์ setConfiguration() ๋ฉ์๋๊ฐ ํต์ฌ์ ๋๋ค. ์ฐ๊ฒฐ์ ํ๋ํ๊ธฐ ์ ์ ์ ํ๋ฆฌ์ผ์ด์ ๋ก์ง์ ์๊ฒฉ ์ฆ๋ช ์ ์ ํจ ๊ธฐ๊ฐ์ ํ์ธํ๊ณ , ํ์ํ ๊ฒฝ์ฐ ์ ์ฐ๊ฒฐ ๊ฐ์ฒด๋ฅผ ๋ง๋ค ํ์ ์์ด pc.setConfiguration({ iceServers: newIceServers })๋ฅผ ํธ์ถํ์ฌ ์๊ฒฉ ์ฆ๋ช ์ ์ ๋ฐ์ดํธํ ์ ์์ต๋๋ค.
๋ค์ํ ์ํคํ ์ฒ(SFU vs. ๋ฉ์)์ ๋ง๊ฒ ํ ์กฐ์
์ด์์ ์ธ ํ ๊ตฌ์ฑ์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ํคํ ์ฒ์ ํฌ๊ฒ ์ข์ฐ๋ฉ๋๋ค:
- SFU (Selective Forwarding Unit): ์ด ์ผ๋ฐ์ ์ธ ์ํคํ ์ฒ์์ ํด๋ผ์ด์ธํธ๋ ์ผ๋ฐ์ ์ผ๋ก ์ค์ ๋ฏธ๋์ด ์๋ฒ์ ํ๋ ๋๋ ๋ ๊ฐ์ ๊ธฐ๋ณธ ํผ์ด ์ฐ๊ฒฐ(๋ฏธ๋์ด ๊ฒ์์ฉ ํ๋, ๊ตฌ๋ ์ฉ ํ๋)์ ๊ฐ์ง๋๋ค. ์ฌ๊ธฐ์๋ ๋น ๋ฅด๊ณ ๋ค์ ์ฐ๊ฒฐ๋๊ฑฐ๋ ๋น ๋ฅธ ์ด๊ธฐ ์ฐ๊ฒฐ์ ๋ณด์ฅํ๊ธฐ ์ํด ์์ ํ(์: minSize: 1, maxSize: 2)์ด๋ฉด ์ถฉ๋ถํฉ๋๋ค.
- ๋ฉ์ ๋คํธ์ํฌ: ๊ฐ ํด๋ผ์ด์ธํธ๊ฐ ์ฌ๋ฌ ๋ค๋ฅธ ํด๋ผ์ด์ธํธ์ ์ฐ๊ฒฐ๋๋ ํผ์ด ํฌ ํผ์ด ๋ฉ์์์ ํ์ ํจ์ฌ ๋ ์ค์ํด์ง๋๋ค. maxSize๋ ์ฌ๋ฌ ๋์ ์ฐ๊ฒฐ์ ์์ฉํ ์ ์๋๋ก ๋ ์ปค์ผ ํ๋ฉฐ, ํผ์ด๊ฐ ๋ฉ์์ ์ฐธ์ฌํ๊ณ ๋๊ฐ์ ๋ฐ๋ผ ํ๋/ํด์ ์ฃผ๊ธฐ๊ฐ ํจ์ฌ ๋ ๋น๋ฒํด์ง๋๋ค.
๋คํธ์ํฌ ๋ณ๊ฒฝ ๋ฐ "์ค๋๋" ์ฐ๊ฒฐ ์ฒ๋ฆฌ
์ฌ์ฉ์์ ๋คํธ์ํฌ๋ ์ธ์ ๋ ์ง ๋ณ๊ฒฝ๋ ์ ์์ต๋๋ค(์: Wi-Fi์์ ๋ชจ๋ฐ์ผ ๋คํธ์ํฌ๋ก ์ ํ). ํ์ ์๋ ์ ํด ์ฐ๊ฒฐ์ ์ด์ ์ ํจํ์ง ์์ ICE ํ๋ณด๋ฅผ ์์งํ์ ์ ์์ต๋๋ค. ์ด๋ restartIce()๊ฐ ๋งค์ฐ ์ ์ฉํฉ๋๋ค. ๊ฒฌ๊ณ ํ ์ ๋ต์ acquire() ํ๋ก์ธ์ค์ ์ผ๋ถ๋ก ์ฐ๊ฒฐ์ ๋ํด restartIce()๋ฅผ ํธ์ถํ๋ ๊ฒ์ผ ์ ์์ต๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ์ฐ๊ฒฐ์ด ์๋ก์ด ํผ์ด์์ ํ์์ ์ฌ์ฉ๋๊ธฐ ์ ์ ์๋ก์ด ๋คํธ์ํฌ ๊ฒฝ๋ก ์ ๋ณด๋ฅผ ๊ฐ๊ฒ ๋์ด ์ฝ๊ฐ์ ์ง์ฐ ์๊ฐ์ด ์ถ๊ฐ๋์ง๋ง ์ฐ๊ฒฐ ์์ ์ฑ์ด ํฌ๊ฒ ํฅ์๋ฉ๋๋ค.
์ฑ๋ฅ ๋ฒค์น๋งํน: ๊ฐ์์ ์ธ ์ํฅ
์ฐ๊ฒฐ ํ์ ์ด์ ์ ์ด๋ก ์ ์ด์ง ์์ต๋๋ค. ์๋ก์ด P2P ํ์ ํตํ๋ฅผ ์ค์ ํ๋ ๋ช ๊ฐ์ง ๋ํ์ ์ธ ์์น๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
์๋๋ฆฌ์ค: ์ฐ๊ฒฐ ํ์ด ์๋ ๊ฒฝ์ฐ
- T0: ์ฌ์ฉ์๊ฐ "ํตํ"๋ฅผ ํด๋ฆญํฉ๋๋ค.
- T0 + 10ms: new RTCPeerConnection()์ด ํธ์ถ๋ฉ๋๋ค.
- T0 + 200-800ms: ์คํผ๊ฐ ์์ฑ๋๊ณ , ๋ก์ปฌ ์ค๋ช ์ด ์ค์ ๋๊ณ , ICE ์์ง์ด ์์๋๊ณ , ์๊ทธ๋๋ง์ ํตํด ์คํผ๊ฐ ์ ์ก๋ฉ๋๋ค.
- T0 + 400-1500ms: ์๋ต์ด ์์ ๋๊ณ , ์๊ฒฉ ์ค๋ช ์ด ์ค์ ๋๊ณ , ICE ํ๋ณด๊ฐ ๊ตํ ๋ฐ ํ์ธ๋ฉ๋๋ค.
- T0 + 500-2000ms: ์ฐ๊ฒฐ์ด ์ค์ ๋ฉ๋๋ค. ์ฒซ ๋ฒ์งธ ๋ฏธ๋์ด ํ๋ ์๊น์ง์ ์๊ฐ: ~0.5 ~ 2์ด.
์๋๋ฆฌ์ค: ์์ด๋ ์ฐ๊ฒฐ ํ์ด ์๋ ๊ฒฝ์ฐ
- ๋ฐฑ๊ทธ๋ผ์ด๋: ํ ๊ด๋ฆฌ์๊ฐ ์ด๋ฏธ ์ฐ๊ฒฐ์ ์์ฑํ๊ณ ์ด๊ธฐ ICE ์์ง์ ์๋ฃํ์ต๋๋ค.
- T0: ์ฌ์ฉ์๊ฐ "ํตํ"๋ฅผ ํด๋ฆญํฉ๋๋ค.
- T0 + 5ms: pool.acquire()๊ฐ ๋ฏธ๋ฆฌ ์์ด๋ ์ฐ๊ฒฐ์ ๋ฐํํฉ๋๋ค.
- T0 + 10ms: ์ ์คํผ๊ฐ ์์ฑ๋๊ณ (ICE๋ฅผ ๊ธฐ๋ค๋ฆฌ์ง ์์ผ๋ฏ๋ก ๋น ๋ฆ ๋๋ค) ์๊ทธ๋๋ง์ ํตํด ์ ์ก๋ฉ๋๋ค.
- T0 + 200-500ms: ์๋ต์ด ์์ ๋๊ณ ์ค์ ๋ฉ๋๋ค. ์ต์ข DTLS ํธ๋์ ฐ์ดํฌ๋ ์ด๋ฏธ ํ์ธ๋ ICE ๊ฒฝ๋ก๋ฅผ ํตํด ์๋ฃ๋ฉ๋๋ค.
- T0 + 250-600ms: ์ฐ๊ฒฐ์ด ์ค์ ๋ฉ๋๋ค. ์ฒซ ๋ฒ์งธ ๋ฏธ๋์ด ํ๋ ์๊น์ง์ ์๊ฐ: ~0.25 ~ 0.6์ด.
๊ฒฐ๊ณผ๋ ๋ช ํํฉ๋๋ค. ์ฐ๊ฒฐ ํ์ ์ฐ๊ฒฐ ์ง์ฐ ์๊ฐ์ ์ฝ๊ฒ 50-75% ์ด์ ์ค์ผ ์ ์์ต๋๋ค. ๋ํ ์ฐ๊ฒฐ ์ค์ ์ CPU ๋ถํ๋ฅผ ๋ฐฑ๊ทธ๋ผ์ด๋์์ ์๊ฐ์ ๊ฑธ์ณ ๋ถ์ฐํจ์ผ๋ก์จ ์ฌ์ฉ์๊ฐ ์์ ์ ์์ํ๋ ์ ํํ ์๊ฐ์ ๋ฐ์ํ๋ ๋ถ์พํ ์ฑ๋ฅ ์คํ์ดํฌ๋ฅผ ์ ๊ฑฐํ์ฌ ํจ์ฌ ๋ ๋ถ๋๋ฝ๊ณ ์ ๋ฌธ์ ์ธ ๋๋์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ๊ณตํฉ๋๋ค.
๊ฒฐ๋ก : ์ ๋ฌธ WebRTC์ ํ์ ๊ตฌ์ฑ ์์
์ค์๊ฐ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ด ๋ณต์กํด์ง๊ณ ์ฑ๋ฅ์ ๋ํ ์ฌ์ฉ์ ๊ธฐ๋์น๊ฐ ๊ณ์ ์ฆ๊ฐํจ์ ๋ฐ๋ผ ํ๋ฐํธ์๋ ์ต์ ํ๊ฐ ๋ฌด์๋ณด๋ค ์ค์ํด์ง๋๋ค. RTCPeerConnection ๊ฐ์ฒด๋ ๊ฐ๋ ฅํ์ง๋ง ์์ฑ ๋ฐ ํ์์ ์๋นํ ์ฑ๋ฅ ๋น์ฉ์ด ๋ฐ๋ฆ ๋๋ค. ๋จ์ผํ๊ณ ์ค๋ ์ง์๋๋ ํผ์ด ์ฐ๊ฒฐ ์ด์์ ํ์๋ก ํ๋ ๋ชจ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฒฝ์ฐ ์ด ๋น์ฉ์ ๊ด๋ฆฌํ๋ ๊ฒ์ ์ ํ ์ฌํญ์ด ์๋๋ผ ํ์ ์ฌํญ์ ๋๋ค.
ํ๋ฐํธ์๋ WebRTC ์ฐ๊ฒฐ ํ ๊ด๋ฆฌ์๋ ์ง์ฐ ์๊ฐ ๋ฐ ๋ฆฌ์์ค ์๋น๋ผ๋ ํต์ฌ ๋ณ๋ชฉ ํ์์ ์ง์ ์ ์ผ๋ก ํด๊ฒฐํฉ๋๋ค. ํผ์ด ์ฐ๊ฒฐ์ ์ฌ์ ์ ์์ฑํ๊ณ , ์์ดํ๊ณ , ํจ์จ์ ์ผ๋ก ์ฌ์ฌ์ฉํจ์ผ๋ก์จ ์ฌ์ฉ์ ๊ฒฝํ์ ๋๋ฆฌ๊ณ ์์ธก ๋ถ๊ฐ๋ฅํ ๊ฒ์์ ์ฆ๊ฐ์ ์ด๊ณ ์์ ์ ์ธ ๊ฒ์ผ๋ก ๋ณํ์ํต๋๋ค. ํ ๊ด๋ฆฌ์๋ฅผ ๊ตฌํํ๋ฉด ์ํคํ ์ฒ ๋ณต์ก์ฑ ๊ณ์ธต์ด ์ถ๊ฐ๋์ง๋ง ์ฑ๋ฅ, ํ์ฅ์ฑ ๋ฐ ์ฝ๋ ์ ์ง ๊ด๋ฆฌ ์ธก๋ฉด์์ ์ป์ ์ ์๋ ์ด์ ์ ์์ฒญ๋ฉ๋๋ค.
์ค์๊ฐ ํต์ ์ ๊ธ๋ก๋ฒํ๊ณ ๊ฒฝ์์ ์ธ ํ๊ฒฝ์์ ์ด์๋๋ ๊ฐ๋ฐ์์ ์ํคํ ํธ์๊ฒ ์ด ํจํด์ ์ฑํํ๋ ๊ฒ์ ์๋์ ์๋ต์ฑ์ผ๋ก ์ฌ์ฉ์์๊ฒ ์ฆ๊ฑฐ์์ ์ ์ฌํ๋ ์ง์ ์ผ๋ก ์ธ๊ณ์ ์ธ ์์ค์ ์ ๋ฌธ์ ์ธ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ๊ธฐ ์ํ ์ ๋ต์ ๋จ๊ณ์ ๋๋ค.