@websocket ๋ฐ์ฝ๋ ์ดํฐ๋ ํด๋ผ์ด์ธํธ์ ์๋ฒ ์ฌ์ด์ ์๋ฐฉํฅ ๋ฉ์์ง ์ฑ๋์ ๋ง๋๋ WebSocket API๋ฅผ ์ ์ํฉ๋๋ค. SSE ์ ์ฉ์ธ @stream๊ณผ ๋ฌ๋ฆฌ ํด๋ผ์ด์ธํธ๊ฐ ๋ณด๋ด๋ ์ด๋ฒคํธ(inEvents)๋ ์ฒ๋ฆฌํ ์ ์๊ณ , ๊ฐ์ namespace/room์ ๋ฌถ์ธ ๋ค๋ฅธ ์ฐ๊ฒฐ๋ก ๋ฉ์์ง๋ฅผ ๋ธ๋ก๋์บ์คํธํ ์ ์์ต๋๋ค.
๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ
์ต์
outEvents
์๋ฒ โ ํด๋ผ์ด์ธํธ๋ก ๋ณด๋ผ ์ด๋ฒคํธ์ ํ์ ์ Zod ์คํค๋ง๋ก ์ ์ํฉ๋๋ค. ํ์ ์ต์ inEvents
ํด๋ผ์ด์ธํธ โ ์๋ฒ๋ก ๋ค์ด์ฌ ์ด๋ฒคํธ์ ํ์ ์ Zod ์คํค๋ง๋ก ์ ์ํฉ๋๋ค. ํ์ ์ต์ ๋ค์ด์จ ์ด๋ฒคํธ๋ envelope์ ๊ฑฐ์ณ ์๋ ๊ฒ์ฆ๋ฉ๋๋ค. ์คํค๋ง์ ์๋ ์ด๋ฒคํธ๋ ํ์์ด ๋ง์ง ์๋ ํ์ด๋ก๋๋ ์ฒ๋ฆฌ๋์ง ์๊ณ ์ ์ฑ
์๋ฐ์ผ๋ก ์ฒ๋ฆฌ๋ฉ๋๋ค.
path
WebSocket ์๋ํฌ์ธํธ ๊ฒฝ๋ก๋ฅผ ์ง์ ํฉ๋๋ค. ๊ธฐ๋ณธ๊ฐ:/{modelName}/{methodName} (camelCase)
namespace
๊ฐ์ ์๋ฒ ์์์ ๋ผ์ฐํ ยท๋ธ๋ก๋์บ์คํธ์ ๋ฒ์๋ฅผ ๊ฐ๋ฅด๋ ๋ ผ๋ฆฌ์ ๊ทธ๋ฃน์ ๋๋ค.Sonamu.websocketRuntime.publishToRoom(roomId, event, data, namespace)๋ก ๋ณด๋ผ ๋ ๊ฐ์ namespace์ ์ฐ๊ฒฐ์๋ง ์ ๋ฌ๋ฉ๋๋ค.
๊ธฐ๋ณธ๊ฐ: "default"
heartbeat
์ฐ๊ฒฐ ์ ์ง๋ฅผ ์ํ ping ๊ฐ๊ฒฉ(๋ฐ๋ฆฌ์ด)์ ๋๋ค. ๊ธฐ๋ณธ๊ฐ:30000 (30์ด)
guards
์ ๊ทผ ๊ถํ์ ์ง์ ํฉ๋๋ค.1008 Policy Violation์ผ๋ก close๋ฉ๋๋ค.
description
WebSocket API ์ค๋ช ์ ์ถ๊ฐํฉ๋๋ค.resourceName
์์ฑ๋๋ ์๋น์ค ํ์ผ์ ๋ฆฌ์์ค ์ด๋ฆ์ ์ง์ ํฉ๋๋ค.WebSocketContext
๋ฐ์ฝ๋ ์ดํฐ๊ฐ ์ ์ฉ๋ ๋ฉ์๋๋ ๋ง์ง๋ง ์ธ์๋กWebSocketContext<TOut, TIn>์ ๋ฐ์ต๋๋ค.
ctx.ws.publish
ํด๋น ์ฐ๊ฒฐ๋ก๋ง ์ด๋ฒคํธ๋ฅผ ์ ์กํฉ๋๋ค.ctx.ws.onMessage
ํด๋ผ์ด์ธํธ๊ฐ ๋ณด๋ธ ์ด๋ฒคํธ๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค.ctx.ws.onClose
์ฐ๊ฒฐ์ด ๋ซํ ๋ ์ ๋ฆฌ ์์ ์ ์ํํฉ๋๋ค.ctx.ws.waitForClose
์ฐ๊ฒฐ์ด ๋๋ ๋๊น์ง ํธ๋ค๋ฌ๋ฅผ ์ด์์๊ฒ ์ ์งํฉ๋๋ค. WebSocket ๋ฉ์๋๋ ๋ณดํต ์ด promise๋ฅผ awaitํ๋ฉฐ ๋ง๋ฌด๋ฆฌ๋ฉ๋๋ค.ctx.ws.join / ctx.ws.leave
๋ธ๋ก๋์บ์คํธ ๋จ์์ธ room์ ์ฐ๊ฒฐ์ ๊ฐ์ /ํํด์ํต๋๋ค.ctx.ws.setUserId / ctx.ws.clearUserId
์ฐ๊ฒฐ์ ์ฌ์ฉ์ ์๋ณ์๋ฅผ ๋ถ์ฌpublishToUser์ ํ๊ฒ์ด ๋๊ฒ ํฉ๋๋ค.
๋ธ๋ก๋์บ์คํธ
ํธ๋ค๋ฌ ๋ฐ์์๋Sonamu.websocketRuntime์ ํตํด ๊ฐ์ ์ฑ๋์ ๋ค๋ฅธ ์ฐ๊ฒฐ์ ๋ฉ์์ง๋ฅผ ๋ณด๋ผ ์ ์์ต๋๋ค.
๋ค๋ฅธ ๋ฐ์ฝ๋ ์ดํฐ์ ํจ๊ป ์ฌ์ฉ
@websocket์ @api, @stream, @upload์ ๊ฐ์ ๋ฉ์๋์ ๋์์ ์ฌ์ฉํ ์ ์์ต๋๋ค. WebSocket์ผ๋ก ๊ตฌ๋
ํ๋ฉด์ ๋์ผ ๋ฐ์ดํฐ๋ฅผ ์ผ๋ฐ HTTP๋ก๋ ์กฐํํ๊ณ ์ถ๋ค๋ฉด, ๋ฉ์๋๋ฅผ ๋ถ๋ฆฌํด ํ์ชฝ์ @api๋ก, ๋ค๋ฅธ ํ์ชฝ์ @websocket์ผ๋ก ๋
ธ์ถํ์ธ์.
์ ์ฝ์ฌํญ
1. @api / @stream / @upload์ ์ค๋ณต ์ฌ์ฉ ๋ถ๊ฐ
2. httpMethod๋ ํญ์ GET
@websocket์ ์๋์ผ๋ก httpMethod: "GET"์ ์ค์ ํฉ๋๋ค. WebSocket upgrade๋ GET ์์ฒญ์์ ์์๋๊ธฐ ๋๋ฌธ์
๋๋ค.
3. createSSE / reply์ ์์กดํ๋ contextProvider ์ฌ์ฉ ์ ์ฃผ์
WebSocket ๊ฒฝ๋ก์์๋ SSE ํฌํผ๋ FastifyReply ์ ๊ทผ์ด ์๋ฏธ๊ฐ ์์ด ์ ๊ทผํ๋ฉด ์ฆ์ ์๋ฌ๊ฐ ๋ฐ์ํฉ๋๋ค. ์ปจํ ์คํธ๊ฐ SSE/reply์ ์์กดํ๋ค๋ฉดwebsocketContextProvider๋ฅผ ๋ณ๋๋ก ์ ์ํ์ธ์.
ํด๋ผ์ด์ธํธ ์ฌ์ฉ (Web)
@websocket์ด ๋ถ์ ๋ฉ์๋์ ๋ํด Sonamu๋ useWebSocketChannel ํ
์ ์๋ ์์ฑํฉ๋๋ค.
useWebSocketChannel์ด ๋ฐํํ๋ ์ํ:
๋ก๊น
@websocket ๋ฐ์ฝ๋ ์ดํฐ๋ ํธ์ถ ์ ์๋์ผ๋ก ๋๋ฒ๊ทธ ๋ก๊ทธ๋ฅผ ๋จ๊น๋๋ค.
@stream๊ณผ์ ์ฐจ์ด
| ํญ๋ชฉ | @stream (SSE) | @websocket |
|---|---|---|
| ๋ฐฉํฅ | ์๋ฒ โ ํด๋ผ์ด์ธํธ (๋จ๋ฐฉํฅ) | ์๋ฐฉํฅ |
| ํด๋ผ์ด์ธํธ ์ด๋ฒคํธ ์ฒ๋ฆฌ | ๋ถ๊ฐ | inEvents ์คํค๋ง๋ก ์์ |
| ๋ธ๋ก๋์บ์คํธ | SSE ์ฐ๊ฒฐ๋ง๋ค ์๋ ๋ฐํ | room / userId ๊ธฐ๋ฐ ๋ผ์ฐํ
์ง์ |
| HTTP ๋ฉ์๋ | GET (์๋) | GET (์๋, upgrade) |
| ์๋ ์์ฑ ํด๋ผ์ด์ธํธ | eventSource ํฌํผ | useWebSocketChannel ํ
|
๋ค์ ๋จ๊ณ
@stream
๋จ๋ฐฉํฅ SSE ์คํธ๋ฆฌ๋ฐ์ด ํ์ํ ๋
@api
์ผ๋ฐ REST API ๋ง๋ค๊ธฐ
@transactional
ํธ๋์ญ์
์ผ๋ก ์ผ๊ด์ฑ ๋ณด์ฅ
@cache
๊ฒฐ๊ณผ ์บ์ฑ์ผ๋ก ์ฑ๋ฅ ํฅ์