
πͺ Redis Pub / Sub μ€κ³
μ€μκ° μλ¦Ό μμ€ν μ μ€κ³ν λ κ°μ₯ μ€μν μμ μ€ νλλ
μ¬μ©μμκ² μ¦κ°μ μΌλ‘ λ©μΈμ§λ₯Ό μ λ¬νλ λ°©λ²μ μ ννλ κ²μ΄λ€.
μ΄λ₯Ό μν΄μλ λ€μν κΈ°μ μ΄ μ‘΄μ¬νκ² μ§λ§,
λ΄κ° μ§ννλ νλ‘μ νΈμμλ Redisμ Pub / Sub κΈ°λ₯μ μ΄μ©ν΄μ μλ² κ° λ©μμ§λ₯Ό μ€κ³νκ³ ,
ν΄λΌμ΄μΈνΈμκ²λ WeSocketμ ν΅ν΄ μ€μκ° μλ¦Όμ μ λ¬νλ ꡬ쑰λ₯Ό μ¬μ©νλ€.
μ¬κΈ°μ ν΅μ¬μ΄ λλ μ€κ³ μμλ Redis μ±λμ κ΅¬μ± λ°©μμ΄μλλ°,
λ΄ νλ‘μ νΈμμλ notification:{userId} νμμ μ±ννλ€.
π·οΈ μ¬μ©μ λ¨μ μ±λ λ€μ΄λ°
Redisμ Pub / Sub μμ λ©μμ§λ₯Ό μ μ‘νκΈ° μν΄μλ μ±λμ μ§μ ν΄μΌ νλλ°,
μ΄λ μ±λμ μΌμ’ μ λΌμ°ν κ²½λ‘ μν μ νλ©°, λ©μμ§λ₯Ό μμ ν μ£Όμ λ₯Ό μλ―Ένλ€.
λ΄ νλ‘μ νΈμμλ μ¬μ©μλ§λ€ κ°λ³ μ±λμ λ§λ€μ΄μ£ΌκΈ° μν΄μ notification:{userId} ννμ λ€μ΄λ° κ·μΉμ μ μ©νλ€.
μ΄λ κ² μ±λ μ΄λ¦μ ꡬμ±ν μ΄μ λ μλμ κ°λ€.
λ¨Όμ , notificationμ΄λΌλ μ λμ¬λ Redisμ μ μ₯λλ ν€λ€ μ€μμ μλ¦Όκ³Ό κ΄λ ¨λ μ±λμ΄λΌλ κ²μ λͺ ννκ² κ΅¬λΆν΄μ€ μ μκΈ° λλ¬Έμ΄λ€.
Redisμλ μ’ μ’ λ€μν λλ©μΈμ ν€λ€μ΄ ν¨κ» μ μ₯λκΈ° λλ¬Έμ,
λͺ μμ μΈ prefixλ₯Ό λλ κ²μ΄ κ΄λ¦¬μ λλ²κΉ μΈ‘λ©΄μμ λμμ΄ λλ€κ³ λ°°μ κΈ° λλ¬Έμ΄λ€.
κ·Έ λ€μ : κΈ°νΈλ, Redis ν€ λ€μ΄λ° κ΄λ‘μ λ°λΌ κ³μΈ΅μ λΆλ¦¬νλ μ©λλ‘ μ¬μ©ν κ²μ΄λ©°,
{userId}λ νΉμ μ¬μ©μμ κ³ μ μλ³μμ΄λ€.
μ΄ λ°©μμ μ¬μ©νλ©΄ κ°λ³ μ¬μ©μμκ²λ§ μλ¦Όμ μ μ‘ν μ μμΌλ©°,
λΆνμν λΈλ‘λμΊμ€νΈλ₯Ό νΌν μ μμ΄μ μ±λ₯μ μΌλ‘λ μ 리νλ€κ³ νλ¨νλ€.
μ΄μ μλ²λ μλ¦Όμ μ μ‘ν λ notification:42 μ κ°μ΄ μμ λμμ΄ λλ μ¬μ©μ IDλ₯Ό ν¬ν¨ν μ±λμ μ§μ νμ¬ λ©μμ§λ₯Ό λ°ννκ² λλ κ²μ΄λ€.
π λ©μμ§ λ°νκ³Ό μμ : Redisμ WebSocket μ°κ²° ꡬ쑰
μ€μ λ‘ μλ¦Όμ μ μ‘νλ κ³Όμ μ μλμ κ°μ΄ λμνλ€.
μ¬μ©μ Aμκ² μλ¦Όμ 보λ΄μΌ ν μν©μ΄ λ°μνλ©΄,
μλ²μμλ ν΄λΉ μλ¦Ό μ 보λ₯Ό λ΄μ λ©μμ§λ₯Ό JSON νμμΌλ‘ μ§λ ¬ννκ³ ,
notification:{userId} μ±λμ λ©μμ§λ₯Ό publishνλ€.
μλ²λ Redisμ RedisMessageListenerContainerλ₯Ό ν΅ν΄ μ΄ μ±λλ€μ ꡬλ νκ³ μλλ°,
μ±λμ΄ μ¬μ©μ IDμ λ°λΌ λμ μΌλ‘ ꡬμ±λκΈ° λλ¬Έμ
μλ²λ νΉμ μ±λλ§ κ΅¬λ νλ κ²μ΄ μλλΌ
ν¨ν΄ ꡬλ (notification:*)μ ν΅ν΄ λͺ¨λ μ¬μ©μ μλ¦Ό μ±λμ ν λ²μ ꡬλ νλλ‘ μ€μ ν΄μ£Όμλ€.
μ΄ κ΅¬μ‘° λλΆμ μλ² μΈμ€ν΄μ€κ° μ¬λ¬ κ°λ‘ λμ΄λλλΌλ,
λͺ¨λ μΈμ€ν΄μ€κ° λμΌν μ±λμ λν΄ λ©μμ§λ₯Ό λ°μ μ μμΌλ©°,
μ΄λ₯Ό ν΅ν΄ μν νμ₯μ±μ ν보ν μ μμλ€.
μ΄μ κ° μλ²λ μμ μκ² μ°κ²°λ ν΄λΌμ΄μΈνΈ WebSocket μΈμ μ€μμ
μμ λμ μ¬μ©μμ μΌμΉνλ μΈμ μ΄ μμ κ²½μ°
ν΄λΉ μ¬μ©μμκ² WebSocket λ©μμ§λ₯Ό μ μ‘νλ€.
β λ©μμ§ λ³΄μ‘΄μ±: Redisμ λ©μμ§λ₯Ό μ μ₯νμ§ μμ μ΄μ
Redis Pub / Subμ λ©μμ§λ₯Ό μμ μμκ² μ λ¬ν ν, ν΄λΉ λ©μμ§λ₯Ό μ μ₯νμ§ μλλ€.
μ¦, λ°ν λΉμ ꡬλ μ€μΈ ν΄λΌμ΄μΈνΈμκ²λ§ λ©μμ§κ° μ λ¬λκ³ , μ΄νμλ λ©μμ§κ° Redis λ΄λΆμ λ¨μ§ μλ κ²μ΄λ€.
μ΄λ Redis Pub / Subμ μ€κ³ μ² νμ΄ μ€μκ°μ±μ μ§μ€λμ΄μκΈ° λλ¬Έμ΄λ€.
λ°λΌμ λλ μλ¦Ό μ체λ λ¨Όμ RDBμ μꡬμ μΌλ‘ μ μ₯λκ³ ,
Redisλ λ¨μν μ΄λ₯Ό μ€μκ°μΌλ‘ μ λ¬νλ μ€κ³ μν μ νλλ‘ μ€κ³νμλ€.
μ΄λ₯Ό ν΅ν΄μ ν΄λΌμ΄μΈνΈκ° μ€νλΌμΈμ΄κ±°λ λ©μμ§λ₯Ό μμ νμ§ λͺ»ν κ²½μ°μλ,
μ¬μ©μλ λμ€μ μ μ‘νμ¬ RDBμμ μμ μκ² μ¨ μλ¦Ό λͺ©λ‘μ νμΈν μ μλ€.
μ΄λ κ² μμμ±κ³Ό μ€μκ°μ±μ κ°κ° λ€λ₯Έ κΈ°μ λ‘ λΆλ¦¬ν¨μΌλ‘μ¨
μμ€ν μ μμ μ±κ³Ό μ±λ₯μ λͺ¨λ ν보ν μ μμλ€ β¨
βοΈ μν νμ₯μ μν ꡬ쑰 μ€κ³
μ΄ κ΅¬μ‘°λ μλ²κ° μ¬λ¬ μΈμ€ν΄μ€λ‘ νμ₯λλλΌλ λ©μμ§ μ λ¬μ΄ λ¨μΌ λ Έλμ μμ‘΄νμ§ μλλ‘ μ€κ³λμ΄ μλ€.
λͺ¨λ μλ² μΈμ€ν΄μ€λ λμΌνκ² notification:* ν¨ν΄μ ν΅ν΄ Redis μ±λμ ꡬλ νκ³ μκΈ° λλ¬Έμ
μλ¦Όμ λ°νν μΈμ€ν΄μ€μ μκ΄μμ΄, μ¬μ©μμκ² WebSocket μΈμ μ΄ μ°κ²°λ μΈμ€ν΄μ€μμ λ©μμ§λ₯Ό λ°μ μ΅μ’ μ λ¬νκ² λλ€.
μ΄ λ°©μμ μλ² κ°μ λ³λμ μΈμ λκΈ°νλ λΈλ‘컀λ₯Ό λμ§ μκ³ λ,
μμ°μ€λ½κ² λΆμ° λ©μμ§ νκ²½μ ꡬμ±ν μ μλ€λ μ₯μ μ΄ μλ€.
μλ₯Ό λ€μ΄, μ΄λ€ μ¬μ©μκ° μΈμ€ν΄μ€ Aμ μ°κ²°λ μνμμ, μΈμ€ν΄μ€ Bκ° μλ¦Όμ λ°ννλλΌλ,
Redisκ° λ©μμ§λ₯Ό λͺ¨λ ꡬλ μμκ² μ νν΄μ£ΌκΈ° λλ¬Έμ
μΈμ€ν΄μ€ Aκ° λ©μμ§λ₯Ό μμ νκ³ , μ¬μ©μμ WebSocketμΌλ‘ μ λ¬νλ κ²μ΄ κ°λ₯ν κ²μ΄λ€.
π₯οΈ κ΅¬ν λ°©λ² μμ½
μμ μ€λͺ ν κ΅¬μ‘°λ‘ κ΅¬νν λ°©μμ λλ΅ μλμ κ°λ€.
λ©μμ§ λ°ν
redisTemplate.convertAndSend("notification:" + userId, jsonMessage);
λ©μμ§ μμ
container.addMessageListener(listener, new PatternTopic("notification:*"));
WebSocket μ μ‘
messagingTemplate.convertAndSendToUser(userId.toString(), "/notification", messageDto);
π¨οΈ Redis Streamsκ° μλ Pub / Subμ μ νν μ΄μ
μ€μκ° λ©μμ§ μ λ¬μ μν Redis κΈ°μ λ‘λ Pub / Sub μΈμλ Redis Streamsκ° μ‘΄μ¬νλ€.
κ·Έλ¬λ Redis Streamsλ λ©μμ§ λ³΄μ‘΄, μλΉμ κ·Έλ£Ή κ΄λ¦¬, μλ offset μ μ΄ λ± λ§μ κΈ°λ₯μ μ 곡νλ λμ μ
ꡬνμ΄ λ³΅μ‘νκ³ μ΄μ λΉμ©μ΄ μ¦κ°νλ€κ³ λ€μλ€.
λ΄ νλ‘μ νΈμμ ꡬνν μλ¦Ό μμ€ν μ
"μ€μκ°μΌλ‘ μ¦μ μ λ¬λλ, λ©μμ§ μ μ€ μμλ DBλ₯Ό ν΅ν΄ 볡μ κ°λ₯ν ꡬ쑰"μλ€.
λ°λΌμ λ©μμ§ λλ½ κ°λ₯μ±μ μμ€ν μ 체μ μΌλ‘ 보μν μ μμκ³ , 볡μ‘ν offset κ΄λ¦¬κ° λΆνμνλ€.
μ΄λ¬ν μꡬμ¬νμλ κ΅¬μ‘°κ° λ¨μνκ³ μ²λ¦¬ μλκ° λΉ λ₯Έ Pub / Subμ΄ ν¨μ¬ μ ν©νλ€κ³ νλ¨νκΈ°μ μ΄λ₯Ό μ μ©νκΈ°λ‘ κ²°μ νλ€.
π κ²°λ‘
μ΄μ²λΌ Redis Pub / Subμμ notification:{userId} νμμ μ±λ λ€μ΄λ°μ μ¬μ©ν κ²μ,
μ¬μ©μ λ¨μλ‘ μλ¦Όμ μ ννκ² μ λ¬νκΈ° μν μ€κ³μλ€.
λ©μμ§λ₯Ό Redisμ 보쑴νμ§ μκ³ μ€μκ°μΌλ‘λ§ μ λ¬νλ ꡬ쑰λ λ©λͺ¨λ¦¬ μ¬μ©μ μ΅μννλ©°,
μλ¦Όμ μμμ±μ λ³λμ RDBμμ μ± μμ§λλ‘ μν μ λΆλ¦¬νλ€.
λν, ν¨ν΄ κΈ°λ° κ΅¬λ (notification:*)μ μ¬μ©ν¨μΌλ‘μ¨
μλ²κ° μν νμ₯λμ΄λ λͺ¨λ μΈμ€ν΄μ€κ° λμΌν λ°©μμΌλ‘ λ©μμ§λ₯Ό μμ νκ³ μ²λ¦¬ν μ μλλ‘ κ΅¬μ±νμμΌλ©°,
WebSocketκ³Ό κ²°ν©νμ¬ ν¨μ¨μ μ΄κ³ μ€μκ°μ±μ΄ λμ μλ¦Ό μμ€ν μ μμ±ν μ μμλ€.
μ΄λ¬ν ꡬ쑰λ μ€μκ°μ±κ³Ό νμ₯μ±, λ¨μμ±μ λͺ¨λ κ³ λ €ν μ€κ³μ΄λ©°,
μ°λ¦¬μ²λΌ ν λ¨μμ μ€μ κ·λͺ¨ μλΉμ€μμ λΉ λ₯΄κ² λμ νκΈ°μ μ ν©ν λ°©μμ΄λΌκ³ νλ¨λλ€.
λ΄ μμ΄λμ΄λ₯Ό λ무λλ λ©μ§κ² μ€μ μ½λλ‘ κ΅¬νν΄μ€ νμμκ² λ€μ ν λ² λ무λλ κ°μ¬νλ€ ,, γ γ ππ»
'π» νλ‘μ νΈ > π νΈλ¬λΈμν ' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
| [νΈλ¬λΈμν ] Jest -> Vitest λ§μ΄κ·Έλ μ΄μ λ°©λ² (0) | 2025.07.05 |
|---|---|
| [νΈλ¬λΈμν ] TypeScriptμμ CSS / μ΄λ―Έμ§ import μ μ€λ₯ λ°μ (0) | 2025.06.14 |
| [νΈλ¬λΈμν ] NPMμμ PNPMμΌλ‘ (0) | 2025.06.04 |
| [νΈλ¬λΈμν ] GitHub Actionsμμ vite: not found μ€λ₯ ν΄κ²° (0) | 2025.05.23 |