์‚ฌ์ด๋“œ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋ฉด์„œ ์‹ค์‹œ๊ฐ„ ์•Œ๋ฆผ์„ ๋ณด๋‚ด๋Š” ๊ธฐ๋Šฅ์„ ๊ฒŒ๋ฐœํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค.

๊ฐ„๋‹จํžˆ ์„ค๋ช…์„ ํ•˜์ž๋ฉด,,์ผ์ •์„ ๋“ฑ๋กํ•˜๋ฉด ์‡ผํ˜ธ์ŠคํŠธ์—๊ฒŒ ๋ฐ”๋กœ ์•Œ๋ฆผ์ด ๊ฐ€์•ผ ํ•˜๊ณ , ํŒŒ์ผ ์—…๋กœ๋“œ๋‚˜ ์ƒํƒœ ๋ณ€๊ฒฝ๋„ ์ฆ‰์‹œ ๋ฐ˜์˜๋˜์–ด์•ผ ํ•˜๋Š” ์ƒํ™ฉ์ด๋‹ค.

์ด๋ฒˆ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ๋‹จ์ˆœ SSE ๊ตฌ์กฐ๋ฅผ ๋„˜์–ด Redis๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜์—ฌ
์„œ๋ฒ„ ๊ฐ„์—๋„ ์•Œ๋ฆผ์ด ์ „๋‹ฌ๋  ์ˆ˜ ์žˆ๋„๋ก ๊ตฌ์„ฑํ•˜์˜€๋‹ค.

๋น„๋™๊ธฐ ์ด๋ฒคํŠธ ํ‘ธ์‹œ ๋ฐฉ์‹์œผ๋กœ ์ ์šฉ์„ ํ•˜์˜€๋Š”๋ฐ ์ด์— ๋Œ€ํ•ด ์ •๋ฆฌ ํ•ด๋ณด์ž ํ•œ๋‹ค.


๋น„๋™๊ธฐ ์ด๋ฒคํŠธ ํ‘ธ์‹œ?

์ผ๋ฐ˜์ ์ธ ์›น ํ†ต์‹ ์€ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ  ์„œ๋ฒ„๊ฐ€ ์‘๋‹ต์„ ์ฃผ๋Š” ๊ตฌ์กฐ๋‹ค.

ํด๋ผ์ด์–ธํŠธ โ†’ ์š”์ฒญ โ†’ ์„œ๋ฒ„ โ†’ ์‘๋‹ต โ†’ ๋

์ด๋Ÿฌํ•œ ํ๋ฆ„์ด ๊ธฐ๋ณธ์ด์ง€๋งŒ, ์‹ค์‹œ๊ฐ„ ์•Œ๋ฆผ ๊ฐ™์€ ๊ฒฝ์šฐ๋Š” ์ข€ ๋‹ค๋ฅด๋‹ค.

ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ณ„์† ์š”์ฒญ์„ ๋ณด๋‚ด๋Š”๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ์„œ๋ฒ„์—์„œ ์ด๋ฒคํŠธ์— ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์•Œ๋ ค์ค˜์•ผํ•œ๋‹ค.

์ด๋ฒˆ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ๊ด€๋ฆฌ์ž๊ฐ€ ์ผ์ •์„ ๋“ฑ๋กํ–ˆ์„ ๋•Œ, ํŒŒ์ผ ์—…๋กœ๋“œ ์‹œ์— (์ด๋Ÿฌํ•œ ์ด๋ฒคํŠธ ์ƒํ™ฉ์—) ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ฌผ์–ด๋ณด์ง€ ์•Š์•„๋„ ์„œ๋ฒ„๊ฐ€ ๋จผ์ € ์•Œ๋ ค์ค˜์•ผํ•œ๋‹ค.

์ด๊ฑธ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ด์ฃผ๋Š”๊ฒŒ ๋น„๋™๊ธฐ ์ด๋ฒคํŠธ ํ‘ธ์‹œ ๋ฐฉ์‹์ด๋‹ค.

ํด๋ผ์ด์–ธํŠธ โ†’ ์—ฐ๊ฒฐ ์œ ์ง€
์„œ๋ฒ„ โ†’ ์ด๋ฒคํŠธ ๋ฐœ์ƒ โ†’ ํด๋ผ์ด์–ธํŠธ๋กœ push

์ด๋Ÿฌํ•œ ๊ตฌ์กฐ์ด๋ฉฐ, ์š”์ฒญ ๊ธฐ๋ฐ˜์ด ์•„๋‹ˆ๋ผ ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜์œผ๋กœ ๋™์ž‘ํ•˜๋Š” ํ†ต์‹  ๋ฐฉ์‹์ด๋‹ค.


์„ ํƒ์ง€

Polling : ๊ณ„์† ์š”์ฒญํ•จ (๋น„ํšจ์œจ)

WebSocket : ์–‘๋ฐฉํ–ฅ (๋ฌด๊ฒ๊ณ  ๋ณต์žก)

SSE : ์„œ๋ฒ„ โ†’ ํด๋ผ ๋‹จ๋ฐฉํ–ฅ (๊ฐ€๋ณ๊ณ  ์‰ฌ์›€)

๋น„๋™๊ธฐ ์ด๋ฒคํŠธ ํ‘ธ์‹œ ๋ฐฉ์‹์—๋Š” ์ด๋ ‡๊ฒŒ ์ด 3๊ฐ€์ง€์˜ ์„ ํƒ์ง€๊ฐ€ ์žˆ๋‹ค.


Polling

Polling์€ ์ผ์ • ์ฃผ๊ธฐ๋งˆ๋‹ค ์„œ๋ฒ„์— ๊ณ„์† ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๋ฐฉ์‹์ด๋‹ค.

์•Œ๋ฆผ ์žˆ์–ด? โ†’ ์—†์Œ  
์•Œ๋ฆผ ์žˆ์–ด? โ†’ ์—†์Œ  
์•Œ๋ฆผ ์žˆ์–ด? โ†’ ์—†์Œ
...

์ด๋Ÿฌํ•œ ๊ณผ์ •์„ ๊ณ„์† ๋ฐ˜๋ณตํ•˜๋Š”๋ฐ, ์ด ๋ฐฉ์‹์€ ์„œ๋ฒ„์— ๋ถˆํ•„์š”ํ•œ ์š”์ฒญ์ด ๊ณ„์† ๋“ค์–ด๊ฐ€๊ณ  ๋„คํŠธ์›Œํฌ ๋‚ญ๋น„๊ฐ€ ์‹ฌํ•ด์„œ ์ œ์™ธํ–ˆ๋‹ค.


WebSocket

WebSocket์€ ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„๊ฐ€ ์„œ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ์–‘๋ฐฉํ–ฅ ํ†ต์‹  ๋ฐฉ์‹์ด๋‹ค.

ํ•œ ๋ฒˆ ์—ฐ๊ฒฐ์„ ๋งบ์œผ๋ฉด ์ดํ›„์—๋Š” HTTP ์š”์ฒญ/์‘๋‹ต ๊ณผ์ • ์—†์ด ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.

ํด๋ผ์ด์–ธํŠธ โ†” ์„œ๋ฒ„ (์–‘๋ฐฉํ–ฅ)

์ด๋Ÿฌํ•œ ๊ตฌ์กฐ์ด๋ฉฐ ์ฑ„ํŒ…, ๊ฒŒ์ž„, ์‹ค์‹œ๊ฐ„ ํ˜‘์—…์ฒ˜๋Ÿผ ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„๊ฐ€ ์„œ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ณ„์† ์ฃผ๊ณ ๋ฐ›์•„์•ผํ•˜๋Š” ๊ฒฝ์šฐ์— ์ ํ•ฉํ•˜๋‹ค.

ํ•˜์ง€๋งŒ ๋ณ„๋„์˜ ํ”„๋กœํ† ์ฝœ(ws://) ์‚ฌ์šฉ, ์—ฐ๊ฒฐ ๊ด€๋ฆฌ ํ•„์š”, ์„ค์ •๊ณผ ๊ตฌํ˜„์ด ๋ณต์žกํ•˜๋‹ค๋Š” ํŠน์ง•์œผ๋กœ ์ธํ•ด ๋‹จ์ˆœ ์•Œ๋ฆผ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๊ธฐ์— ๊ณผํ•˜๋‹ค๊ณ  ํŒ๋‹จํ•˜์—ฌ ์ œ์™ธํ•˜์˜€๋‹ค.


SSE

SSE(Server-Sent Events)๋Š” ์„œ๋ฒ„์—์„œ ํด๋ผ์ด์–ธํŠธ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด๋Š” ๋‹จ๋ฐฉํ–ฅ ํ†ต์‹  ๋ฐฉ์‹์ด๋‹ค.

HTTP ๊ธฐ๋ฐ˜์œผ๋กœ ๋™์ž‘ํ•˜๋ฉฐ, ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํ•œ ๋ฒˆ ์š”์ฒญ์„ ๋ณด๋‚ด๋ฉด ์„œ๋ฒ„๋Š” ์—ฐ๊ฒฐ์„ ๋Š์ง€ ์•Š๊ณ  ์œ ์ง€ํ•˜๋ฉด์„œ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ๋งˆ๋‹ค ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•œ๋‹ค.

ํด๋ผ์ด์–ธํŠธ -------- ์—ฐ๊ฒฐ ์œ ์ง€ -------- ์„œ๋ฒ„

             (๋Š๊ธฐ์ง€ ์•Š๋Š” HTTP)

์„œ๋ฒ„ โ†’ ์ด๋ฒคํŠธ ๋ฐœ์ƒ โ†’ ํด๋ผ์ด์–ธํŠธ๋กœ push

WebSocket๊ณผ ๋น„๊ตํ–ˆ์„ ๋•Œ ๋ณ„๋„์˜ ํ”„๋กœํ† ์ฝœ์ด ์•„๋‹ˆ๋ผ HTTP๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ๊ตฌํ˜„์ด ๊ฐ„๋‹จํ•˜๋ฉฐ, ์„œ๋ฒ„์—์„œ ํด๋ผ์ด์–ธํŠธ ์•Œ๋ฆผ์— ์ตœ์ ํ™”๋œ๋‹ค๋Š” ์žฅ์ ์ด์žˆ๋‹ค.

์ด๋ฒˆ ํ”„๋กœ์ ํŠธ์—๋Š” ์ผ์ • ์ƒ์„ฑ, ํŒŒ์ผ ์—…๋กœ๋“œ ์‹œ ์•Œ๋ฆผ์ด๋ผ๋Š” ์„œ๋ฒ„์—์„œ ํด๋ผ์ด์–ธํŠธ๋กœ ์ด๋ฒคํŠธ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์ด๋ผ (ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์„œ๋ฒ„๋กœ ์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ผ ํ•„์š”๋Š” ์—†๋‹ค) SSE๋กœ ์„ ํƒ์„ ํ•˜์˜€๋‹ค.


SSE ๊ตฌ์กฐ์˜ ํ•œ๊ณ„

๊ธฐ๋ณธ์ ์ธ SSE ๊ตฌ์กฐ๋Š” ์„œ๋ฒ„๊ฐ€ 1๋Œ€์ผ ๊ฒฝ์šฐ์—๋Š” ๋ฌธ์ œ๊ฐ€ ์—†์ง€๋งŒ, ์„œ๋ฒ„๊ฐ€ ์—ฌ๋Ÿฌ ๋Œ€๋กœ ํ™•์žฅ๋˜๋Š” ๊ฒฝ์šฐ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

A ์„œ๋ฒ„์—์„œ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜์˜€๋Š”๋ฐ, B ์„œ๋ฒ„์— ํด๋ผ์ด์–ธํŠธ ์—ฐ๊ฒฐ์ด ์กด์žฌํ•œ๋‹ค๊ณ  ์˜ˆ๋ฅผ ๋“ค์–ด๋ณด์ž,,

์ด ๊ฒฝ์šฐ A์—์„œ ๋ฐœ์ƒํ•œ ์•Œ๋ฆผ์€ B์— ์ „๋‹ฌ๋˜์ง€ ์•Š๋Š”๋‹ค,,์„œ๋ฒ„๊ฐ€ 2๊ฐœ ์ด์ƒ๋ถ€ํ„ฐ๋Š” ๊ทธ๋ ‡๋‹ค.

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด Redis๋ฅผ ์ถ”๊ฐ€ํ•˜์˜€๋‹ค.


Redis

Redis๋Š” ์ธ๋ฉ”๋ชจ๋ฆฌ ๊ธฐ๋ฐ˜์˜ ๋ฐ์ดํ„ฐ ์ €์žฅ์†Œ๋กœ, ๋น ๋ฅธ ์†๋„๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์บ์‹œ, ์„ธ์…˜ ์ €์žฅ, ๋ฉ”์‹œ์ง€ ๋ธŒ๋กœ์ปค๋กœ ๋งŽ์ด ์‚ฌ์šฉ๋œ๋‹ค.

์ด๋ฒˆ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ์šฉ๋„๊ฐ€ ์•„๋‹ˆ๋ผ ์„œ๋ฒ„ ๊ฐ„ ๋ฉ”์‹œ์ง€๋ฅผ ์ „๋‹ฌํ•˜๊ธฐ ์œ„ํ•œ ์—ญํ• ๋กœ ์‚ฌ์šฉํ•˜์˜€๋‹ค.

๊ธฐ๋ณธ์ ์ธ SSE ๊ตฌ์กฐ์—์„œ๋Š” ์„œ๋ฒ„๊ฐ€ 1๋Œ€์ผ ๊ฒฝ์šฐ ๋ฌธ์ œ๊ฐ€ ์—†์ง€๋งŒ, ์„œ๋ฒ„๊ฐ€ ์—ฌ๋Ÿฌ ๋Œ€๋กœ ๋Š˜์–ด๋‚˜๋Š” ์ˆœ๊ฐ„ ์•Œ๋ฆผ ์ „๋‹ฌ์ด ๋Š๊ธฐ๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด Redis์˜ Pub/Sub ๊ตฌ์กฐ๋ฅผ ํ™œ์šฉํ•˜์˜€๋‹ค.

Publisher โ†’ Redis โ†’ Subscriber

Publisher : ์ด๋ฒคํŠธ ๋ฐœ์ƒ ์‹œ ๋ฉ”์‹œ์ง€ ๋ฐœํ–‰
Redis : ๋ฉ”์‹œ์ง€๋ฅผ ์ค‘๊ฐ„์—์„œ ์ „๋‹ฌ
Subscriber : ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›์•„ ์ฒ˜๋ฆฌ

์œ„ ๊ตฌ์กฐ๋ฅผ ํ†ตํ•ด ์–ด๋–ค ์„œ๋ฒ„์—์„œ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋”๋ผ๋„ ๋ชจ๋“  ์„œ๋ฒ„๊ฐ€ ๋™์ผํ•œ ๋ฉ”์‹œ์ง€๋ฅผ ์ „๋‹ฌ๋ฐ›์œผ๋ฉฐ, ๊ฐ ์„œ๋ฒ„๋Š” ์ž์‹ ์ด ๊ฐ€์ง€๊ณ  ์žˆ๋Š” SSE ์—ฐ๊ฒฐ์„ ํ†ตํ•ด ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์•Œ๋ฆผ์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

์ฆ‰ Redis๋ฅผ ํ†ตํ•ด ์„œ๋ฒ„ ๊ฐ„ ์˜์กด์„ฑ ์ œ๊ฑฐ, ํ™•์žฅ ๊ฐ€๋Šฅํ•œ ๊ตฌ์กฐ, ์•ˆ์ •์ ์ธ ์•Œ๋ฆผ ์ „๋‹ฌ+๋น ๋ฆ„..์ด๋ ‡๊ฒŒ 3๊ฐ€์ง€๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.


SSE ๊ตฌํ˜„

SSE๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด ํฌ๊ฒŒ 3๊ฐ€์ง€ ๊ตฌ์„ฑ์œผ๋กœ ๋‚˜๋ˆ„์–ด ์„ค๊ณ„ํ•˜์˜€๋‹ค.

1. Emitter ์ €์žฅ์†Œ

Emitter : ์„œ๋ฒ„๊ฐ€ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๊ณ„์† ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด๊ธฐ ์œ„ํ•œ ์—ฐ๊ฒฐ ํ†ต๋กœ

SSE๋Š” ์‚ฌ์šฉ์ž๋งˆ๋‹ค ์—ฐ๊ฒฐ์ด ์œ ์ง€๋˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ ์‚ฌ์šฉ์ž๋ณ„ ์—ฐ๊ฒฐ์„ ์ €์žฅํ•  ๊ณต๊ฐ„์ด ํ•„์š”ํ•˜๋‹ค.

์ด๋ฅผ ์œ„ํ•ด SseEmitter๋ฅผ Map ํ˜•ํƒœ๋กœ ๊ด€๋ฆฌํ•˜์˜€๋‹ค.

private final Map<Long, SseEmitter> emitters = new ConcurrentHashMap<>();

key๋Š” ์‚ฌ์šฉ์ž ID, value๋Š” ํ•ด๋‹น ์‚ฌ์šฉ์ž์˜ SSE ์—ฐ๊ฒฐ ๊ฐ์ฒด์ด๋‹ค. ์ด ๊ตฌ์กฐ๋ฅผ ํ†ตํ•ด ํŠน์ • ์‚ฌ์šฉ์ž์—๊ฒŒ ์•Œ๋ฆผ์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

2. SSE ์—ฐ๊ฒฐ ์ƒ์„ฑ

ํด๋ผ์ด์–ธํŠธ๊ฐ€ SSE ์—ฐ๊ฒฐ์„ ์‹œ์ž‘ํ•˜๋Š” API์ด๋‹ค.

@GetMapping("/subscribe")
public SseEmitter subscribe(...) {
    return notificationService.connect(memberId);
}
SseEmitter emitter = new SseEmitter(60 * 60 * 1000L);
emitterRepository.save(memberId, emitter);

ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ด API๋ฅผ ํ•œ ๋ฒˆ ํ˜ธ์ถœํ•˜๋ฉด ์„œ๋ฒ„์™€์˜ ์—ฐ๊ฒฐ์ด ์œ ์ง€๋˜๋ฉฐ, ์ดํ›„์—๋Š” ๋ณ„๋„์˜ ์š”์ฒญ ์—†์ด๋„ ์ด๋ฒคํŠธ๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.

3. ์ด๋ฒคํŠธ ๋ฐœ์ƒ

์ผ์ • ์ƒ์„ฑ, ํŒŒ์ผ ์—…๋กœ๋“œ ๋“ฑ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์ฆ‰์‹œ Redis๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ์ „๋‹ฌํ•œ๋‹ค.

notificationPublisher.publish(notification);

์ด ์‹œ์ ์—์„œ Notification ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ ๋’ค, Redis๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐœํ–‰ํ•œ๋‹ค.

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

4. Redis Publisher

redisTemplate.convertAndSend("notification", json);

Notification ๊ฐ์ฒด๋ฅผ JSON์œผ๋กœ ๋ณ€ํ™˜ํ•œ ๋’ค โ€œnotificationโ€ ์ฑ„๋„๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐœํ–‰ํ•œ๋‹ค.

์ด๋•Œ Redis๋Š” ํ•ด๋‹น ์ฑ„๋„์„ ๊ตฌ๋…ํ•˜๊ณ  ์žˆ๋Š” ๋ชจ๋“  ์„œ๋ฒ„์—๊ฒŒ ๋ฉ”์‹œ์ง€๋ฅผ ์ „๋‹ฌํ•˜๊ฒŒ ๋œ๋‹ค.

5. Redis Subscriber

Redis์—์„œ ๋ฉ”์‹œ์ง€๋ฅผ ์ˆ˜์‹ ํ•˜์—ฌ ์‹ค์ œ SSE๋กœ ์ „๋‹ฌํ•˜๋Š” ์—ญํ• ์ด๋‹ค.

java

public void onMessage(Message message, byte[] pattern) {
    String body = new String(message.getBody());
    Notification notification =
        objectMapper.readValue(body, Notification.class);
    SseEmitter emitter =
        emitterRepository.get(notification.getMemberId());
    if (emitter != null) {
        emitter.send(
            SseEmitter.event()
                .name("notification")
                .data(notification)
        );
    }
}

Redis์—์„œ ๋ฉ”์‹œ์ง€๋ฅผ ์ˆ˜์‹ ํ•˜๋ฉด JSON ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•œ ๋’ค, ํ•ด๋‹น ์‚ฌ์šฉ์ž์— ๋Œ€ํ•œ SSE ์—ฐ๊ฒฐ(emitter)์„ ์กฐํšŒํ•œ๋‹ค.

์—ฌ๊ธฐ์„œ ํ•ด๋‹น ์—ฐ๊ฒฐ์ด ์กด์žฌํ•  ๊ฒฝ์šฐ ๊ทธ emitter๋ฅผ ํ†ตํ•ด ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์•Œ๋ฆผ์„ ์ „์†กํ•œ๋‹ค.

Redis โ†’ ์„œ๋ฒ„ โ†’ ์‚ฌ์šฉ์ž emitter โ†’ ํด๋ผ์ด์–ธํŠธ

์ด ํ๋ฆ„์œผ๋กœ ์‹ค์ œ ์•Œ๋ฆผ์ด ์ „๋‹ฌ๋œ๋‹ค.


์ „์ฒด ํ๋ฆ„

1. ํด๋ผ์ด์–ธํŠธ โ†’ /subscribe ์š”์ฒญ (SSE ์—ฐ๊ฒฐ ์ƒ์„ฑ)
2. ์„œ๋ฒ„ โ†’ ์‚ฌ์šฉ์ž๋ณ„ emitter ์ €์žฅ
3. ๊ด€๋ฆฌ์ž โ†’ ์ผ์ • ์ƒ์„ฑ (์ด๋ฒคํŠธ ๋ฐœ์ƒ)
4. ์„œ๋ฒ„ โ†’ Redis Publisher ํ˜ธ์ถœ
5. Redis โ†’ ๋ฉ”์‹œ์ง€ ์ „๋‹ฌ
6. Redis Subscriber โ†’ ๋ฉ”์‹œ์ง€ ์ˆ˜์‹ 
7. ์„œ๋ฒ„ โ†’ ํŠน์ • ์‚ฌ์šฉ์ž emitter ์กฐํšŒ
8. SSE๋กœ ์•Œ๋ฆผ push
9. ํด๋ผ์ด์–ธํŠธ โ†’ ์‹ค์‹œ๊ฐ„ ์•Œ๋ฆผ ์ˆ˜์‹ 

์ฆ‰, SSE๋ฅผ ํ†ตํ•ด ํด๋ผ์ด์–ธํŠธ์™€์˜ ์—ฐ๊ฒฐ์„ ์œ ์ง€ํ•˜๊ณ , Redis Pub/Sub์„ ํ†ตํ•ด ์„œ๋ฒ„ ๊ฐ„ ๋ฉ”์‹œ์ง€๋ฅผ ์ „๋‹ฌํ•˜๋ฉฐ ํ™•์žฅ ๊ฐ€๋Šฅํ•œ ์‹ค์‹œ๊ฐ„ ์•Œ๋ฆผ ๊ตฌ์กฐ๋ฅผ ๊ตฌ์„ฑํ•˜์˜€๋‹ค.