Skip to content

๐Ÿ“ก Redis pubsub๋ฅผ ํ™œ์šฉํ•œ SSE ์ ์šฉ๊ธฐ

student079 edited this page Nov 18, 2024 · 1 revision

์•ˆ๋…•! ํด๋กœ๋ฐ”ํŒŒํŠธ๋ผ! ๋Š” ์‚ฌ์šฉ์ž๋“ค์ด ์Œ์„ฑ์œผ๋กœ ์Œ์ •๊ณผ ๋ฐœ์Œ์„ ๊ฒจ๋ฃจ๋Š” ๊ฒŒ์ž„์„ ์ฆ๊ธธ ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„๋œ ๊ฒŒ์ž„์ž…๋‹ˆ๋‹ค. ๐ŸŽค WebRTC๋ฅผ ํ†ตํ•ด ์Œ์„ฑ์„ ์ŠคํŠธ๋ฆฌ๋ฐํ•˜๊ณ , WebSocket์„ ์‚ฌ์šฉํ•˜์—ฌ ์‹ค์‹œ๊ฐ„ ํ†ต์‹ ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ , ๊ฒŒ์ž„ ๋ฐฉ ๋ชฉ๋ก์˜ ์‹ค์‹œ๊ฐ„ ์—…๋ฐ์ดํŠธ๋Š” ์—ฌ์ „ํžˆ ๋ฌธ์ œ์˜€์ฃ . ๋ฐฉ์˜ ์ƒ์„ฑ, ์‚ฌ์šฉ์ž ์ฐธ์—ฌ, ํ‡ด์žฅ ๋“ฑ์˜ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ฆ‰์‹œ ๋ฐ˜์˜ํ•˜๋ ค๋ฉด, ๋” ๋‚˜์€ ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด Redis Pub/Sub์™€ Server-Sent Events๋ฅผ ๋„์ž…ํ•˜์—ฌ ๊ฒŒ์ž„ ๋ฐฉ ๋ชฉ๋ก์˜ ์‹ค์‹œ๊ฐ„ ์—…๋ฐ์ดํŠธ๋ฅผ ๊ตฌํ˜„ํ•œ ๊ฒฝํ—˜์„ ๊ณต์œ ํ•˜๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค. ๐Ÿ˜Š


๊ธฐ์กด ๊ตฌ์กฐ์™€ ๋ฌธ์ œ์ 

๊ธฐ์กด์—๋Š” HTTP REST API๋ฅผ ํ†ตํ•ด ๊ฒŒ์ž„ ๋ฐฉ ๋ชฉ๋ก์„ ๊ด€๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ํŽ˜์ด์ง€๋ฅผ ์ƒˆ๋กœ๊ณ ์นจํ•  ๋•Œ๋งˆ๋‹ค ์„œ๋ฒ„์—์„œ ๋ฐฉ ๋ชฉ๋ก์„ ์ „๋‹ฌํ•˜๋Š” ๋ฐฉ์‹์ด์—ˆ์ฃ . ํ•˜์ง€๋งŒ ์ด ๋ฐฉ๋ฒ•์—๋Š” ๋ช‡ ๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

1๏ธโƒฃ ์‹ค์‹œ๊ฐ„์„ฑ ๋ถ€์กฑ

  • ๋ฐฉ์ด ์ƒ์„ฑ๋˜๊ฑฐ๋‚˜ ์‚ฌ์šฉ์ž๊ฐ€ ๋ฐฉ์„ ๋– ๋‚˜๋ฉด, ์ฆ‰๊ฐ์ ์œผ๋กœ ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ฐ˜์˜๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์ด๋กœ ์ธํ•ด ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์— ์ง€์—ฐ์ด ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.

2๏ธโƒฃ ์„œ๋ฒ„ ๋ถ€ํ•˜ ์ฆ๊ฐ€

  • ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ฃผ๊ธฐ์ ์œผ๋กœ ์„œ๋ฒ„์— ๋ฐ์ดํ„ฐ๋ฅผ ์š”์ฒญํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ฐฑ์‹ ๋˜๋Š” ๊ตฌ์กฐ์—ฌ์„œ ์„œ๋ฒ„์— ๋ถˆํ•„์š”ํ•œ ๋ถ€ํ•˜๋ฅผ ์ดˆ๋ž˜ํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด Redis Pub/Sub์™€ SSE๋ฅผ ๋„์ž…ํ•˜์—ฌ ์‹ค์‹œ๊ฐ„์„ฑ๊ณผ ์„œ๋ฒ„ ํšจ์œจ์„ฑ์„ ๊ฐœ์„ ํ–ˆ์Šต๋‹ˆ๋‹ค. ๐Ÿš€


๐Ÿ“ก Redis Pub/Sub์™€ SSE๋กœ ๋ฆฌํŒฉํ† ๋ง

๐Ÿ”ง Redis Pub/Sub๋ž€?

Redis Pub/Sub๋Š” Publish/Subscribe(๋ฐœํ–‰/๊ตฌ๋…) ํŒจํ„ด์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋Š” ๋ฉ”์‹œ์ง• ์‹œ์Šคํ…œ์ž…๋‹ˆ๋‹ค. ๋ฐœํ–‰์ž๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ํŠน์ • ์ฑ„๋„์— ๋ณด๋‚ด๊ณ , ๊ตฌ๋…์ž๋Š” ํ•ด๋‹น ์ฑ„๋„์˜ ๋ฉ”์‹œ์ง€๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ˆ˜์‹ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • Publisher(๋ฐœํ–‰์ž): ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐœํ–‰ํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๊ฒŒ์ž„ ๋ฐฉ ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐœํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  • Subscriber(๊ตฌ๋…์ž): ํŠน์ • ์ฑ„๋„์„ ๊ตฌ๋…ํ•˜๊ณ , ๊ทธ ์ฑ„๋„์— ๋ฉ”์‹œ์ง€๊ฐ€ ๋“ค์–ด์˜ค๋ฉด ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ด๋ฅผ ์ˆ˜์‹ ํ•ฉ๋‹ˆ๋‹ค.

Redis ๊ณต์‹ ๋ฌธ์„œ์—์„œ๋Š” Pub/Sub๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค:

"Redis Pub/Sub is a simple and fast messaging system. Messages are sent by publishers to channels, and subscribers receive those messages when subscribed to the corresponding channels."

โ€” Redis Pub/Sub Documentation

Redis์—์„œ Pub/Sub๋ฅผ ํ™œ์šฉํ•˜๋ฉด ์—ฌ๋Ÿฌ ์„œ๋ฒ„๋‚˜ ์‹œ์Šคํ…œ ๊ฐ„ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†กํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋กœ์จ ๊ฒŒ์ž„ ๋ฐฉ ์ƒํƒœ์˜ ์‹ค์‹œ๊ฐ„ ๋™๊ธฐํ™”๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ”ง SSE(Server-Sent Events)๋ž€?

SSE๋Š” ์„œ๋ฒ„-ํด๋ผ์ด์–ธํŠธ ๊ฐ„์˜ ๋‹จ๋ฐฉํ–ฅ ํ†ต์‹ ์„ ์œ„ํ•œ ๊ธฐ์ˆ ๋กœ, ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์„œ๋ฒ„์— ์—ฐ๊ฒฐ์„ ์œ ์ง€ํ•˜๊ณ  ์„œ๋ฒ„๊ฐ€ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ํ‘ธ์‹œํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. WebSocket๊ณผ ๋‹ฌ๋ฆฌ ์–‘๋ฐฉํ–ฅ ํ†ต์‹ ์ด ํ•„์š” ์—†๋Š” ์ƒํ™ฉ์—์„œ ๊ฐ„ํŽธํ•˜๊ณ  ํšจ์œจ์ ์ธ ์†”๋ฃจ์…˜์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

SSE๋Š” HTTP ํ”„๋กœํ† ์ฝœ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์ž‘๋™ํ•˜๋ฏ€๋กœ ๋ธŒ๋ผ์šฐ์ € ํ˜ธํ™˜์„ฑ์ด ๋›ฐ์–ด๋‚˜๋ฉฐ ์„ค์ •์ด ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ๋ฅผ ์„œ๋ฒ„์—์„œ ํด๋ผ์ด์–ธํŠธ๋กœ ํ‘ธ์‹œํ•  ๋•Œ ๋งค์šฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.


Redis Pub/Sub์™€ SSE๋ฅผ ํ™œ์šฉํ•œ ์ž‘๋™ ์›๋ฆฌ

1๏ธโƒฃ Redis Pub/Sub๋กœ ์ƒํƒœ ๋ณ€๊ฒฝ ๊ฐ์ง€

  • ๊ฒŒ์ž„ ๋ฐฉ์ด ์ƒ์„ฑ๋˜๊ฑฐ๋‚˜ ์‚ญ์ œ๋˜๊ฑฐ๋‚˜ ์‚ฌ์šฉ์ž๊ฐ€ ์ฐธ์—ฌ/ํ‡ด์žฅํ•˜๋Š” ๊ฒฝ์šฐ, Redis์˜ Pub/Sub๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ƒํƒœ ๋ณ€๊ฒฝ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐœํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  • ์„œ๋ฒ„๋Š” ์ด ๋ฉ”์‹œ์ง€๋ฅผ ๊ตฌ๋…ํ•˜์—ฌ ๋ฐฉ ์ƒํƒœ ๋ณ€๊ฒฝ์„ ๊ฐ์ง€ํ•ฉ๋‹ˆ๋‹ค.

2๏ธโƒฃ SSE๋กœ ํด๋ผ์ด์–ธํŠธ์— ์‹ค์‹œ๊ฐ„ ์ „์†ก

  • ์„œ๋ฒ„๋Š” Redis์—์„œ ๋ฉ”์‹œ์ง€๋ฅผ ์ˆ˜์‹ ํ•˜๊ณ , ์ด๋ฅผ SSE๋ฅผ ํ†ตํ•ด ํด๋ผ์ด์–ธํŠธ์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.
  • ํด๋ผ์ด์–ธํŠธ๋Š” ์ˆ˜์‹ ํ•œ ์ด๋ฒคํŠธ๋กœ UI๋ฅผ ์ฆ‰์‹œ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.

์ด ๊ตฌ์กฐ๋Š” ์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ์˜ ํ•ต์‹ฌ์ด ๋ฉ๋‹ˆ๋‹ค.


๊ตฌ์ฒด์ ์ธ Redis Pub/Sub ํ™œ์šฉ

1. pub/sub ํด๋ผ์ด์–ธํŠธ ๋ถ„๋ฆฌ

Redis์˜ Pub/Sub ๊ธฐ๋Šฅ์„ ํ™œ์šฉํ•˜๋ฉด ์—ฌ๋Ÿฌ ์‹œ์Šคํ…œ ๊ฐ„์— ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋•Œ, Publish(๋ฐœํ–‰)์™€ Subscribe(๊ตฌ๋…) ์—ญํ• ์„ ๋ถ„๋ฆฌํ•˜๋ฉด ์„ฑ๋Šฅ๊ณผ ์œ ์ง€๋ณด์ˆ˜ ์ธก๋ฉด์—์„œ ์ด์ ์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Redis Pub/Sub์˜ ๊ธฐ๋ณธ ๊ตฌ์กฐ

Redis์—์„œ Pub/Sub ๋ชจ๋ธ์€ ๋‘ ๊ฐ€์ง€ ์ฃผ์š” ์—ญํ• ๋กœ ๋‚˜๋‰ฉ๋‹ˆ๋‹ค:

  • Publisher (Pub): ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐœํ–‰ํ•˜๋Š” ํด๋ผ์ด์–ธํŠธ์ž…๋‹ˆ๋‹ค. ํŠน์ • ์ฑ„๋„์— ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด๋ฉด, ์ด ์ฑ„๋„์„ ๊ตฌ๋…ํ•˜๊ณ  ์žˆ๋Š” ํด๋ผ์ด์–ธํŠธ๋“ค์ด ํ•ด๋‹น ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • Subscriber (Sub): ํŠน์ • ์ฑ„๋„์„ ๊ตฌ๋…ํ•˜๊ณ  ์žˆ๋Š” ํด๋ผ์ด์–ธํŠธ์ž…๋‹ˆ๋‹ค. ๊ตฌ๋…ํ•œ ์ฑ„๋„์— ๋ฉ”์‹œ์ง€๊ฐ€ ๋„๋‹ฌํ•˜๋ฉด ์ด๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ˆ˜์‹ ํ•ฉ๋‹ˆ๋‹ค.

๊ธฐ๋ณธ์ ์œผ๋กœ ๊ฐ™์€ Redis ํด๋ผ์ด์–ธํŠธ๋ฅผ ์‚ฌ์šฉํ•ด Pub/Sub๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์‹ค์ œ๋กœ ํด๋ผ์ด์–ธํŠธ๋ฅผ ๋ถ„๋ฆฌํ•˜์—ฌ ๊ฐ๊ฐ ๋…๋ฆฝ์ ์ธ ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•˜๋„๋ก ์„ค๊ณ„ํ•˜๋ฉด ๋” ํšจ์œจ์ ์ด๊ณ , ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์‰ฌ์šด ์‹œ์Šคํ…œ์„ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Pub/Sub ํด๋ผ์ด์–ธํŠธ ๋ถ„๋ฆฌ์˜ ์ด์ 

Redis ๊ณต์‹ ๋ฌธ์„œ์—์„œ๋Š” Pub/Sub ์‹œ์Šคํ…œ์„ ํ†ตํ•ด ์—ฌ๋Ÿฌ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ฉ”์‹œ์ง€๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค๊ณ  ์–ธ๊ธ‰ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ, Pub/Sub ํŒจํ„ด์„ ์‚ฌ์šฉํ•  ๋•Œ, ๊ฐ ํด๋ผ์ด์–ธํŠธ๋ฅผ ๋…๋ฆฝ์ ์œผ๋กœ ๊ด€๋ฆฌํ•˜๋ฉด ๋” ํšจ์œจ์ ์œผ๋กœ ์‹œ์Šคํ…œ์„ ํ™•์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

"Using separate clients for publishing and subscribing can help improve performance in scenarios where a client might need to do other work in parallel, such as managing a user interface while receiving messages."

โ€” Redis Pub/Sub ๊ณต์‹ ๋ฌธ์„œ

๋”ฐ๋ผ์„œ Pub/Sub ํด๋ผ์ด์–ธํŠธ๋ฅผ ๋ถ„๋ฆฌํ•˜๋ฉด ์„ฑ๋Šฅ ๊ฐœ์„ ๊ณผ ํ•จ๊ป˜ ์œ ์ง€๋ณด์ˆ˜์„ฑ์ด ํ–ฅ์ƒ๋˜๋ฉฐ, ๊ฐ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ž์‹ ์˜ ์—ญํ• ์— ๋งž๊ฒŒ ์ตœ์ ํ™”๋œ ์ž‘์—…์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, Publisher๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐœํ–‰ํ•˜๋Š” ๋ฐ ์ง‘์ค‘ํ•˜๊ณ , Subscriber๋Š” ์ˆ˜์‹ ๋œ ๋ฉ”์‹œ์ง€๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ์ง‘์ค‘ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

@Injectable()
export class RedisService implements OnModuleDestroy {
  private pubClient: Redis; // publish ํด๋ผ์ด์–ธํŠธ
  private subClient: Redis; // subscribe ํด๋ผ์ด์–ธํŠธ

  constructor(@Inject('REDIS_CLIENT') private readonly redisClient: Redis) {
    this.pubClient = new Redis(redisClient.options);
    this.subClient = new Redis(redisClient.options);
  }

  onModuleDestroy() {
    this.pubClient.quit();
    this.subClient.quit();
  }
  ...
}

2. ๋ฉ”์‹œ์ง€ ๋ฐœํ–‰

๊ฒŒ์ž„ ๋ฐฉ ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค roomUpdate ์ฑ„๋„์„ ํ†ตํ•ด ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐœํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋ฐฉ์ด ์ƒ์„ฑ๋  ๋•Œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด Redis์— ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐœํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

await this.redisService.publishToChannel(
  "roomUpdate",
  JSON.stringify(roomData)
);

์ด ๋ฉ”์‹œ์ง€๋Š” roomUpdate ์ฑ„๋„์„ ๊ตฌ๋…ํ•˜๋Š” ๋ชจ๋“  ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค.

3. ๋ฉ”์‹œ์ง€ ๊ตฌ๋…

์„œ๋ฒ„๋Š” roomUpdate ์ฑ„๋„์„ ๊ตฌ๋…ํ•˜๊ณ , ๊ฒŒ์ž„ ๋ฐฉ์˜ ์ƒํƒœ ๋ณ€ํ™”๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๊ฐ์ง€ํ•˜์—ฌ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์ „์†กํ•ฉ๋‹ˆ๋‹ค. RoomController์—์„œ๋Š” RedisService๋ฅผ ํ†ตํ•ด ์ฑ„๋„์„ ๊ตฌ๋…ํ•˜๊ณ , roomUpdateSubject๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜์—ฌ SSE๋ฅผ ํ†ตํ•ด ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์—…๋ฐ์ดํŠธ๋ฅผ ์ „์†กํ•ฉ๋‹ˆ๋‹ค.

export class RoomController {
  private readonly roomUpdateSubject = new Subject<MessageEvent>();

  constructor(private readonly redisService: RedisService) {
    this.redisService.subscribeToChannel("roomUpdate", async (message) => {
      const roomKeys = await this.redisService.keys("room:*");
      const rooms = await Promise.all(
        roomKeys.map(async (key) => {
          const roomData = await this.redisService.get<string>(key);
          return JSON.parse(roomData) as RoomDataDto;
        })
      );
      this.roomUpdateSubject.next({ data: rooms });
    });
  }

  @Sse("stream")
  getRoomUpdates(): Observable<MessageEvent> {
    return this.roomUpdateSubject.asObservable();
  }
}

4. ํด๋ผ์ด์–ธํŠธ์—์„œ SSE ์ด๋ฒคํŠธ ์ˆ˜์‹ 

ํด๋ผ์ด์–ธํŠธ๋Š” EventSource API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ SSE๋ฅผ ํ†ตํ•ด ์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์‹ ํ•ฉ๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ๋Š” ์„œ๋ฒ„์™€ ์—ฐ๊ฒฐ ํ›„, ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ „์†ก๋˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„ UI๋ฅผ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.

const eventSource = new EventSource("/api/rooms/stream");

eventSource.onmessage = (event) => {
  const update = JSON.parse(event.data);
  updateRoomList(update); // UI ์—…๋ฐ์ดํŠธ
};

WebSocket ๋Œ€์‹  SSE๋ฅผ ์„ ํƒํ•œ ์ด์œ 

1. ๋‹จ์ˆœ์„ฑ

WebSocket์€ ์–‘๋ฐฉํ–ฅ ํ†ต์‹ ์— ์œ ์šฉํ•˜์ง€๋งŒ, ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ฐ์ดํ„ฐ ์ „์†ก๋งŒ ํ•„์š”ํ•  ๋•Œ๋Š” SSE๊ฐ€ ๋” ๊ฐ„๋‹จํ•˜๊ณ  ํšจ์œจ์ ์ž…๋‹ˆ๋‹ค.

2. ๋ธŒ๋ผ์šฐ์ € ํ˜ธํ™˜์„ฑ

SSE๋Š” HTTP ๊ธฐ๋ฐ˜์ด๋ฏ€๋กœ ๋Œ€๋ถ€๋ถ„์˜ ๋ธŒ๋ผ์šฐ์ €์—์„œ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ง€์›๋˜๋ฉฐ, ์„ค์ •์ด ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด, WebSocket์€ ๋ฐฉํ™”๋ฒฝ์ด๋‚˜ ๋„คํŠธ์›Œํฌ ์„ค์ •์— ๋”ฐ๋ผ ์ฐจ๋‹จ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

3. ์—ฐ๊ฒฐ ํšจ์œจ์„ฑ

WebSocket์€ ๋ชจ๋“  ํด๋ผ์ด์–ธํŠธ์™€์˜ ์—ฐ๊ฒฐ์„ ์œ ์ง€ํ•ด์•ผ ํ•˜๋ฏ€๋กœ, ๋‹ค์ˆ˜์˜ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋™์ผํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•  ๋•Œ SSE๊ฐ€ ๋” ํšจ์œจ์ ์ž…๋‹ˆ๋‹ค.


์ ์šฉ ๊ฒฐ๊ณผ

1๏ธโƒฃ ์‹ค์‹œ๊ฐ„ ๋ฐฉ ๋ชฉ๋ก ์—…๋ฐ์ดํŠธ

  • ๋ฐฉ ์ƒ์„ฑ, ์‚ญ์ œ, ์‚ฌ์šฉ์ž์˜ ์ด๋™ ๋“ฑ์ด ์ฆ‰์‹œ ๋ฐ˜์˜๋˜์–ด ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์ด ํฌ๊ฒŒ ํ–ฅ์ƒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

2๏ธโƒฃ ์„œ๋ฒ„ ํšจ์œจ์„ฑ ํ–ฅ์ƒ

  • ๊ธฐ์กด์˜ HTTP REST ๋ฐฉ์‹์—์„œ๋Š” ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ฃผ๊ธฐ์ ์œผ๋กœ ์„œ๋ฒ„์— ์š”์ฒญ์„ ๋ณด๋‚ด์•ผ ํ–ˆ์ง€๋งŒ, SSE์™€ Redis Pub/Sub๋ฅผ ํ†ตํ•ด ์„œ๋ฒ„๋Š” ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋งŒ ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•˜๊ณ , ํด๋ผ์ด์–ธํŠธ๋Š” ์‹ค์‹œ๊ฐ„์œผ๋กœ ์—…๋ฐ์ดํŠธ๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๋งˆ๋ฌด๋ฆฌํ•˜๋ฉฐ

Redis Pub/Sub์™€ SSE๋ฅผ ํ™œ์šฉํ•œ ๊ฒŒ์ž„ ๋ฐฉ ๋ชฉ๋ก์˜ ์‹ค์‹œ๊ฐ„ ์—…๋ฐ์ดํŠธ ์‹œ์Šคํ…œ์€ ์•ˆ๋…•! ํด๋กœ๋ฐ”ํŒŒํŠธ๋ผ! ๊ฒŒ์ž„์˜ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ํฌ๊ฒŒ ํ–ฅ์ƒ์‹œ์ผฐ์Šต๋‹ˆ๋‹ค. ์•ž์œผ๋กœ๋„ ๋‹ค์–‘ํ•œ ์‹ค์‹œ๊ฐ„ ๊ธฐ์ˆ ์„ ํ™œ์šฉํ•˜์—ฌ ๋” ๋‚˜์€ ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋„๋ก ๋…ธ๋ ฅํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๐Ÿ˜Š

์ฐธ๊ณ  ์ž๋ฃŒ

์•ˆ๋…•! ํด๋กœ๋ฐ”ํŒŒํŠธ๋ผ

ํŒ€ ๋ฌธํ™”

๐Ÿค Ground Rule

ํ˜‘์—… ๋ฐฉ์‹

๐Ÿ”’ Convention
๐ŸŒณ Git Branch ์ „๋žต

๊ฐœ๋ฐœ ๋ฌธ์„œ

๐Ÿ› ๏ธ AGT - Automatic Git & Github Tool
๐Ÿ“Š WebRTC Mesh โ€ ํŠธ๋ž˜ํ”ฝ ๊ณ„์‚ฐ
๐ŸŽข WebRTC Mesh - ํ—˜๋‚œํ•œ ์—ฌ์ •
๐Ÿ’ฌ WebRTC๋ฅผ ์•Œ์•„๋ณด์ž
๐Ÿ“ฎ SSE(Server Sent Events)
๐Ÿ“– SSE Pagination
โณ Socket ํ†ต์‹ ์—์„œ ๋น„๋™๊ธฐ ์ž‘์—… ์ˆœ์„œ ๋ณด์žฅ ๋ฐฉ๋ฒ•
๐Ÿ“ก Redis pub/sub๋ฅผ ํ™œ์šฉํ•œ SSE ์ ์šฉ๊ธฐ
๐Ÿ—๏ธ Naver Cloud Platform์„ ํ™œ์šฉํ•œ ๋ฐฐํฌ ์ „๋žต
โš”๏ธ๐Ÿš€ ๋ถ€ํ•˜ ํ…Œ์ŠคํŠธ: ๋‹จ์ผ ์ธ์Šคํ„ด์Šค VS NKS
๐Ÿšดโ€โ™€๏ธ Redis๋กœ ๊ฒŒ์ž„๋ฐฉ ๊ด€๋ฆฌ ์ตœ์ ํ™”: ํšจ์œจ์ ์ธ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ์™€ ์„ฑ๋Šฅ ๊ฐœ์„ 

ํšŒ์˜๋ก

๐Ÿ“† ํšŒ์˜๋ก ์บ˜๋ฆฐ๋”
๐Ÿ–ค ๋ฐ์ผ๋ฆฌ ์Šคํฌ๋Ÿผ ํ…œํ”Œ๋ฆฟ
๐Ÿ–ค ํšŒ๊ณ  ํ…œํ”Œ๋ฆฟ

๋ฉ˜ํ† ๋ง

0๏ธโƒฃ 0์ฃผ์ฐจ ๋ฉ˜ํ† ๋ง ์ผ์ง€
1๏ธโƒฃ 1์ฃผ์ฐจ ๋ฉ˜ํ† ๋ง ์ผ์ง€
2๏ธโƒฃ 2์ฃผ์ฐจ ๋ฉ˜ํ† ๋ง ์ผ์ง€
3๏ธโƒฃ 3์ฃผ์ฐจ ๋ฉ˜ํ† ๋ง ์ผ์ง€
4๏ธโƒฃ 4์ฃผ์ฐจ ๋ฉ˜ํ† ๋ง ์ผ์ง€

๋ฐœํ‘œ

0๏ธโƒฃ 0์ฃผ์ฐจ ๋ฐœํ‘œ
1๏ธโƒฃ 1์ฃผ์ฐจ ๋ฐœํ‘œ
2๏ธโƒฃ 2์ฃผ์ฐจ ๋ฐœํ‘œ
3๏ธโƒฃ 3์ฃผ์ฐจ ๋ฐœํ‘œ
4๏ธโƒฃ 4์ฃผ์ฐจ ๋ฐœํ‘œ
5๏ธโƒฃ ์ตœ์ข… ๋ฐœํ‘œ

Clone this wiki locally