- Ref - Session | CHZZK
μ±ν λ©μμ§ μ‘°ν
μ (νμ ꡬλ μ΄ νμν μ)νμ μ‘°ν
Scopeμ λν κΆν μ¬μ¬κ° λͺ¨λ λ§μ³€μμ κ°μ ν©λλ€. κ·Έλ μ§ μμ κ²½μ° 500 Internal Server Errorμ ν¨κ» μΈμ μ°κ²° URLλΆν° λ°κΈμ΄ λΆκ°λ₯ν©λλ€.
- λ§μ μΈμμ Eventλ₯Ό ꡬλ ν΄μΌνλ κ²½μ°(μ: λ§μΈν¬λννΈ μ€νΈλ¦¬λ¨Έ νμμ 1μ²λͺ μ°λνλ κ²½μ° λ±), κ° μ€νΈλ¦¬λ¨Έκ° κ°λ°μμ μ ν리μΌμ΄μ μ OAuth λ‘κ·ΈμΈμ νκ²λ νμ¬ Access Tokenμ λ°κΈ λ°μ μΈμ μ μμ±νλ λ°©μμ μΆμ²λ립λλ€. μ΄λ Client μΈμ¦μΌλ‘ μΈμ μ λ°κΈ λ°μ 15κ°μ μ±λμ μ±ν , νμ μ΄λ²€νΈλ₯Ό λͺ¨λ ꡬλ νλ κ²½μ° 30κ° μ νμ λλ¬νλ©°, Access Token λ°©μμ ν μΈμ λΉ μ΅λ 30κ°μ μ΄λ²€νΈλ₯Ό ꡬλ ν μ μλ μ νμ λ²μ΄λκΈ° μν λ°©λ²μ΄κΈ° λλ¬Έμ λλ€.
- APIλ‘ λ°κΈλ Session Socket URLμ μ ν¨ν μκ°μ΄ μΌλ§λ λλμ§λ μ ννκ² μ μ μμΌλ(μμμΌλ‘λ μ½ 30μ΄ ~ 1λΆ?), λ§μ½ μ°κ²°μ μλνμ λ URLμ΄ μ¬λ°λ¦μλ λΆκ΅¬ μ°κ²° μλμ μ°κ²°μ΄ λ°λ‘ λκΈ°λ κ²½μ°, ν΄λΉ URLμ΄ λ§λ£λκ²μ λλ€. μλ‘ λ°κΈ λ°μΌμ μΌν©λλ€.
- νμ¬ Client μΈμ¦λ§μ μ΄μ©ν΄μ κ°λ°μμ μ±λ μ΄μΈ ν μ€νΈλ¦¬λ¨Έμ μ±ν
μ΄λ νμμ ꡬλ
νκ³ μΆμ κ²½μ°, REST APIλ‘ κ΅¬λ
μμ²μ μ μ‘ ν λ Authorization ν€λμ Bearer ν ν° κ°μ μ€νΈλ¦¬λ¨Έκ° μ¬μ μ μΈμ¦ Schemeμ μλ£νμ¬ λ°κΈν Access Token κ°μΌλ‘ μ§μ νλ©΄ κ°λ₯ν©λλ€. λ€λ§, ν μΈμ
λΉ μ΅λλ‘ κ΅¬λ
ν μ μλ μ΄λ²€νΈ κ°μλ₯Ό κ³ λ €νμ¬, κ°μΈμ μΌλ‘ μΈμ
μ체λ₯Ό Access Token λ°©μμΌλ‘ μμ±νλ κ²μ μΆμ²λ립λλ€.
- λ΄μ©μ λμΆ© μ½μΌμ ¨λ€λ©΄ μκ² μ§λ§, λ€. μ€νΈλ¦¬λ¨Έμ λ‘κ·ΈμΈμ ν¬ν¨νμ§ μκ³ ν΄λΉ μ€νΈλ¦¬λ¨Έ μ±λμ μ±ν μ΄λ νμ μ΄λ²€νΈλ₯Ό ꡬλ ν μ μλ λ°©λ²μ μμ μμ΅λλ€. λ΄ μ ν리μΌμ΄μ Client μ 보 λ¨μΌλ‘ λ΄ μ±λ νΉμ μ±λ ꡬλ μ μμ λΆκ°λ₯νλ€λ μλ―Έμ λλ€. λ΄ μ±λμ ꡬλ ν λμλ REST APIμ μΈμ¦ ν ν°μ λ£μ΄μΌνλκΉμ.
- νμ¬ Client μΈμ¦μ ν΅ν΄ μμ±λ Session(λ° Session Key)μ λν΄ λ€μ λ΄μ©μ νμΈμ΄ μ΄λ ΅κ±°λ λΆκ°λ₯νκ²μΌλ‘ νμ
λ©λλ€:
- μΈμ URLμ λ°κΈ ν λ€ μ°κ²°μ μ§ν νμΌλ μ°κ²°μ΄ λκΈ΄ κ²½μ°λ μ΅μ΄ μ°κ²° μ ν μκ°μ΄ μ§λ μ΄ν, μΈμ λͺ©λ‘μ μ‘°ννμλ μ°κ²°μ΄ λκ²Όκ±°λ μ°κ²° μκ°μ΄ μ§λλ²λ¦° μΈμ μ λ³΄κ° μΈμ λͺ©λ‘μμ μ¬λΌμ§λ μκ° (νμ¬ μ΅λ 39κ°μ μΈμ μμ± μ΄ν μΆκ° μΈμ μ μμ±νλ €κ³ ν λ μ¬λΌμ§λ 쑰건μΌλ‘ μΆμΈ‘λ¨)
- κ°μ λ‘ μΈμ μ μΈμ λͺ©λ‘μμ μ κ±°ν μ μλ λ°©λ² (μλ§ κ·Έλ₯ λ―Έμ 곡νλκ²μΌλ‘ μΆμΈ‘ν©λλ€.)
- κ°μ₯ ν° μ°©μ€κ° λ°μ ν μ μλ λΆλΆμΌλ‘, 곡μ λ¬Έμμμ "μ΅λ nκ°μ API μ°κ²°μ μ μ§ ν μ μμ" λ΄μ©μ λμμ μ°κ²°μ μ μ§μν¬ μ μλ κ°μλ₯Ό λ»νλ©° κ°λ°μκ° μ΅λλ‘ μμ± ν μ μλ μΈμ μ κ°μκ° μλλλ€. μΈμ μ μΈμ λ μ§ μ¬λ¬κ° μμ±ν μ μλκ²μΌλ‘ 보μ λλ€. λ€λ§ μ΅λ μΈμ μ‘°ν κ°λ₯ κ°μμΈ 39κ° μ΄μμ μμ±νλ©΄ μ΄λ»κ² λλμ§μ λν΄μλ νμΈν΄λ³΄μ§ λͺ»νμ΅λλ€.
- λλ²μ§Έλ‘ κ°μ₯ λ§μ μ°©μ€λ‘, μ΄λ²€νΈλ₯Ό ꡬλ
/ꡬλ
μ·¨μ ν λ μ¬μ©νλ
sessionKey
κ°μ POST μμ²μ΄μ΄λ Query Parameter(?sessionKey=XXXXXX
)λ‘ μ€μ ν΄μΌνλ©° μμ² Bodyμ JSON ννλ‘ μμ±νλ λ°©μμ μ§μλμ§ μμ΅λλ€. (μ¬λ΄..) - WebSocket μ°κ²°μ΄ λμ΄ μμ§ μλ μνμμ REST APIλ₯Ό ν΅ν΄ Session Key μ 보λ§μ μ΄μ©νμ¬ Eventλ₯Ό ꡬλ ν μλ μμ΅λλ€. 400 Bad Requestμ μ°κ²° νμΈ μ€λ₯ λ©μμ§λ₯Ό μλ΄ν©λλ€.
- TypeScript κΈ°μ€ socket.io-client λ²μ 2.0.3, @types/socket.io-client λ²μ 1.4.36μ΄ κ°λ₯ν μ΅λ λ²μ μΌλ‘ 보μ λλ€. μ΄μΈμ λ²μ μ μ¬μ©νλ©΄ μλ²λ¨μμ κ°μ λ‘ μ°κ²°ν΄μ£Όμ§ μμ΅λλ€.
- Java/Kotlin κΈ°μ€ socket.io-client-java λ²μ 1.0.2κ° κ°λ₯ν μ΅λ λ²μ μΌλ‘ 보μ λλ€. μ΄μΈμ λ²μ μ μ¬μ©νλ©΄ μλ²λ¨μμ κ°μ λ‘ μ°κ²°ν΄μ£Όμ§ μμ΅λλ€.
-
Session Socket URL(λ°κΈ λ°μ μΈμ μ°κ²° URLμ μλ―Έ)μ
https://ssio<λ²νΈ>.nchat.naver.com:443?auth=<AUTH_TOKEN>
λ‘ λ°νλλ©° μ£Όλ‘ νμΈλ λ²νΈλ€λ‘07
,09
,27
μ΄ μ‘΄μ¬ν©λλ€. λ°κΈλ URL λ΄μ μ«μ μ΄μΈ λ€λ₯Έ μ«μλ‘ μ°κ²°μ΄ μ μμ μΌλ‘ μ§νλλμ§λ μλν΄λ³΄μ§ μμμ΅λλ€. -
ν μ€νΈλ₯Ό μ§ννκΈ° μν΄ μ¬μ©ν μ½λ μμ μ΄ Gistμ 첨λΆν©λλ€.
μλμ λ΄μ©μ μΈμ μ°κ²° μ΄ν SYSTEM μ΄λ²€νΈλ₯Ό ꡬλ νμμ λ μμ λ°μ μ μλ λ©μμ§ μ’ λ₯μ λλ€.
λͺ¨λ λ©μμ§λ JSON λ©μμ§λ‘ μ΄λ£¨μ΄μ ΈμμΌλ©°, κ°λ μ±μ μν΄ Indentλ₯Ό μ£Όμμ΅λλ€. μ€μ λ‘λ ν μ€λ‘ νμλ©λλ€.
λΆκ°μ μΈ μ€λͺ μ μνμ¬ λ¬Έμμ JSONμ λͺ¨λ JSONCλ‘ μμ±λμμ΅λλ€! μ€μ JSONμμλ μ£Όμμ΄ λΆκ°λ₯ν μ μ μνμκΈΈ λ°λλλ€.
- μ±ν μ°κ²° μ§ν μ
{
"type": "connected",
"data": {
"sessionKey": "<SOCKET_SESSION_KEY>"
// νμ¬ μ°κ²°λ μΈμ
μ Session Key κ°μ νλνμ€ μ μμ΅λλ€.
// μ μ 보λ₯Ό μ΄μ©νμ¬ Eventλ₯Ό ꡬλ
νκ±°λ μΈμ
μ ꡬλΆνλ μ©λλ‘ μ¬μ©ν μ μμ΅λλ€.
}
}
- POST μμ²μΌλ‘ μ±ν
Eventλ₯Ό ꡬλ
ν μ (
/open/v1/sessions/events/subscribe/chat?sessionKey=<SOCKET_SESSION_KEY>
)
{
"type": "subscribed",
"data": {
"eventType": "CHAT", // ꡬλ
Event νμ
, μμ κ°λ₯ν κ°μ CHAT, DONATIONμ
λλ€.
"channelId": "<SUBSCRIBED_CHANNEL_ID>" // ꡬλ
ν μ±λ ID
}
}
- POST μμ²μΌλ‘ νμ Eventλ₯Ό ꡬλ
ν μ (
/open/v1/sessions/events/subscribe/donation?sessionKey=<SOCKET_SESSION_KEY>
)
{
"type": "subscribed",
"data": {
"eventType": "DONATION", // ꡬλ
Event νμ
, μμ κ°λ₯ν κ°μ CHAT, DONATIONμ
λλ€.
"channelId": "<SUBSCRIBED_CHANNEL_ID>" // ꡬλ
ν μ±λ ID
}
}
- POST μμ²μΌλ‘ μ±ν
Eventλ₯Ό ꡬλ
μ·¨μν μ (
/open/v1/sessions/events/unsubscribe/chat?sessionKey=<SOCKET_SESSION_KEY>
)
{
"type": "unsubscribed",
"data": {
"eventType": "CHAT", // ꡬλ
ν΄μ§ Event νμ
, μμ κ°λ₯ν κ°μ CHAT, DONATIONμ
λλ€.
"channelId": "<UNSUBSCRIBED_CHANNEL_ID>" // ꡬλ
ν΄μ§ν μ±λ ID
}
}
- POST μμ²μΌλ‘ νμ Eventλ₯Ό ꡬλ
μ·¨μν μ (
/open/v1/sessions/events/unsubscribe/donation?sessionKey=<SOCKET_SESSION_KEY>
)
{
"type": "unsubscribed",
"data": {
"eventType": "DONATION", // ꡬλ
ν΄μ§ Event νμ
, μμ κ°λ₯ν κ°μ CHAT, DONATIONμ
λλ€.
"channelId": "<UNSUBSCRIBED_CHANNEL_ID>" // ꡬλ
ν΄μ§ν μ±λ ID
}
}
μλμ λ΄μ©μ μΈμ μ°κ²° μ΄ν CHAT μ΄λ²€νΈλ₯Ό ꡬλ νμμ λ μμ λ°μ μ μλ λ©μμ§ μ’ λ₯μ λλ€.
λͺ¨λ λ©μμ§λ JSON λ©μμ§λ‘ μ΄λ£¨μ΄μ ΈμμΌλ©°, κ°λ μ±μ μν΄ Indentλ₯Ό μ£Όμμ΅λλ€. μ€μ λ‘λ ν μ€λ‘ νμλ©λλ€.
λΆκ°μ μΈ μ€λͺ μ μνμ¬ λ¬Έμμ JSONμ λͺ¨λ JSONCλ‘ μμ±λμμ΅λλ€! μ€μ JSONμμλ μ£Όμμ΄ λΆκ°λ₯ν μ μ μνμκΈΈ λ°λλλ€.
- μΌλ° μ±ν
{
"channelId": "<STREAMING_CHANNEL_ID>", // λ°©μ‘μΈμ μ±λ ID
"senderChannelId": "<CHAT_SENDER_CHANNEL_ID>", // λ©μμ§λ₯Ό μ μ‘ν μ¬λμ μ±λ ID
"profile": { // μΉμ§μ§ νλ‘ν μ 보
"nickname": "<CHAT_SENDER_NICKNAME>", // λ©μμ§λ₯Ό μ μ‘ν μ¬λμ λλ€μ
"verifiedMark": false, // μΉμ§μ§ μΈμ¦ λ§ν¬ (ννΈλ μ€νΈλ¦¬λ¨Έ μΈμ¦ λ§ν¬λ‘ μΆμ )
"badges": [ // λ±μ§ μ΄λ―Έμ§ URL λͺ©λ‘
{
"imageUrl": "https://ssl.pstatic.net/static/nng/glive/icon/streamer.png" // μ€νΈλ¦¬λ¨Έ λ³ΈμΈμ λ±μ§ μ΄λ―Έμ§
}
// λ±μ§ μ’
λ₯λ λ€μν λ§νΌ, λͺ¨λ λ±μ§μ URLμ κΈ°μ
νκΈ°λ μ΄λ €μ΄ μ μν΄ λΆνλ립λλ€.
]
},
"content": "do test {:d_47:}", // μ±ν
λ΄μ©, μΉμ§μ§ μ±ν
μ΄λͺ¨μ§λ μ€κ΄νΈ λ΄μ μ½λ‘ νμμ κ·Έ μμ μ΄λͺ¨μ§ μ΄λ¦μ λ΄λ ννλ‘ κ΅¬μ±λμ΄μμ΅λλ€.
"emojis": { // μ΄λͺ¨μ§ μ΄λ¦ λ° URL
"d_47": "https://ssl.pstatic.net/static/nng/glive/icon/b_07.gif?type=f60_60"
},
"messageTime": 1739110481425 // λ©μμ§ μ μ‘ μκ°
}
μλμ λ΄μ©μ μΈμ μ°κ²° μ΄ν DONATION μ΄λ²€νΈλ₯Ό ꡬλ νμμ λ μμ λ°μ μ μλ λ©μμ§ μ’ λ₯μ λλ€.
λͺ¨λ λ©μμ§λ JSON λ©μμ§λ‘ μ΄λ£¨μ΄μ ΈμμΌλ©°, κ°λ μ±μ μν΄ Indentλ₯Ό μ£Όμμ΅λλ€. μ€μ λ‘λ ν μ€λ‘ νμλ©λλ€.
λΆκ°μ μΈ μ€λͺ μ μνμ¬ λ¬Έμμ JSONμ λͺ¨λ JSONCλ‘ μμ±λμμ΅λλ€! μ€μ JSONμμλ μ£Όμμ΄ λΆκ°λ₯ν μ μ μνμκΈΈ λ°λλλ€.
- μΌλ° νμ
{
"donationType": "CHAT", // νμ νμ
, κ°λ₯ν νμ
μ νμ¬ CHAT, VIDEO λ μ’
λ₯ μ
λλ€.
"channelId": "<DONATION_RECEIVED_CHANNEL_ID>", // νμμ μμ ν μ±λ ID (μ€νΈλ¦¬λ¨Έ)
"donatorChannelId": "<DONATOR_CHANNEL_ID>", // νμμ λ³΄λΈ μ±λ ID (μμ²μ)
"donatorNickname": "<DONATOR_NICKNAME>", // νμμ λ³΄λΈ μ±λμ λλ€μ (μμ²μ λλ€μ)
"payAmount": 1000, // νμ κΈμ‘
"donationText": "TEST" // νμ λ΄μ©
}
- μμ νμ
- μμ URLμ λν λ³λ μ 보λ μ λ¬λμ§ μμ΅λλ€.
{
"donationType": "VIDEO", // νμ νμ
, κ°λ₯ν νμ
μ νμ¬ CHAT, VIDEO λ μ’
λ₯ μ
λλ€.
"channelId": "<DONATION_RECEIVED_CHANNEL_ID>", // νμμ μμ ν μ±λ ID (μ€νΈλ¦¬λ¨Έ)
"donatorChannelId": "<DONATOR_CHANNEL_ID>", // νμμ λ³΄λΈ μ±λ ID (μμ²μ)
"donatorNickname": "<DONATOR_NICKNAME>", // νμμ λ³΄λΈ μ±λμ λλ€μ (μμ²μ λλ€μ)
"payAmount": 1000, // νμ κΈμ‘
"donationText": "μΉμ§μ§, μ€νΈλ¦¬λ°μ΄ μμλ©λλ€." // νμ λ΄μ©, μμ νμμ κ²½μ° νμ λ΄μ©μ΄ μμμ μ λͺ©μ
λλ€.
}
-
νμ μ΄λ²€νΈλ λλΆλΆ μ€μ νμ μ΄λ²€νΈμ λν΄μλ§ λμν©λλ€. νμμ ν μ€νΈ νκ³ μΆλ€λ©΄ μμ΅ μ°½μΆμ΄ νμ±ν λ μ±λ κΈ°μ€μΌλ‘
μΉμ§μ§ μ€νλμ€ β λ°©μ‘ κ΄λ¦¬ β μλ¦Ό β νμ μλ¦Ό
μΌλ‘ μ΄λνμ¬νμ μλ¦Ό ꡬμ μ΅νλ¨μ "ν μ€νΈ μλ¦Ό 보λ΄κΈ°"
κΈ°λ₯μ μ΄μ©ν΄μ£ΌμκΈΈ λ°λλλ€. (https://studio.chzzk.naver.com/μ±λ ID/notification
) -
μ΅λͺ νμμ μ§νν μ
donatorChannelId
λ"anonymous"
,donatorNickname
μ""
μ λλ€. -
μ€νΈλ¦¬λ¨Έμ νμ κΈμ‘ νμ μ¬λΆμ κ΄κ³ μμ΄ κ³΅μ APIλ₯Ό ν΅νμ¬ λ°μ Eventμμλ
payAmount
κ° νμλ©λλ€.
Q. μ΄κ±° 곡μ ν΄λ λλμ?
A. λ€ λ©λλ€.
@fi-xz μν λΉ λ₯΄κ³ μμΈν λ΅λ³ κ°μ¬λ립λλ€. μ λ§ λμμ΄ λ§μ΄ λμμ΅λλ€!