[WebDev] Patterns for building realtime features
https://zknill.io/posts/patterns-for-building-realtime/?utm_source=tldrwebdev
Patterns for building realtime features
Realtime features make apps feel modern, collaborative, and up-to-date. The features predominantly require sharing changes triggered by one user to other users, as the changes are happening. This typically means your server needs to send data to some set o
zknill.io
์ค์๊ฐ ๊ธฐ๋ฅ์ ์ฑ์ ๋ ํ๋์ ์ด๊ณ , ํ์ ์ ์ด๋ฉฐ, ์ต์ ์ํ๋ก ์ ์ง๋๋๋ก ํด์ค๋ค. ์ด ๊ธฐ๋ฅ์ ์ฃผ๋ก ํ ์ฌ์ฉ์๊ฐ ๋ฐ์์ํจ ๋ณ๊ฒฝ์ ๋ค๋ฅธ ์ฌ์ฉ์๋ค์๊ฒ ์ค์๊ฐ์ผ๋ก ๊ณต์ ํ๋ ๊ฒ์ ํ์๋กํ๋ค.
์ด๊ฒ์ ์ผ๋ฐ์ ์ผ๋ก ์๋ฒ๊ฐ ํน์ ํด๋ผ์ด์ธํธ๋ค์๊ฒ ๋ฐ์ดํฐ๋ฅผ ๋ณด๋ด์ผ ํ๋๋ฐ, ๊ทธ ํด๋ผ์ด์ธํธ๋ค์ ์์ ๋ค์ด ๋ฐ์ดํฐ๋ฅผ ๋์น๊ณ ์๋ค๋ ์ฌ์ค์ ์์ง ๋ชปํ๋ ์ํฉ์ ์๋ฏธํ๋ค.
์ด ํจํด๋ค์ ์๋ฒ๊ฐ ํด๋ผ์ด์ธํธ์๊ฒ ๋ฐ์ดํฐ๋ฅผ ์๋ฆด ์ ์๋ connection์ ์์กดํ๋ค. ์ด connection์ ์น์์ผ, sse, ์ด๋ฒคํธ ์คํธ๋ฆผ ๋๋ polling์ผ ์ ์๋ค. ์ด connection์ ๋จ์ํ ํด๋ผ์ด์ธํธ๊ฐ ์๋ก์ด ๋ฐ์ดํฐ๊ฐ ์๋ค๋ ๊ฒ์ ์์ง ๋ชปํ๋ ์ํฉ์์ ์๋ฒ๊ฐ ํด๋ผ์ด์ธํธ์๊ฒ ๋ฐ์ดํฐ๋ฅผ ๋ณด๋ผ ์ ์๋ ์๋๋ก ํ๋ฉด ๋๋ค.
Patterns
Poke / Pull
`poke/pull` ์ ๊ธฐ์กด ์ฑ๊ณผ ํธํ๋ ์ ์๋ ๊ฐ์ฅ ์ฌ์ด ๋ฐฉ๋ฒ์ด๋ค. ์๋ฒ์์ update๊ฐ ์ผ์ด๋ฌ์ ๋, ์ด๋ฅผ subscribeํ๊ณ ์๋ ๋ชจ๋ ํด๋ผ์ด์ธํธ์๊ฒ ์๋ก์ด ๋ณ๊ฒฝ์ ๋ฐ์ํ๋ผ๊ณ ์๋ฆฌ๋ `poke`๊ฐ ์ ์ก๋๋ค.
ํด๋ผ์ด์ธํธ๊ฐ ์ด ์๋ฆผ์ ๋ฐ์ผ๋ฉด, ์๋ก์ด ์ํ๋ฅผ `pull`ํ๊ธฐ ์ํ ์์ฒญ์ ์๋ฒ์ ๋ณด๋ธ๋ค. poke/pull ์ ์๋ก์ด ์ํ๋ฅผ ๊ฐ์ ธ๊ฐ๊ธฐ ์ํ ์๋ ํฌ์ธํธ๋ฅผ ๊ธฐ์กด์ ์๋ ๊ฒ์ผ๋ก ํ์ฉํ ์ ์๊ธฐ ๋๋ฌธ์ ๊ธฐ์กด ์ฑ๊ณผ์ ํธํ์ ์ ๋ฆฌํ๋ค. ์ด๋ฏธ ์กด์ฌํ๋ `pull API`๋ฅผ ์ฌ์ฉํ๋ฉด ๋๊ธฐ ๋๋ฌธ์ `poke`๋ง ๊ตฌํํ๋ฉด ๋๋ค.
์ด ํจํด์ ๋ฌธ์ ์ ์ fan-out์ด๋ค. ์๋ฒ์ ํ๋์ ๋ณ๊ฒฝใ ๋ง ์ผ์ด๋๋, ๋ค์์ ํด๋ผ์ด์ธํธ์ ๋ํด fan-out์ด ์ผ์ด๋๋ค. ์ด๋ ๋ค์์ ํด๋ผ์ด์ธํธ๋ค์ด ๋์์ ์๋ฒ์ pull ์์ฒญ์ ๋ณด๋ธ๋ค๋ ๊ฒ์ ์๋ฏธํ๋ค.
๋ชจ๋ ํด๋ผ์ด์ธํธ๋ค์ด ๋์์ ์์ฒญํ๊ธฐ ๋๋ฌธ์, ์บ์ฑ์ ๋งค์ฐ ํจ๊ณผ์ ์ธ ๋ฐฉ๋ฒ์ด๋ค. ๋ฐ๋ผ์, ์๋ต์ ์บ์ฑํ๊ณ ๋ชจ๋ ํด๋ผ์ด์ธํธ์๊ฒ ๋์ผํ ์๋ต์ ์ฃผ๋ ๊ฒ์ ๋น๊ต์ ์ฝ๋ค. ํด๋ผ์ด์ธํธ๋ค์ ๊ฑฐ์ ๋์์ pulll ์์ฒญ์ ๋ณด๋ด๊ธฐ ๋๋ฌธ์, ์บ์ฑ๋ ์๋ต์ ์ถฉ๋ถํ ์ต์ ์ํ๋ฅผ ์ ์งํ ์ ์๋ค.
์๋ฒ๋ ๋ํ ์ด๋ฌํ `poke`๋ฅผ ๋ ๊ธด ์๊ฐ์ ๋๊ณ ๋ถ์ฐ์ํฌ ์ ์๋๋ฐ, ์ด๋ ๊ฒ ํ๋ฉด ๋์์ `pull` ์์ฒญ์ ๋ณด๋ด๋ ํด๋ผ์ด์ธํธ ์๋ฅผ ์ค์ผ ์ ์๋ค.
Push state
๋๋ฒ์งธ ํจํด์ `push state`์ด๋ค. ์ด ํจํด์์ ์๋ฒ๋ ์ด๋ฏธ ํด๋ผ์ด์ธํธ๊ฐ ๋ฐ์์ผํ ์ต์ ์ํ๋ฅผ ์๊ณ ์๊ธฐ ๋๋ฌธ์, ๊ทธ ์ํ๋ฅผ ํด๋ผ์ด์ธํธ์ ํธ์ํ๋ค. `poke`๋ฅผ ๋ณด๋ด๋ ๋์ , ์๋ก์ด ์ํ๋ฅผ ์ฆ์ ์๋ฒ์์ ๋ณด๋ด๋ ๊ฒ์ด๋ค.
์ด๊ฒ์ ๋ชจ๋ ํด๋ผ์ด์ธํธ๊ฐ `pull`์ ํ ํ์ ์์ด ์ฆ์ ์ ๋ฐ์ดํธ๋ ์ํ๋ฅผ ๋ฐ๊ธฐ ๋๋ฌธ์ fan-out ๋ฌธ์ ๋ฅผ ์ํ์ํจ๋ค. ์ํ๋ฅผ ํธ์ฑํ๋ ๊ฒ์ ํด๋ผ์ด์ธํธ๊ฐ ์ํ์ ๋๊ธฐํ๋์ง ์์ ๊ฐ๋ฅ์ฑ์ด ์ ๊ธฐ ๋๋ฌธ์ ๋ค๋ฃจ๊ธฐ๊ฐ ์ฝ๋ค. ๋งค๋ฒ ์ ๋ฐ์ดํธ๋ ๋๋ง๋ค ํด๋ผ์ด์ธํธ๋ ์ฌ์ฉํด์ผ ํ ์ ์ฒด ์ํ์ ์ฌ๋ณธ์ ๋ฐ๊ฒ ๋๋ฏ๋ก, ํด๋ผ์ด์ธํธ์์ ๋ฐ์ํ ๋ฒ๊ทธ๋ก ์ธํด ์ํ๊ฐ ์๊ฐ๋ฆฌ๋ ๋ฌธ์ ๊ฐ ๋น ๋ฅด๊ฒ ํด๊ฒฐ๋ ์ ์๋ค.
๊ทธ๋ฌ๋ ์ ์ฒด ์ํ๋ฅผ ํธ์ฑํ๋ ๊ฒ์ ํด๋ผ์ด์ธํธ๊ฐ ๋ณ๊ฒฝ๋ ๋ถ๋ถ์ ํ์ ํ๊ธฐ ์ด๋ ค์ธ ์ ์๋ค. ๋ํ ์์ ๋ณ๊ฒฝ์ด ์ผ์ด๋๋ ์ ์ฒด ์ํ๋ฅผ ์ฌ ์ ์กํด์ผํ๊ธฐ ๋๋ฌธ์, ๋๊ท๋ชจ ์ํ๋ฅผ ์ฒ๋ฆฌ ํ๋๋ฐ์๋ ์ ํฉํ์ง ์๋ค. ์๋ฅผ ๋ค์ด, “walk the dog”๊ฐ ์๋ฃ๋์ด์ true๋ก ๋ณ๊ฒฝ๋๋ ๊ฒฝ์ฐ์๋, ๋ชจ๋ “todos”๋ฅผ ๋ค์ ์ ์กํด์ผ ํ๋ค.
Push ops
push ops๋ ํด๋ผ์ด์ธํธ๊ฐ ์ด๋ ๋ถ๋ถ์ด ๋ณ๊ฒฝ๋์๋์ง ์ฝ๊ฒ ํ์ ํ ์ ์๋๋ก ๋์์ฃผ๋ฉฐ, ์ ์ก๋๋ ๋ฐ์ดํฐ์ ์ฌ์ด์ฆ๋ ์ค์ฌ์ค๋ค.
์ผ๋ฐ์ ์๋ก ์๋ฒ๋ ์ํ ๋ณ๊ฒฝ์ ๋ฐ์์ํค๋ ์์ ์ ๋ํด ์ดํดํ๊ณ ์์ผ๋ฉฐ, ์ด๋ฅผ ์ฐ๊ฒฐ๋ ํด๋ผ์ด์ธํธ๋ค์๊ฒ ์ ์กํ ์ ์๋ค. ์ฆ, ์๋ฒ๋ ์ ์ฒด ์ํ๋ฅผ ๋ณด๋ด๋ ๋์ ํด๋ผ์ด์ธํธ์ ์ํ๋ฅผ ์๋ฒ์ ์ํ์ ์ผ์นํ๋๋ก ์ ๋ฐ์ดํธํ ์ ์๋ ์์ (operation)์ ์ ์กํ๋ค.
์์ ์์์ ๊ฐ์ด, ์ด ์์ (operation)์ id๊ฐ 2์ธ todo ํญ๋ชฉ์ ์ํ๊ฐ `completed: true` ๋ก ๋ณ๊ฒฝ๋์์์ ๋ํ๋ธ๋ค.
๊ฐ ํด๋ผ์ด์ธํธ๋ ์ด ์์ ์ ๊ธฐ์กด ์ํ์ ๋ณํฉํ๋ค. `push state` ์์ ์ธ๊ธํ ๊ฒ ์ฒ๋ผ, ์ด๊ฒ์ ์๋ฒ๊ฐ ํด๋ผ์ด์ธํธ์ ์ํ๋ฅผ ์ ํํ ์ดํดํ๊ณ ์๋ค๋ ๊ฒ์ ์์กดํ๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ์๋ฒ๊ฐ ์์ฑํ ์์ (operation)๋ง์ผ๋ก๋ ํด๋ผ์ด์ธํธ์ ์ํ๋ฅผ ์๋ฒ์ ๋๊ธฐํ ์ํฌ ์ ์๋ค.
๋ง์ง๋ง์ผ๋ก `push ops` ๋ ํด๋ผ์ด์ธํธ๊ฐ ์์ ์ ์ ์ฉํ ์ ์๋ ์ด๊ธฐ ์ํ๋ฅผ ์ป๋ ๋งค์ปค๋์ฆ์ ์ ๊ณตํด์ผํ๋ค. ์ด๊ฒ์ ์ผ๋ฐ์ ์ผ๋ก ์ด๊ธฐ ์ํ๋ฅผ ์ค์ ํ๋ `initial` ์์ ์ ๋จผ์ ์ ๊ณตํ๊ณ , ์ดํ์ ์์ ์ด ๊ทธ ์์ ์ ์ฉ๋๋ ์์ผ๋ก ๋ชจ๋ธ๋ง๋๋ค.
Event Sourcing
`event sourcing` ์์๋ ๋ณ๊ฒฝ์ ๋ํ๋ด๋ ์์ ํน์ ์ ๋ฐ์ดํธ๋ ์ํ๋ฅผ ์ ์กํ๋ ๋์ ๋ณ๊ฒฝ์ ์ ๋ฐํ ‘์ด๋ฒคํธ’ ์์ฒด๋ฅผ ํด๋ผ์ด์ธํธ์ ์ ์กํ๋ค.
์ด ์์ ์์ ๋ณผ ์ ์๋ฏ์ด, ์ด๋ฒคํธ๋ ์ ๋ฐ์ดํธ ๋ ์ํ๋ฅผ ํฌํจํ๋ ๋์ ๋ฐ์ํ ‘์ด๋ฒคํธ’๋ฅผ ํฌํจํ๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์, ์ด ์ด๋ฒคํธ๊ฐ ๋ฌด์์ธ์ง ์๋ ๊ฒ์ ํด๋ผ์ด์ธํธ์ ์ฑ ์์ด๋ค. purists ๋ค์ ์ด๊ฒ์ด ๋ ๋์ ๋ฐ์ดํฐ ํํ ๋ฐฉ์์ด๋ผ๊ณ ์ฃผ์ฅํ์ง๋ง, ์ค์ ๋ก๋ ๊ฐ ํด๋ผ์ด์ธํธ๋ค์ด ๋์ผํ ๋น์ฆ๋์ค ๋ก์ง์ ๊ตฌํํด์ผํ๋ค๋ ๋ถ๋ด์ด ์๊ธด๋ค. ์ฆ, ์ด ์ด๋ฒคํธ๊ฐ completed ํ๋๋ฅผ true๋ก ๋ณ๊ฒฝํด์ผ ํ๋ค๋ ์๋ฏธ์์ ์ดํดํ๋ ๋ก์ง์ ๊ฐ ํด๋ผ์ด์ธํธ์์ ๊ตฌํํด์ผ ํ๋ค๋ ๊ฒ์ด๋ค.
์๋ง๋ ๋ง์ฝ ํด๋ผ์ด์ธํธ๊ฐ ๋จ์ํ ์ ๋ฐ์ดํธ๋ ์ํ๋ฅผ ํ์ํ๋ ๊ฒ ์ด์์ ๋ณต์กํ ๋ก์ง์ ๊ฐ๋ ๊ฒฝ์ฐ๋ผ๋ฉด, ์ด๋ฒคํธ๋ฅผ ๋ณด๋ด๋ ๊ฒ์ด ์ ์ฉํ ์ ์๋ค. ์ด๋ ๊ฒ ํ๋ฉด ํด๋ผ์ด์ธํธ๊ฐ completed ํ๋๊ฐ true๋ก ๋ณ๊ฒฝ๋์์์ ์ญ์ผ๋ก ํด์ํ ํ์ ์์ด, ๊ทธ์ “todo was completed”๋ผ๋ ์ด๋ฒคํธ๋ฅผ ์ง์ ๋ฐ์์ ์ฒ๋ฆฌํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
Transports
์๋ฒ์ ํด๋ผ์ด์ธํธ๋ฅผ ์ฐ๊ฒฐ๋ ์ํ๋ก ์ ์งํ๊ธฐ ์ํด ์ฌ์ฉํ ์ ์๋ ์น์์ผ, sse, ์ด๋ฒคํธ ์คํธ๋ฆผ, ์ฝ๋ฉง, ํด๋ง ๋ฑ์ ๋ค์ํ ์ ์ก๋ฐฉ์์ด ์๋ค. ๊ฐ ๋ฐฉ์์๋ ์ฅ๋จ์ ์ด ์์ง๋ง, ์ ๋ฐ์ ์ผ๋ก ๋์ผํ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ค.
๋์ดํ ๋ชจ๋ ์ ์ก ๋ฐฉ์์ HTTP์์์ ๋์ํ๋ค. ์ฆ, ์ด๋ค์ ๋ชจ๋ ์๋ฒ์ ํด๋ผ์ด์ธํธ ๊ฐ์ 1:1 ์ฐ๊ฒฐ ๋ฐฉ์์ด๋ค. ์ฆ, ํ๋์ ํด๋ผ์ด์ธํธ๋ ํ๋์ ์๋ฒ์ ์ฐ๊ฒฐ๋๋ค. ์ด์ ์๋ฒ๊ฐ ์ฌ๋ฌ๊ฐ์ `replicas` ๋ก ์ํ ํ์ฅ๋ ์์คํ ์ ์๊ฐํด๋ณด์. ์ด ๊ฒฝ์ฐ, ์ํ ๋ณ๊ฒฝ์ ์ ๋ฐํ ์ต์ด ์์ฒญ์ ์ฒ๋ฆฌํ ์๋ฒ๊ฐ ๋ชจ๋ ํด๋ผ์ด์ธํธ ์ฐ๊ฒฐ์ ๊ด๋ฆฌํ๋ ์๋ฒ์ ๋ค๋ฅผ ๊ฐ๋ฅ์ฑ์ด ์๋ค.
์ ์ด๋ฏธ์ง์๋ ๋ ๋์ ์๋ฒ `replica`๊ฐ ์๋ค. ๋ น์ ํด๋ผ์ด์ธํธ๊ฐ ๋ณ๊ฒฝ์ ์ํํ๊ณ , ์น์์ผ ์ฐ๊ฒฐ์ ํตํด ํด๋น ๋ณ๊ฒฝ ์ฌํญ์ server A์ ๊ณต์ ํ๋ฉด, server A๊ฐ ํ๋์ ํด๋ผ์ด์ธํธ์ ์ด ์ ๋ฐ์ดํธ๋ฅผ ๊ณต์ ํ๋ ๊ฒ์ ๋น๊ต์ ์ฝ๋ค. ํ์ง๋ง, server A๊ฐ ์ฃผํฉ์ ํด๋ผ์ด์ธํธ ๋ ๋ช ๊ณผ ์ด ์ ๋ฐ์ดํธ๋ฅผ ๊ณต์ ํ๋ ๊ฒ์ ์๋นํ ์ด๋ ต๋ค. ์๋ํ๋ฉด ์ด ํด๋ผ์ด์ธํธ๋ค์ server B์ ์ฐ๊ฒฐ๋์ด ์๊ธฐ ๋๋ฌธ์ด๋ค.
์ด๊ฒ์ ๋งค์ฐ ๋ฒ๊ฑฐ๋ก์ด ๋ฌธ์ ์ด๋ค. ์ผ๋ฐ์ ์ผ๋ก ์ํ ํ์ฅ๋ ์๋ฒ๋ค ๊ฐ์ ๋๊ธฐํ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ํตํด ์ด๋ฃจ์ด์ง๋ค. ํ์ง๋ง, ๊ฐ ์๋ฒ `replica`๊ฐ ๋ณ๊ฒฝ ์ฌํญ์ ๊ฐ์งํ๊ธฐ ์ํด ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ง์์ ์ผ๋ก ํด๋งํ๋ ๊ฒ์ ๋นํจ์จ ์ ์ด๋ค. `LISTEN/NOTIFY` ๊ฐ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์๋ฆผ ๋ฐฉ์์ ์ฌ์ฉํ๋ ๊ฒ๋ ์ด์์ ์ธ ํด๊ฒฐ์ฑ ์ด ์๋๋ค.
์ด๋ฐ ์ํฉ์์ Pub/Sub์ ๊ฝค ์ ์ฉํ๋ค. Pub/Sub ์์คํ ์ ์น์์ผ ์ธํ๋ผ์ ํฌ์์ด์ ๋์ ์ฒ๋ฆฌํด์ฃผ๊ธฐ ๋๋ฌธ์ด๋ค.