μ—¬ν–‰
λ² νŠΈλ‚¨

νšŒμ‚¬ λ„€νŠΈμ›Œν¬μ—μ„œ Agora onUserJoined() 콜백이 μ•ˆ 올 λ•Œ? Cloud Proxy μ„€μ •μœΌλ‘œ ν•΄κ²°ν•˜κΈ°

μ•±μ—μ„œ Agora SDKλ₯Ό 톡해 μŒμ„± μ±„νŒ… κΈ°λŠ₯을 κ΅¬ν˜„ν–ˆλŠ”λ°, μ§‘μ—μ„œλŠ” 잘 λ˜μ§€λ§Œ νšŒμ‚¬μ—μ„œλŠ” onUserJoined() 콜백쑰차 μ˜€μ§€ μ•ŠλŠ” ν˜„μƒ, ν˜Ήμ‹œ κ²ͺμ–΄λ³΄μ…¨λ‚˜μš”?
저희도 졜근 이 문제λ₯Ό κ²ͺ으며 원인을 λΆ„μ„ν–ˆκ³ , ν•΄κ²° λ°©λ²•μœΌλ‘œ Agora의 Cloud Proxy κΈ°λŠ₯을 μ‚¬μš©ν–ˆμŠ΅λ‹ˆλ‹€.
이번 κΈ€μ—μ„œλŠ” Agora Cloud Proxy의 μž‘λ™ 방식, λΉ„μš©, μ„€μ • 방법을 μ •λ¦¬ν•΄λ“œλ¦½λ‹ˆλ‹€.

문제 상황 μš”μ•½

β€’
Agora SDK의 joinChannel ν˜ΈμΆœμ€ 성곡
β€’
ν•˜μ§€λ§Œ νšŒμ‚¬ λ„€νŠΈμ›Œν¬μ—μ„œλŠ” onUserJoined() 콜백이 μ•„μ˜ˆ μ˜€μ§€ μ•ŠμŒ
β€’
λ™μΌν•œ κΈ°κΈ°/μ•±μœΌλ‘œ μ§‘μ—μ„œλŠ” 정상 μž‘λ™ β†’ λ„€νŠΈμ›Œν¬ ν™˜κ²½ 차이둜 μΆ”μ •

원인: κΈ°μ—… λ„€νŠΈμ›Œν¬μ˜ λ°©ν™”λ²½ 및 포트 μ œν•œ

νšŒμ‚¬λ‚˜ κΈ°κ΄€ λ„€νŠΈμ›Œν¬λŠ” λ³΄μ•ˆμƒ 이유둜 λ‹€μŒμ„ μ°¨λ‹¨ν•˜λŠ” κ²½μš°κ°€ λ§ŽμŠ΅λ‹ˆλ‹€:
β€’
UDP 포트 차단 (3478~3481 λ“±)
β€’
NAT λ°©ν™”λ²½ λ˜λŠ” ν”„λ‘μ‹œ μ‚¬μš©
β€’
Deep Packet Inspection(DPI)으둜 VoIP νŠΈλž˜ν”½ μ œν•œ
이둜 인해 Agora의 λ―Έλ””μ–΄ μ„œλ²„μ™€μ˜ 연결이 μ‹€νŒ¨ν•˜κ³ , μ½œλ°±λ„ λ°›μ§€ λͺ»ν•˜κ²Œ λ©λ‹ˆλ‹€.

ν•΄κ²° 방법: Agora Cloud Proxy μ‚¬μš©

AgoraλŠ” 이λ₯Ό μœ„ν•΄ Cloud Proxy κΈ°λŠ₯을 μ œκ³΅ν•©λ‹ˆλ‹€.
μ΄λŠ” 일반 연결이 λΆˆκ°€λŠ₯ν•  λ•Œ TCP 기반 ν”„λ‘μ‹œ μ„œλ²„λ₯Ό κ²½μœ ν•΄ μ•ˆμ •μ μœΌλ‘œ ν†΅μ‹ ν•˜κ²Œ ν•΄μ£ΌλŠ” κΈ°λŠ₯μž…λ‹ˆλ‹€.

Cloud Proxy μ„€μ • 방법

1. μ½˜μ†”μ—μ„œ Cloud Proxy ν™œμ„±ν™”

Agora μ½˜μ†” 접속: https://console.agora.io
β€’
[Project Management] β†’ ν•΄λ‹Ή ν”„λ‘œμ νŠΈ 선택
β€’
[Advanced Features] νƒ­ β†’ Enable Cloud Proxy ν† κΈ€ ON
β€’
μ•½ 24μ‹œκ°„ λ‚΄ 적용됨

2. SDKμ—μ„œ Cloud Proxy μ‚¬μš© λͺ…μ‹œ

Force TCP λͺ¨λ“œ (rtc.proxy:2) 섀정이 νšŒμ‚¬λ§μ—μ„œ κ°€μž₯ μ•ˆμ •μ 

Android (Kotlin)

val rtcEngine = RtcEngine.create(context, "YOUR_APP_ID", rtcEventHandler) rtcEngine.setParameters("{\"rtc.proxy\":2}") rtcEngine.joinChannel("YOUR_TOKEN", "YOUR_CHANNEL_NAME", "", 0)
Kotlin
볡사

iOS (Swift)

let agoraKit = AgoraRtcEngineKit.sharedEngine(withAppId: "YOUR_APP_ID", delegate: self) agoraKit.setParameters("{\"rtc.proxy\":2}") agoraKit.joinChannel(byToken: "YOUR_TOKEN", channelId: "YOUR_CHANNEL_NAME", info: nil, uid: 0, joinSuccess: nil)
Swift
볡사

λΉ„μš©μ€? λ¬΄λ£ŒμΈκ°€μš”?

Cloud ProxyλŠ” 기본적으둜 무료 μ²΄ν—˜μ΄ 제곡되며, μ†Œκ·œλͺ¨ μ‚¬μš©μ—λŠ” μΆ”κ°€ μš”κΈˆμ΄ μ—†μŠ΅λ‹ˆλ‹€.
쑰건
λ‚΄μš©
30일 무료 μ²΄ν—˜
μ΅œλŒ€ 50λͺ… λ™μ‹œ μ‚¬μš©μžκΉŒμ§€ κ°€λŠ₯, μžλ™ μ’…λ£Œ
μ›” 무료 μ‚¬μš©λŸ‰
Cloud Proxy 10,000λΆ„κΉŒμ§€ 무료
유료 μ „ν™˜ 쑰건
무료 μ‚¬μš©λŸ‰ 초과 λ˜λŠ” λŒ€κ·œλͺ¨ μ‚¬μš© (μ›” $500 이상 μš”κΈˆ λ°œμƒ κ°€λŠ₯μ„±)
μ²΄ν—˜μ€ νšŒμ‚¬ λ‹Ή 1회만 κ°€λŠ₯ν•˜λ©°, μ½˜μ†”μ—μ„œ μ‹ μ²­ ν›„ μ‚¬μš© κ°€λŠ₯

κ²°λ‘ 

β€’
AgoraλŠ” 기본적으둜 μžλ™ ν”„λ‘μ‹œ fallback을 μ œκ³΅ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
β€’
Cloud Proxy μ‚¬μš©μ„ 원할 경우, λ°˜λ“œμ‹œ μ½˜μ†”μ—μ„œ ν™œμ„±ν™”ν•˜κ³  SDKμ—μ„œλ„ λͺ…μ‹œμ μœΌλ‘œ μ„€μ •ν•΄μ•Ό ν•©λ‹ˆλ‹€.
β€’
ν…ŒμŠ€νŠΈλ‚˜ μ†Œκ·œλͺ¨ μš΄μ˜μ—μ„œλŠ” λΉ„μš© 없이 μ‚¬μš©ν•  수 μžˆμœΌλ‹ˆ λΆ€λ‹΄ 없이 μ μš©ν•΄λ³΄μ„Έμš”.

λ³΄λ„ˆμŠ€: 둜그둜 ν™•μΈν•˜κΈ°

ν”„λ‘μ‹œκ°€ μ μš©λ˜μ—ˆλŠ”μ§€ ν™•μΈν•˜λ €λ©΄ Agora SDK의 둜그 κΈ°λŠ₯을 μ‚¬μš©ν•˜μ„Έμš”.
rtcEngine.setLogFile("/sdcard/agora/agora.log")
Kotlin
볡사
Agoraλ₯Ό μ•ˆμ •μ μœΌλ‘œ μš΄μ˜ν•˜λ €λ©΄ λ„€νŠΈμ›Œν¬ ν™˜κ²½μ— 따라 μœ μ—°ν•˜κ²Œ λŒ€μ‘ν•˜λŠ” 것이 μ€‘μš”ν•©λ‹ˆλ‹€.
ν”„λ‘μ‹œ μ„€μ • ν•œ μ€„λ‘œ νšŒμ‚¬ λ‚΄ λ„€νŠΈμ›Œν¬ 문제λ₯Ό λ§λ”νžˆ ν•΄κ²°ν•΄λ³΄μ„Έμš”!