Cloud SLI,SLO - 100-hours-a-week/KTB4-5th-wiki GitHub Wiki
์์ฑ์ผ: 2026-09-30 ยท ์์ ์ผ: 2026-10-01
์ ์ฉ ๋ฒ์: v1 (v2ยทv3๋ 6. ํฅํ ๋ฒ์ ๊ณํ ์ฐธ๊ณ )
ํต์ฌ ์ฌ์ฉ์ ์ฌ์ ์ ํ์ง์ ์ธก์ ํ๊ณ , ๋ชฉํ ์์ค๊ณผ ์ฅ์ ๋์ ๊ธฐ์ค์ ์ ํ๊ธฐ ์ํ ๋ฌธ์์ ๋๋ค. ์ฌ์ฉ์ ๊ธฐ๋์ ์ด์ ์ฌ๊ฑด์ ๊ณ ๋ คํด ์์์ ์งํ๋ถํฐ ์์ํฉ๋๋ค.
| ๊ฐ๋ | ์๋ฏธ |
|---|---|
| CUJ(ํต์ฌ ์ฌ์ฉ์ ์ฌ์ ) | ์ฌ์ฉ์๊ฐ ์๋น์ค๋ฅผ ์ฌ์ฉํ๋ฉด์ ๋ชฉ์ ์ ๋ฌ์ฑํด ๋์๊ฐ๋ ๊ณผ์ |
| SLI(์๋น์ค ์์ค ์งํ) | ์ฌ์ฉ์ ์ฌ์ ์ ํ์ง์ ์ค์ ๋ก ์ธก์ ํ ๊ฐ |
| SLO(์๋น์ค ์์ค ๋ชฉํ) | ์ ํด์ง ๊ธฐ๊ฐ ๋์ ์งํ๊ฐ ๋ง์กฑํด์ผ ํ ์์ค |
| ์ค๋ฅ ์์ฐ | SLO๊ฐ ํ์ฉํ๋ ์คํจ ๋ฒ์๋ก, ๊ธฐ๋ฅ ๊ฐ๋ฐ๊ณผ ์์ ์ฑ ๊ฐ์ ์ ์ฐ์ ์์๋ฅผ ์ ํ๋ ๊ธฐ์ค |
๋ค๋จน์์ ํต์ฌ ์ฌ์ฉ์ ์ฌ์ ์ ์ฌ๊ณ ๋ฑ๋ก โ ์์นจ ์ ํต๊ธฐํ ์๋ฆผ โ ์ฌ๊ณ ์กฐํ โ ์ง์ ์๋น ๋๋ ์ถ์ฒ ์๋ฆฌ ํ์ฉ์ ๋๋ค.
flowchart TD
manual["์๋ ๋ฑ๋ก ยท v1"] --> inventory["์ฌ๊ณ ์ ์ฅ"]
receipt["์์์ฆ ์ดฌ์ยทAI ๋ฑ๋ก ยท v2"] --> inventory
photo["์ค๋ฌผ ์ดฌ์ยทAI ๋ฑ๋ก ยท v3"] --> inventory
inventory --> morning["์์นจ ์ ํต๊ธฐํ ์๋ฆผ ยท v1"]
morning --> gen["08:00 ์๋ฆผ ์์ฑ ยท v1"]
gen --> v1poll["v1 ยท ํด๋ง์ผ๋ก ์๋ฆผ ํ์ธ"]
gen --> v1push["v1 ยท Push ์์ "]
morning -.-> v2["v2 ยท SSE + Push, ์ฌ์ ์ ์ Catch-up"]
v1poll --> notice["์๋ฐยท๋ง๋ฃ ๋ฌผํ ํ์ธ"]
v1push --> notice
v2 -.-> notice
notice --> list["์ค๋๊น์ง์ธ ์ฌ๊ณ ์กฐํ ยท v1"]
list --> choice{"์ฌ๊ณ ํ์ฉ ๋ฐฉ๋ฒ"}
choice -->|"๋ฐ๋ก ์๋น"| direct["๊ณผ์ยท์๋ฃ ๋ฑ ์ง์ ์๋น"]
choice -->|"์๋ฆฌ์ ํ์ฉ ยท v3"| recommend["์ฌ๊ณ ๊ธฐ๋ฐ ์๋ฆฌ ์ถ์ฒ"]
recommend --> recipe["๋ ์ํผ ํ์ธยท์๋ฆฌ ์ ์ฉ"]
recipe --> consume["๋ ์ํผ ๊ธฐ์ค ์ฌ๊ณ ์๋น ์ฒ๋ฆฌ"]
classDef base fill:#e8f1ff,stroke:#4175b5,color:#172b4d;
classDef added fill:#e8f5e9,stroke:#4b8651,color:#16391a;
classDef future fill:#fff1dc,stroke:#ad7927,color:#51340a;
class manual,inventory,morning,gen,v1poll,v1push,notice,list,choice,direct base;
class receipt,v2 added;
class photo,recommend,recipe,consume future;
| ํญ๋ชฉ | ์ด์ ๊ธฐ์ค |
|---|---|
| ์๊ฐ ๊ธฐ์ค | ์๋น์ค ๋์์ ํ๊ตญ์ด๋ฉฐ, ์๋ฒ์ ์ ๋ฌด ๋ ์งยท์๊ฐ์ Asia/Seoul(KST, UTC+9) ๊ธฐ์ค์ ๋๋ค. ์ฌ์ฉ์๋ณ ์๊ฐ๋ ์ค์ ์ ์ง์ํ์ง ์์ต๋๋ค. |
| ์ ํต๊ธฐํ ๋จ๊ณ | D-3~D-day(๋น์ผ)๋ โ์๋ฐโ, ์ ํต๊ธฐํ์ด ์ง๋ ์ฌ๊ณ ๋ โ๋ง๋ฃโ์ ๋๋ค. ์ฌ๊ณ ์ํยท๋ชฉ๋ก ํํฐยท์๋ฆผ ์ ํ์ด ๋ชจ๋ ๊ฐ์ ๊ธฐ์ค์ ์ฌ์ฉํฉ๋๋ค. |
| ์์นจ ์๋ฆผ ์๊ฐ | ๋งค์ผ 08:00์ ๋ฐ์กํ๋ฉฐ, ํ์ฉ ์ง์ฐ 1๋ถ์ ๋์ด 08:01๊น์ง ์๋ฒ๊ฐ ์๋ฆผ ์์ฑยท์ ์ก์ ๋ง์น๋ฉด ์ ์๋ก ๋ด ๋๋ค. ์ฌ์ฉ์ ๊ธฐ๊ธฐ์ ์์ ์๊ฐ์ด ์๋ ์๋ฒ์ ๋ฐ์ก ์๊ฐ ๊ธฐ์ค์ ๋๋ค. |
| ์๋ฆผ ์ฑ๋ | Polling + Web Push. ํด๋ผ์ด์ธํธ๋ 30์ด๋ง๋ค ์ต์ ์๋ฆผ ID์ ๋ฏธ์ฝ์ ์๋ฅผ ์กฐํํ๊ณ , ๊ฐ์ด ๋ฐ๋๋ฉด ์๋ฆผ ๋ชฉ๋ก์ ๋ค์ ์กฐํํฉ๋๋ค(ํญ์ด ๋ฐฑ๊ทธ๋ผ์ด๋์ด๋ฉด ์ค์ง, ๋ณต๊ท ์ ์ฆ์ ์กฐํ). ๋์์ ์๋ฒ๊ฐ Web Push(VAPID ์๋ช , ํ์ค Web Push ํ๋กํ ์ฝ)๋ฅผ ๋ฐ์กํฉ๋๋ค. |
| ์๋ฆผ ๋์ | ์๋ฐยท๋ง๋ฃ ์ฌ๊ณ ๊ฐ ์๋ ๋์ฅ๊ณ ์ ํ์ฑ ๋ฉค๋ฒ์ ๋๋ค. ํํดยท๋นํ์ฑ ์ฌ์ฉ์, ๋์ฅ๊ณ ์์ ๋๊ฐ ๋ฉค๋ฒ, ์ญ์ ๋ ๋์ฅ๊ณ ๋ ๋์์ด ์๋๋๋ค. |
R = /api/v1/refrigerators/{refrigerator-id} ๋ก ์ค์ฌ ์๋๋ค. ๋๋ถ๋ถ์ API๊ฐ ๋์ฅ๊ณ ๊ฒฝ๋ก ์๋์ ์์ด ๊ฐ์ ์ ๋ ๊ฒฝ๋ก๊ฐ ๋ฐ๋ณต๋๋ฏ๋ก, ํ๋ฅผ ์งง๊ฒ ํด API๋ณ ์ฐจ์ด(๋ ๊ฒฝ๋ก)๊ฐ ์ ๋ณด์ด๊ฒ ํ๊ธฐ ์ํจ์ ๋๋ค. ๋์ ์ค์ ํธ์ถ ๊ฒฝ๋ก๋ R์ ํผ์ณ ์ฝ์ด์ผ ํฉ๋๋ค.
| ์ฌ์ฉ์ ์์ | ์ธก์ APIยท๊ธฐ๋ก | ์ฑ๊ณต ํ์ |
|---|---|---|
| ์๋ ์ฌ๊ณ ๋ฑ๋ก | POST R/ingredients | 201 |
| ์ค๋๊น์ง์ธ ์ฌ๊ณ ์กฐํ | GET R/ingredients, GET /api/v1/ingredients/{ingredient-id} | 200. ๋น์ผ ์ฌ๊ณ ๋ โ์๋ฐโ ํํฐ์ ํฌํจ |
| ์๋ฆผ ํ์ธ(ํด๋ง) | GET R/notifications/stream, GET R/notifications/unread-count, GET R/notifications | 200 |
| ์์นจ ์๋ฆผ ๋ฐ์ก | ์๋ฆผยทPush ๋ฐ์ก ๊ธฐ๋ก(์ฌ์ฉ์ ํธ์ถ API ์๋) | 3.3 ์์นจ ์๋ฆผ ํ์ ์ฐธ๊ณ |
์ฌ๋ฌ API๋ก ์ด์ด์ง๋ ์ฌ์ฉ์ ์์ ์ ํ ๊ฑด์ผ๋ก ์ง๊ณํฉ๋๋ค.
์ธก์ ํ์ง ์๋ API
- ๋จ๊ฑด ์ฌ๊ณ ๋ฑ๋ก(POST R/ingredient): API๋ ์์ง๋ง FE์์ ํธ์ถํ์ง ์์ ์ ์ ์ฌ์ฉ์์ ์ฌ์ ์ ํฌํจ๋์ง ์์ต๋๋ค. 5xx๋ ์ผ๋ฐ ์ค๋ฅ ๋ชจ๋ํฐ๋ง์ผ๋ก ํ์ธํฉ๋๋ค.
- ๋ณด์กฐ ๊ด์ธก ๋์: ์ง์ ์๋น(POST /api/v1/ingredients/{ingredient-id}), Push ๊ตฌ๋ (POST /api/v1/push-subscriptions)์ ๋ชฉํ ์์ด ์ฑ๊ณต๋ฅ ยท์๋ต์๊ฐ๋ง ๊ด์ฐฐํฉ๋๋ค.
๊ณตํต ๊ณ์ฐ ๊ธฐ์ค
- ์ฑ๊ณต๋ฅ ์ ์ฑ๊ณต ๊ฑด์ รท ํ๊ฐ ๋์ ๊ฑด์๋ก ๊ณ์ฐํฉ๋๋ค.
- ์ฌ๋ฌ ๊ตฌ๊ฐ์ ํฉ์น ๋๋ ๊ตฌ๊ฐ๋ณ ๋น์จ์ ํ๊ท ํ์ง ์๊ณ , ์ฑ๊ณต ๊ฑด์์ ํ๊ฐ ๋์ ๊ฑด์๋ฅผ ๊ฐ๊ฐ ๋ํ ๋ค ๋๋๋๋ค. p95ยทp99๋ ๊ตฌ๊ฐ๋ณ ๊ฐ์ ํ๊ท ํ์ง ์๊ณ ์ ์ฒด ์ธก์ ๊ฐ์์ ๋ค์ ๊ณ์ฐํฉ๋๋ค.
- ํ์ ์ HTTP ์๋ต ์ฝ๋๋ก๋ง ํฉ๋๋ค. ์๋ต ๋ด์ฉ์ด ๋ง๋์ง๋ ํ์ ํ์ง ์์ต๋๋ค.
| ํ์ | ์๋ต ์ฝ๋ | ๊ธฐ์ค |
|---|---|---|
| ์ฑ๊ณต | 2xx (์ฌ๊ณ API: INGREDIENT-200-001\~006, INGREDIENT-201-001\~002) | ์์ฒญ์ด ์ ์ ์ฒ๋ฆฌ๋ ๊ฒฝ์ฐ |
| ์คํจ | ๋ชจ๋ 5xx (BE์ 500: GLOBAL-500-001, Nginx์ 502ยท503ยท504 ํฌํจ) | ์ฐ๋ฆฌ ์๋น์ค ์ชฝ ์ฅ์ ๋ก ์์ฒญ์ ์ฒ๋ฆฌํ์ง ๋ชปํ ๊ฒฝ์ฐ |
| ํ๊ฐ ์ ์ธ | ๋ชจ๋ 4xx (400ยท401ยท403ยท404ยท409ยท412ยท422ยท428 ํฌํจ) | ์ฑ๊ณต ๊ฑด์์๋, ํ๊ฐ ๋์ ๊ฑด์์๋ ๋ฃ์ง ์์ |
4xx ์ ์ธ
4xx ์์ฒญ์ ์์๋ ์์ฒญ์ฒ๋ผ ๋ณด๊ณ ์ฑ๊ณต๋ฅ ์ ๊ณ์ฐํฉ๋๋ค.
| ์์: ํ ๋ฌ ์์ฒญ 1,000๊ฑด | ๊ฑด์ |
|---|---|
| ์ฑ๊ณต(2xx) | 950๊ฑด |
| 4xx | 40๊ฑด โ ๊ณ์ฐ์์ ์ ์ธ |
| ์คํจ(5xx) | 10๊ฑด |
| ์ฑ๊ณต๋ฅ | 950 รท (1,000 โ 40) = 950 รท 960 โ 98.96% |
4xx๋ฅผ ์คํจ๋ก ์ธ๋ฉด 95%, ์ฑ๊ณต์ผ๋ก ์ธ๋ฉด 99%๊ฐ ๋ฉ๋๋ค. ์ ์ธํ๋ฉด 4xx๋ ์ฑ๊ณต๋ฅ ์ ์ฌ๋ฆฌ์ง๋ ๋ด๋ฆฌ์ง๋ ์์ต๋๋ค.
- ์ด์ : 4xx๋ ์๋ชป๋ ์ ๋ ฅยท๊ถํ ์์ ๋ฑ ํด๋ผ์ด์ธํธ ์์ฒญ์์ ๋น๋กฏ๋๋ฉฐ, ์ ์์ ์ผ๋ก ๋ถํ๋ฅผ ๋ฃ์ ์์ฒญ์ฒ๋ผ ์๋๋ ์คํจ๋ 4xx๋ก ๋์์ต๋๋ค. ์๋ฒ๋ ์ ์ ์ฌ์ฉ์์ ์ค์์ ์๋๋ ์คํจ๋ฅผ ๊ตฌ๋ถํ ์ ์์ผ๋ฏ๋ก, 4xx๋ฅผ ์คํจ๋ก ์ธ๋ฉด ์๋น์ค ํ์ง๊ณผ ๋ฌด๊ดํ ์์ฒญ์ด SLO๋ฅผ ๊น๊ฒ ๋ฉ๋๋ค.
- ํธ๋ ์ด๋์คํ: ์ธ๋ถ ์์ธ์ผ๋ก SLO๊ฐ ํ๋ค๋ฆฌ์ง ์๋ ๋์ , ์๋ฒ ๋ฒ๊ทธ๋ ์ธ์ฆ ์ฅ์ ๋ก ์๋ชป ๋ฐ์ํ 4xx(์: ์ ์ ์ฌ์ฉ์์๊ฒ 401ยท404 ๋๋ ๋ฐ์)๋ SLO์ ๋๋ฌ๋์ง ์์ต๋๋ค. 4xx๋ ์ฝ๋๋ณ ๊ฑด์๋ฅผ ๋ณ๋๋ก ์ง๊ณํ๊ณ , ํ์๋ณด๋ค ๊ธ์ฆํ๋ฉด ์์ธ์ ํ์ธํฉ๋๋ค.
์๊ฐ ์ด๊ณผยท์ฐ๊ฒฐ ์คํจ
flowchart LR
U(["์ฌ์ฉ์"]) --- Z1["์ฌ์ฉ์ โ Nginx<br/>ํ์ ๋ถ๋ ยท DNSยทTLS ์คํจ ยท AWS ์ฅ์ <br/>ํ๊ฐ ์ ์ธ (Sentry๋ก ๊ฑด์๋ง ๊ด์ธก)"]
Z1 --- N(["Nginx"])
N --- Z2["Nginx โ BE<br/>502 BE ๋ค์ดยท์ฌ๋ฐฐํฌ<br/>504 BE ์๋ต ์ง์ฐ<br/>์คํจ"]
Z2 --- BE(["BE"])
BE --- Z3["BE ๋ด๋ถ<br/>500 DB ์ฐ๊ฒฐ ์๊ฐ ์ด๊ณผ ยท ์ฒ๋ฆฌ ์ค ์์ธ<br/>์คํจ"]
Z3 --- DB(["DB"])
classDef excluded fill:#eeeeee,stroke:#888888,color:#333333;
classDef failure fill:#fde2e1,stroke:#c0504d,color:#5a1a18;
class Z1 excluded;
class Z2,Z3 failure;
- ์ฌ์ฉ์ โ Nginx ๊ตฌ๊ฐ์ ์ ์ธํ๋ ์ด์ : v1์ Route 53์์ Nginx๋ก ๋ฐ๋ก ์ฐ๊ฒฐ๋๋ฏ๋ก ์ด ๊ตฌ๊ฐ์์ ์ฐ๋ฆฌ ์ชฝ ์ฑ ์์ธ ์ฅ์ ๋ AWS ์ฅ์ ๋ฟ์ ๋๋ค. ๋ฐ๋ฉด ์ด ๊ตฌ๊ฐ์ ์คํจ๋ ๋๋ถ๋ถ ์ฌ์ฉ์์ ์ธํฐ๋ท ๋ฏธ์ฐ๊ฒฐยท์ฝํ ํ์ ๊ฐ์ ์ธ๋ถ ์์ธ์ด๋ฉฐ, ํด๋ผ์ด์ธํธ ๊ธฐ๋ก๋ง์ผ๋ก๋ ๋์ ๊ตฌ๋ถํ๊ธฐ ์ด๋ ต์ต๋๋ค.
- ํธ๋ ์ด๋์คํ: ์๋ฒ ๊ธฐ๋ก(NginxยทBE)๋ง์ผ๋ก ํ์ ํด ๊ธฐ์ค์ด ๋ช ํํ๊ณ ์ฌ์ฉ์ ํ๊ฒฝ ๋ฌธ์ ๊ฐ ์์ด์ง ์์ต๋๋ค. ๋์ ์์ฒญ์ด ์๋ฒ๊น์ง ์ค์ง ๋ชปํ๋ ๋๋ฌธ ์ฅ์ ๋ ์ฑ๊ณต๋ฅ ์ ๋๋ฌ๋์ง ์์ผ๋ฏ๋ก, Sentry์์ ์งง์ ์๊ฐ์ ์ฌ๋ฌ ์ฌ์ฉ์์ ๋คํธ์ํฌ ์ค๋ฅ๊ฐ ๋์์ ๋์ด๋๋์ง๋ก ํ์ธํฉ๋๋ค.
์๋ต ์ฝ๋ ๊ธฐ๋ฐ ํ์ ์ ํ๊ณ
์๋ฒ๊ฐ 2xx๋ก ์๋ตํ์ง๋ง ๊ฒฐ๊ณผ๊ฐ ์๋ชป๋ ๊ฒฝ์ฐ๋ ์ฑ๊ณต์ผ๋ก ์ง๊ณ๋ฉ๋๋ค.
| ์์ | ์๋ต | ์ค์ ๊ฒฐ๊ณผ |
|---|---|---|
| ์ฌ๊ณ ๋ฑ๋ก | 201 | ์๊ฐ๋ ๋ณํ ์ค๋ฅ๋ก ์ ํต๊ธฐํ์ด ํ๋ฃจ ๋ฐ๋ ค ์ ์ฅ๋จ |
| ์ฌ๊ณ ๋ฑ๋ก | 201 | 5๊ฐ ์ค 3๊ฐ๋ง ์ ์ฅ๋จ |
| ์ฌ๊ณ ์กฐํ | 200 | ๋น์ผ ์ฌ๊ณ ๊ฐ ๋ชฉ๋ก์์ ๋น ์ง |
- ํธ๋ ์ด๋์คํ: ์๋ฒ ๊ธฐ๋ก์ผ๋ก ๋ฐ๋ก ์ง๊ณํ ์ ์์ด ๊ธฐ์ค์ด ๋ช ํํ๊ณ ๊ตฌํ ๋ถ๋ด์ด ์ ์ ๋์ , ์กฐ์ฉํ ํ๋ฆฌ๋ ๋ฌธ์ ๋ SLO์ ๋๋ฌ๋์ง ์์ ํ ์คํธยทQAยท์ฌ์ฉ์ ์ ๋ณด๋ก ์ฐพ์์ผ ํฉ๋๋ค.
- ๊ณ ๋ํ ์ฌ์ง: ๊ฒฐ๊ณผ๋ฅผ ๋์กฐํ๊ธฐ ์ฌ์ด ํญ๋ชฉ๋ถํฐ ํ์ ์ ์ถ๊ฐํ ์ ์์ต๋๋ค(์: ์์นจ ์๋ฆผ ๋์ ์์ ์ค์ ์์ฑ ์, ๋ฑ๋ก ์์ฒญ ๊ฑด์์ ์ค์ ์ ์ฅ ๊ฑด์ ๋น๊ต).
ํ์ ๊ธฐ์ค
- ์๋ฒ ๊ธฐ๋ก์ผ๋ก ํ์ ํ๋ฉฐ, ์ฌ์ฉ์ ๊ธฐ๊ธฐ๊ฐ ์๋ฆผ์ ๋ฐ๊ฑฐ๋ ํ์ธํ ์๊ฐ์ ๊ณ ๋ คํ์ง ์์ต๋๋ค. 08:01๊น์ง ๊ณํํ ๋ฐ์ก์ ์งํค์ง ๋ชปํ๋ฉด ์คํจ์ ๋๋ค.
- ์ฌ์ฉ์๋ณ ์๋ฆผ์ ํ ๊ฑด์ผ๋ก ์ธ๊ณ , ์ฌ๋ฌ ๊ธฐ๊ธฐ ์ค ํ๋๋ง Push ์ ์์ ์ฑ๊ณตํด๋ ์ฑ๊ณต์ ๋๋ค.
- Push ๋์ ์ฌ์ฉ์(ํ์ฑ Push ๊ธฐ๊ธฐ๊ฐ ์๊ณ ๋ง๋ฃ ์๋ฆผ ์์ ์ ์ผ ์ฌ์ฉ์)๋ ์๋ฆผ ์์ฑ๊ณผ Push ์ ์๊ฐ ๋ชจ๋ ์ฑ๊ณตํด์ผ ์ฑ๊ณต์ ๋๋ค. ๊ทธ ์ธ ์ฌ์ฉ์๋ ์๋ฆผ ์์ฑ๋ง์ผ๋ก ํ์ ํฉ๋๋ค.
flowchart TD
A{"08:01๊น์ง ์๋ฆผ ์์ฑ?"} -->|์๋์ค| F["์คํจ"]
A -->|์| B{"Push ๋์ ์ฌ์ฉ์?<br/>ํ์ฑ Push ๊ธฐ๊ธฐ + ๋ง๋ฃ ์๋ฆผ ์์ ์ผฌ"}
B -->|์๋์ค| S["์ฑ๊ณต"]
B -->|์| C{"Push ๋ฐ์ก ๊ฒฐ๊ณผ<br/>์ฌ์ฉ์์ ๊ธฐ๊ธฐ ์ค ํ๋๋ผ๋"}
C -->|"ACCEPTED (08:01๊น์ง ์ ์)"| S
C -->|"CANCELLED (๊ตฌ๋
๋ง๋ฃ ยท ์์ ์ ์ฌ์ฉ ๋ถ๊ฐ)"| X["ํ๊ฐ ์ ์ธ"]
C -->|"FAILED ๋๋ 08:01 ์ดํ ์ ์"| F
classDef ok fill:#e3f2e1,stroke:#4b8651,color:#16391a;
classDef ng fill:#fde2e1,stroke:#c0504d,color:#5a1a18;
classDef ex fill:#eeeeee,stroke:#888888,color:#333333;
class S ok;
class F ng;
class X ex;
- ์๋ฆผ ์์ฑ ์ฑ๊ณต: 08:01๊น์ง ์๋ฆผ์ด ์์ฑ๋์ด ํด๋ง์ผ๋ก ์กฐํํ ์ ์๋ ์ํ
- Push ์ ์ ์ฑ๊ณต: ๋ธ๋ผ์ฐ์ ํธ์ ์๋น์ค(Chrome์ FCM, Safari๋ Apple, Firefox๋ Mozilla)๊ฐ 2xx๋ก ์ ์ํ ์ํ. ๊ธฐ๊ธฐ ๋์ฐฉ์ ์๋ฏธํ์ง๋ ์์ต๋๋ค.
ํธ๋ ์ด๋์คํ: ์๋ฒ ๋ฐ์ก ๊ธฐ๋ก๋ง์ผ๋ก ํ์ ํด ๊ธฐ์ค์ด ๋ช ํํ๊ณ Push ์ฅ์ ๊ฐ SLO์ ๋ฐ๋ก ๋๋ฌ๋ฉ๋๋ค. ๋์ ๋ธ๋ผ์ฐ์ ํธ์ ์๋น์ค ์์ฒด์ ์ฅ์ ์ฒ๋ผ ์ฐ๋ฆฌ ์ชฝ ์์ธ์ด ์๋ ์ ์ ์คํจ๋ ์คํจ๋ก ์ง๊ณ๋๊ณ , ์๋ฒ๊ฐ ์ ์๊ฐ์ ๋ณด๋๋๋ผ๋ ์ฌ์ฉ์๊ฐ ๋ฆ๊ฒ ๋ฐ๋ ๊ฒฝ์ฐ๋ ๋๋ฌ๋์ง ์์ต๋๋ค.
Push ๋ฐ์ก ๊ธฐ๋ก๋ณ ํ์
๋ฐ์ก ๊ธฐ๋ก(push_notifications) |
์๋ฏธ | ํ์ |
|---|---|---|
ACCEPTED |
ํธ์ ์๋น์ค๊ฐ 2xx๋ก ์ ์ | ์ฑ๊ณต |
FAILED + SEND_FAILEDยทSEND_WINDOW_EXPIRED
|
์ ์ก ์ค๋ฅยท์๊ฐ ์ด๊ณผ(์ต๋ 10์ด), ์ ์ค๊น์ง ๋ฐ์กํ์ง ๋ชปํจ | ์คํจ |
CANCELLED + SUBSCRIPTION_UNAVAILABLE
|
๊ตฌ๋ ๋ง๋ฃ(404ยท410) ๋๋ ์์ ์์ฑ ํ ๊ตฌ๋ ๋ณ๊ฒฝ | ํ๊ฐ ์ ์ธ |
CANCELLED + RECIPIENT_UNAVAILABLE
|
๋ฐ์ก ์ง์ ํํดยท๋์ฅ๊ณ ๋๊ฐยท์์ ๋ | ํ๊ฐ ์ ์ธ |
- ์ ์ธ ์ด์ : 4xx๋ฅผ ํ๊ฐ์์ ์ ์ธํ๋ ์์น์ ๋ฐ๋ฆ ๋๋ค. ๊ตฌ๋ ์ ์ฌ์ฉ์๊ฐ ์๋ฆผ ๊ถํ์ ํด์ ํ๊ฑฐ๋ ๋ธ๋ผ์ฐ์ ๋ฐ์ดํฐ๋ฅผ ์ง์ฐ๋ ๋ฑ ์ฌ์ฉ์ ์ชฝ ์์ธ์ผ๋ก ์ฌ๋ผ์ง๊ณ , ๋ฐ์ก ์ง์ ํํดยท์์ ๋์ ์ฌ์ฉ์์ ์ ํ์ ๋๋ค.
- ํธ๋ ์ด๋์คํ: ์ฌ์ฉ์ ์ชฝ ์์ธ์ด ์ค๋ฅ ์์ฐ์ ๊น์ง ์๋ ๋์ , VAPID ํค๋ฅผ ์๋ชป ๊ต์ฒดํ๋ ๋ฑ ์ฐ๋ฆฌ ์ค์๋ก ๊ตฌ๋
์ด ๋๋ ๋ฌดํจํ๋๋ ๊ฒฝ์ฐ๊ฐ ๋๋ฌ๋์ง ์์ต๋๋ค.
SUBSCRIPTION_UNAVAILABLE๊ฑด์๋ฅผ ๋ณ๋๋ก ์ง๊ณํ๊ณ ๊ธ์ฆํ๋ฉด ์์ธ์ ํ์ธํฉ๋๋ค. - ํ๊ณ: ๋ฐ์ก ๊ธฐ๋ก์ ํธ์ ์๋น์ค์ HTTP ์ํ ์ฝ๋๋ ์ ์ฅ๋์ง ์์ผ๋ฏ๋ก, 404ยท410 ์ธ์ 4xx(์: 400ยท403)๋ 5xx์ ๊ฐ์
SEND_FAILED๋ก ๊ธฐ๋ก๋์ด ์คํจ๋ก ์ง๊ณ๋ฉ๋๋ค.
๋ฐ์ก ํ๋ฆ๊ณผ ์ง๊ณ ์ ์ ์์
flowchart LR
subgraph ONTIME["์ ์ ๊ตฌ๊ฐ (08:00 ~ 08:01): ์ฑ๊ณต ์ธ์ "]
T0["08:00<br/>๋ฐฐ์น ์์"] --> T1["์๋ฆผ ์์ฑ<br/>๋์ฅ๊ณ ๋ณ"] --> T2["Push 1์ฐจ ๋ฐ์ก<br/>๊ธฐ๊ธฐ๋ณ"]
end
T2 --> CUT{{"08:01<br/>์ ์ ๊ธฐ์ค"}}
subgraph LATE["์ ์ ์ดํ: ์ ์๋ผ๋ ์ ์ ๊ธฐ์ค์ผ๋ก๋ ์คํจ"]
R1["์ฌ์๋ 1<br/>์ฝ 08:05"] --> R2["์ฌ์๋ 2<br/>์ฝ 08:20"] --> R3["์ฌ์๋ 3<br/>์ฝ 08:50"] --> DL["12:00<br/>๋ฐ์ก ๋ง๊ฐ"]
end
CUT -->|"1์ฐจ ์คํจ ์"| R1
classDef cut fill:#fff1dc,stroke:#ad7927,color:#51340a;
class CUT cut;
style ONTIME fill:#e3f2e1,stroke:#4b8651
style LATE fill:#fde2e1,stroke:#c0504d
- 08:00 ๋ฐฐ์น๊ฐ ๋์ฅ๊ณ ๋ณ๋ก ์๋ฆผ์ ์์ฑํ ๋ค, ์์ฑ๋ ์๋ฆผ์ ๊ธฐ์ค์ผ๋ก ๊ธฐ๊ธฐ๋ณ Push๋ฅผ ๋ฐ์กํฉ๋๋ค. ์๋ฆผ ์์ฑ์ ์คํจํ๋ฉด Push๋ ๋ฐ์ก๋์ง ์์ต๋๋ค.
- Push ์คํจ ์ ์ง์ ์คํจ ์์ ๋ถํฐ 5๋ถยท15๋ถยท30๋ถ ๋ค์ ์ฐจ๋ก๋ก ์ฌ์๋ํ๊ณ (1์ฐจ ์คํจ๊ฐ 08:00์ด๋ฉด ์ฝ 08:05ยท08:20ยท08:50), ์ ์ค๊ฐ ์ง๋๋ฉด ์ค๋จํฉ๋๋ค. ์ฒซ ์ฌ์๋๊ฐ 5๋ถ ๋ค์ด๋ฏ๋ก ์ฌ์๋๋ก ์ ์๋ผ๋ ์ ์ ๊ธฐ์ค์ผ๋ก๋ ์คํจ์ ๋๋ค.
- ์๋ฆผ ์์ฑ์ ์คํจํ ๋์ฅ๊ณ ๋ DB์ ๋จ์ง ์๊ณ ๋ฐฐ์น ๋ก๊ทธ(
failedRefrigeratorCount)์๋ง ๋จ์ต๋๋ค. ๋ฐ์ก ์๋ ๊ฑด์๋ง ํ๊ฐ ๋์์ผ๋ก ์ก์ผ๋ฉด ๋์ ๋๋ฝ์ ๋์น๋ฏ๋ก, ์ ์ฒด ๋์ ์๋ ๋ฐฐ์น ๋ก๊ทธ์์ ํจ๊ป ๊ฐ์ ธ์ต๋๋ค.
์๋ฆผ ๋์ ์ฌ๊ณ
- ์ ํต๊ธฐํ์ด ์ง๋ ์ฌ๊ณ ๋ ์ฌ์ฉ์๊ฐ ์น์ธ ๋๊น์ง ๋งค์ผ ๋ง๋ฃ ์๋ฆผ์ ํฌํจ๋ฉ๋๋ค. ์น์ฐ์ง ์์ ์ฌ๊ณ ๋ฅผ ์น์ฐ๋๋ก ์๋ฆฌ๋ ๊ฒ์ด ๋ชฉ์ ์ ๋๋ค.
- ์๋์ด 0์ธ ์ฌ๊ณ ๋ ์กด์ฌํ์ง ์์ต๋๋ค. ๋จ์ ์์ด 0์ด ๋๋ฉด ์ฌ๊ณ ๊ฐ ์ญ์ ๋๊ณ , ๋ฑ๋กยท์์ ์์๋ ์๋์ 1 ์ด์(๋ฌด๊ฒ๋ 0 ์ด๊ณผ)๋ง ํ์ฉ๋ฉ๋๋ค.
- ์๋ฆผ์ 08:00 ๋ฐฐ์น๊ฐ ์กฐํํ ์์ ์ ์ฌ๊ณ ๋ก ๋ง๋ค๋ฉฐ, ์ดํ์ ์ฌ๊ณ ๋ณ๊ฒฝ์ ๋น์ผ ์๋ฆผ์ ๋ฐ์๋์ง ์์ต๋๋ค. ๋ฐ์ก ์ง์ ์ฌ๊ณ ๋ฅผ ๋ค์ ํ์ธํ๋ ๋ฑ ๊ณ ๋ํ ์ฌ์ง๊ฐ ์์ต๋๋ค.
์๋ ค์ง ํ๊ณ (ํด๋ผ์ด์ธํธ)
- ํ๋ฉด ํ์ ์ง์ฐ: ํด๋ง ๊ฐ๊ฒฉ์ด 30์ด์ด๋ฏ๋ก ์๋ฆผ์ด ํ๋ฉด์ ํ์๋๊ธฐ๊น์ง ์ต๋ ์ฝ 30์ด๊ฐ ๊ฑธ๋ฆด ์ ์์ผ๋ฉฐ, ์ด๋ ์๋ฒ ๊ธฐ์ค SLO์ ํฌํจํ์ง ์์ต๋๋ค.
- ํด๋ง ์ค๋จ: ํด๋ง ์์ฒญ์ด ์ฌ์๋ ํ์๋ ์คํจํ๋ฉด ํด๋ง์ด ๋ฉ์ถ๊ณ , ์ฌ์ฉ์๊ฐ ํญ์ ์ ํํด ๋์์ฌ ๋ ์ฌ๊ฐ๋ฉ๋๋ค. ๋ฐ์ก ์ง์ ์๋ฒ๊ฐ ์ ๊น 5xx๋ฅผ ๋ฐํํ๋ฉด, ์๋ฒ๊ฐ ์ ์์ ์๋ฆผ์ ์์ฑํ๋๋ผ๋ ํญ ์ ํ ์ ๊น์ง ํ๋ฉด์ ํ์๋์ง ์์ ์ ์์ต๋๋ค.
EC2์ ๋ก๊ทธ๋ฅผ CloudWatch Logs๋ก ์์งํ๊ณ , ์งํ ํํฐ(Metric Filter)๋ก ์ค์๊ฐ ์ง๊ณํฉ๋๋ค.
flowchart LR
subgraph EC2["EC2"]
NG["Nginx ์ ๊ทผ ๋ก๊ทธ"]
BL["BE ๋ก๊ทธ"]
BT["08:00 ๋ฐฐ์น ๋ก๊ทธ"]
end
NG & BL & BT --> AG["CloudWatch Agent"]
AG -->|"์ฝ 5์ด"| CL["CloudWatch Logs"]
CL -->|"์งํ ํํฐ ยท 1๋ถ"| CM["CloudWatch ์งํ<br/>์๋ต ์ฝ๋๋ณ ๊ฑด์"]
DB[("DB<br/>์๋ฆผยทPush ๋ฐ์ก ๊ธฐ๋ก")]
SE["Sentry<br/>๋ธ๋ผ์ฐ์ ์๋ต์๊ฐ"]
CM -->|"์์
์ฑ๊ณต๋ฅ "| M["์ ํฉ์ฐ ยท SLO ํ์ "]
CL -->|"์๋ฆผ ๋์ ์"| M
DB -->|"์์นจ ์๋ฆผ"| M
SE -->|"์๋ต์๊ฐ"| M
- 1๋ถ ์ฃผ๊ธฐ๋ฅผ ์ ํํ ์ด์ : ์งํ ํํฐ๋ ๋ก๊ทธ๊ฐ ๋์ฐฉํ ๋๋ง๋ค ํ๊ฐํ์ง๋ง ์งํ ๊ฐ์ 1๋ถ ๋จ์๋ก ๊ธฐ๋กํ๋ฏ๋ก, ์ฝ๋ ์์ ์์ด ์ป์ ์ ์๋ ๊ฐ์ฅ ์งง์ ์ฃผ๊ธฐ์ ๋๋ค. ์ฅ์ ๊ฐ ๋๋ฉด ์ฝ 1~2๋ถ ์์ ์งํ์ ๋ฐ์๋ฉ๋๋ค.
- ํธ๋ ์ด๋์คํ: 1์ด ๋จ์ ์ง๊ณ๋ BE ๋ก๊ทธ ํ์์ ๋ฐ๊พธ๊ฑฐ๋(EMF) ์งํ๋ฅผ ์ง์ ๋ณด๋ด์ผ(PutMetricData) ํ๋ฏ๋ก ์ฑํํ์ง ์์์ต๋๋ค. ๋ํ ์งํ ํํฐ๋ ์กฐ๊ฑด๋ณ ๊ฑด์๋ง ์ ์ ์์ด, 4xx ์ ์ธยทAPI๋ณ ๋ถ๋ฆฌ์ฒ๋ผ ์กฐ๊ฑด์ด ๋์ด๋๋ฉด ํํฐ๋ ๊ทธ๋งํผ ๋์ด๋ฉ๋๋ค.
- ๋ณด๊ด: CloudWatch๋ ์งํ๋ฅผ 15์ผ ์ด๋ด 1๋ถ, 63์ผ ์ด๋ด 5๋ถ, 455์ผ ์ด๋ด 1์๊ฐ ํด์๋๋ก ๋ณด๊ดํฉ๋๋ค. ํด์๋๊ฐ ์ค์ด๋ ํฉ๊ณ๋ ์ ์ง๋๋ฏ๋ก ์๊ฐ ํฉ์ฐ์๋ ์ํฅ์ด ์์ต๋๋ค.
ํ๊ฐ ๊ธฐ๊ฐ์ **ํ๊ตญ ์๊ฐ ๊ธฐ์ค ๋ฌ๋ ฅ ์(๋งค์ 1์ผ 00:00 ์ด์, ๋ค์ ๋ฌ 1์ผ 00:00 ๋ฏธ๋ง)**์ ๋๋ค. ์๊ฐ ๋น์จ์ ์ผ๋ณ ๋น์จ์ ํ๊ท ์ด ์๋๋ผ ๊ฑด์๋ฅผ ํฉ์ฐํด ๊ณ์ฐํฉ๋๋ค.
| ๋์ | ๋ชฉํ |
|---|---|
| ์์นจ ์๋ฆผ | ํด๋น ์ ํ๊ฐ ๋์ ์๋ฆผ์ 95% ์ด์์ด ๊ฐ ๋ฐ์ก์ผ KST 08:01๊น์ง ์ฑ๊ณต (3.3 ๊ธฐ์ค) |
| ์์ ์ฑ๊ณต๋ฅ | ์๋ ์ฌ๊ณ ๋ฑ๋กยท์ฌ๊ณ ์กฐํยท์๋ฆผ ์กฐํ(ํด๋ง) ๊ฐ๊ฐ ์๊ฐ 95% ์ด์ |
| ์๋ต์๊ฐ | ์๋ ์ฌ๊ณ ๋ฑ๋กยท์ฌ๊ณ ์กฐํ ๊ฐ๊ฐ p95 โค 1์ด, p99 โค 10์ด |
์๋ต์๊ฐ์ ํ๊ฐ ๋์์ 95% ์ด์์ด 1์ด ์ด๋ด, 99% ์ด์์ด 10์ด ์ด๋ด๋ผ๋ ๋ ์กฐ๊ฑด์ผ๋ก ๊ด๋ฆฌํ๋ฉฐ, ๋ฑ๋ก๊ณผ ์กฐํ๋ฅผ ๊ฐ๊ฐ ํ๊ฐํฉ๋๋ค. ์๋ต์๊ฐ ๋ชฉํ์ ์ฑ๊ณต๋ฅ ๋ชฉํ๋ ์๋ก ๋์ ํ์ง ์๊ณ ๊ฐ๊ฐ ํ๊ฐํฉ๋๋ค.
4xx ์๋ต์ ์ฑ๊ณต๋ฅ ๊ณผ ๊ฐ์ด ์๋ต์๊ฐ ์ง๊ณ์์๋ ์ ์ธํฉ๋๋ค.
- ์ด์ : ์ ์์ ์ผ๋ก ๋ถํ๋ฅผ ๋ฃ์ ์์ฒญ์ ๋๋ถ๋ถ 4xx๋ก ๋์์ค๋ฉฐ, ์๋ฒ๋ ์ด๋ฅผ ์ ์ ์์ฒญ๊ณผ ๊ตฌ๋ถํ ์ ์์ต๋๋ค. 4xx๋ฅผ ํฌํจํ๋ฉด ์ด๋ฐ ์์ฒญ ๋๋ฌธ์ ์๋ต์๊ฐ ์งํ๊ฐ ์ด์ฉ ์ ์์ด ๋๋น ์ง๋ฏ๋ก ์ด๋ฅผ ๋ง๊ธฐ ์ํด ์ ์ธํฉ๋๋ค.
- ํธ๋ ์ด๋์คํ: ์ธ๋ถ ์์ฒญ์ผ๋ก ์งํ๊ฐ ํ๋ค๋ฆฌ์ง ์๋ ๋์ , ์ ์ ์ฌ์ฉ์๊ฐ ๋ฐ์ 4xx ์๋ต์ด ๋๋ ธ๋ ๊ฒฝ์ฐ(์: ์ธ์ฆ ์ฒ๋ฆฌ ์ง์ฐ ํ 401)๋ ์๋ต์๊ฐ ์งํ์ ๋๋ฌ๋์ง ์์ต๋๋ค.
์ด๊ธฐ ์๋น์ค ๋จ๊ณ์์๋ ์ด์ ๋ฐ์ดํฐ๊ฐ ์๊ณ ํธ๋ํฝ์ด ์ ์ผ๋ฏ๋ก ํ์ค์ ์ผ๋ก ์งํฌ ์ ์๋ 95%์์ ์์ํฉ๋๋ค. ์ด์ ๋ฐ์ดํฐ๊ฐ ์์ด๋ฉด ์ค์ ์ฑ๊ณต๋ฅ ์ ๋ณด๊ณ ๋ชฉํ๋ฅผ ๋์ ๋๋ค.
- ํธ๋ ์ด๋์คํ: ๋ชฉํ๊ฐ ๋์จํด ์ด๊ธฐ ์ฅ์ ๋ ์ฌ๋ฐฐํฌ ์ค๋จ์ผ๋ก SLO๊ฐ ์ฝ๊ฒ ๊นจ์ง์ง ์๊ณ , ์ค๋ฅ ์์ฐ์ ์ค์ ๊ฐ์ ์ฐ์ ์์ ํ๋จ์ ์ธ ์ ์์ต๋๋ค(์: ์ 1,000๊ฑด์ด๋ฉด ์คํจ 50๊ฑด๊น์ง ํ์ฉ). ๋์ ์ 5%์ ์คํจ๊น์ง ํ์ฉํ๋ฏ๋ก ์์ ํ์ง ์ ํ๋ SLO์ ๋๋ฌ๋์ง ์์ต๋๋ค. ์ด๋ฅผ ๋ณด์ํ๊ธฐ ์ํด 5xx ๊ฑด์๋ ๋ณ๋๋ก ๊ด์ฐฐํ๊ณ , ๋ชฉํ๋ ์ด์ ๋ฐ์ดํฐ๋ฅผ ๋ฐํ์ผ๋ก ๋จ๊ณ์ ์ผ๋ก ๋์ ๋๋ค.
- ์ฐธ๊ณ : IBM์ ๋์ ์ค์๋์ ์์คํ ์์ 99.9% ๋๋ 99.99% ๊ฐ์ฉ์ฑ์ ๊ณ ๋ คํ ์ ์๋ค๊ณ ์ค๋ช ํฉ๋๋ค. ๋ค๋จน์๋ ์ด๊ธฐ ๋จ๊ณ์ด๋ฏ๋ก ์ด ์์ค์ ์ฅ๊ธฐ ๋ชฉํ๋ก ๋๊ณ , ์ฒ์์๋ ๋ฎ์ ๋ชฉํ๋ก ์์ํฉ๋๋ค.
Jakob Nielsen์ด ์ ๋ฆฌํ ์๋ต์๊ฐ ํ๊ณ(Usability Engineering, 1993)๋ฅผ ๊ทผ๊ฑฐ๋ก ํฉ๋๋ค.
| ํ๊ณ | ์ฌ์ฉ์ ์ธ์ง | ๋ค๋จน์ ๋ชฉํ |
|---|---|---|
| 1์ด | ์ง์ฐ์ ๋๋ผ์ง๋ง ์๊ฐ์ ํ๋ฆ์ด ๋๊ธฐ์ง ์๋ ํ๊ณ | p95 โค 1์ด: ๋๋ถ๋ถ์ ์ฌ์ฉ์๊ฐ ์์ ํ๋ฆ์ ์ ์ง |
| 10์ด | ์์ ์ ์ฃผ์๋ฅผ ์ ์งํ ์ ์๋ ํ๊ณ | p99 โค 10์ด: ๊ฑฐ์ ๋ชจ๋ ์ฌ์ฉ์๊ฐ ์์ ์ ์ดํํ์ง ์์ |
- ํธ๋ ์ด๋์คํ: ์ฌ์ฉ์ ์ธ์ง์ ๊ทผ๊ฑฐํด "์ 1์ด์ธ๊ฐ"๋ฅผ ์ค๋ช ํ ์ ์์ง๋ง, ์นยท๋ชจ๋ฐ์ผ ๋คํธ์ํฌ ํ๊ฒฝ์ ์ ์ ๋ก ํ ์ฐ๊ตฌ๊ฐ ์๋๋ฉฐ ์ ์ฉ ๋น์จ(95%, 99%)์ ํ๋ก์ ํธ์ ์ค๊ณ ๊ฒฐ์ ์ ๋๋ค.
- ๊ฒ์ฆ: ์ธก์ ์์ ํ 2~4์ฃผ๊ฐ์ ์ค์ ์๋ต์๊ฐ์ผ๋ก ๋ชฉํ๊ฐ ํ์ค์ ์ธ์ง ํ์ธํฉ๋๋ค. ์ธก์ ๊ฐ์ด ๊ธฐ์ค๋ณด๋ค ๋์๋ฉด ๋ชฉํ๋ฅผ ๋ฎ์ถ๊ธฐ๋ณด๋ค ๊ฐ์ ๊ณผ์ ๋ก ๋ค๋ฃน๋๋ค.
- ์ฐธ๊ณ : Google Core Web Vitals์ INP๋ ์ ๋ ฅ ํ ์ฒซ ๋ฐ์์ด ๊ทธ๋ ค์ง๊ธฐ๊น์ง๋ฅผ p75 ๊ธฐ์ค 200ms ์ดํ๋ฉด "์ข์"์ผ๋ก ๋ด ๋๋ค. ๋ค๋จน์ ๋ชฉํ(API ์์ฒญ๋ถํฐ ์๋ต ์์ ๊น์ง)์ ์ธก์ ๋ฒ์๊ฐ ๋ฌ๋ผ ๋ชฉํ ์์น๋ก๋ ์ฐ์ง ์์ต๋๋ค.
FE์ ์ค์ ๋ Sentry์ ์ฑ๋ฅ ์ธก์ (Tracing)์ด ์๋์ผ๋ก ๊ธฐ๋กํ๋ API ์์ฒญ ๊ตฌ๊ฐ(http.client)์ ์ฌ์ฉํฉ๋๋ค.
| ํญ๋ชฉ | ๋ด์ฉ |
|---|---|
| ์์ | ๋ธ๋ผ์ฐ์ ๊ฐ API ์์ฒญ์ ๋ณด๋ธ ์์ |
| ์๋ฃ | ๋ธ๋ผ์ฐ์ ๊ฐ API ์๋ต์ ๋ฐ์ ์์ |
| ๋์ | ์๋ ์ฌ๊ณ ๋ฑ๋ก(POST R/ingredients), ์ฌ๊ณ ์กฐํ(GET R/ingredients ๋ฑ) |
| ์ํ๋ง | prod 10%, dev 100% (์ค๋ฅ ์ด๋ฒคํธ๋ ์ ๋ถ ์์ง) |
์๋ ๋ค์ด์ด๊ทธ๋จ์์ ํ๋ ์์ญ์ด ์ธก์ ๊ตฌ๊ฐ์ ๋๋ค. ์๋ ์ฌ๊ณ ๋ฑ๋ก์ ์๋ก ๋ค์์ผ๋ฉฐ, ์ฌ๊ณ ์กฐํ๋ ๊ฐ์ ๋ฐฉ์์ ๋๋ค.
sequenceDiagram
actor U as ์ฌ์ฉ์
participant B as ๋ธ๋ผ์ฐ์ (FE)
participant N as Nginx
participant BE as BE
participant DB as DB
U->>B: ๋ฑ๋ก ๋ฒํผ ํด๋ฆญ
Note over U,B: ์ธก์ ์ ์ธ: ์
๋ ฅ ์ฒ๋ฆฌ
rect rgba(66, 133, 244, 0.18)
Note over B,DB: ์ธก์ ๊ตฌ๊ฐ (Sentry http.client)
B->>N: POST R/ingredients ์์ฒญ ์ ์ก โ ์ธก์ ์์
Note over B,N: DNS ์กฐํยทTLS ์ฐ๊ฒฐยท๋คํธ์ํฌ ์ ์ก
N->>BE: ์์ฒญ ์ ๋ฌ
BE->>DB: ์ฌ๊ณ ์ ์ฅ
DB-->>BE: ์ ์ฅ ์๋ฃ
BE-->>N: 201 ์๋ต
N-->>B: 201 ์๋ต ์์ โก ์ธก์ ์๋ฃ
end
B->>U: ๋ฑ๋ก ์๋ฃ ํ์
ํ์
Note over U,B: ์ธก์ ์ ์ธ: ํ๋ฉด ๊ทธ๋ฆฌ๊ธฐ
| ๊ตฌ๊ฐ | ์ธก์ ์ฌ๋ถ | ์ค๋ช |
|---|---|---|
| ๋ฒํผ ํด๋ฆญ โ ์์ฒญ ์ ์ก | ์ ์ธ | ์ ๋ ฅ ์ฒ๋ฆฌยท์์ฒญ ์ค๋น ์๊ฐ |
| โ ์์ฒญ ์ ์ก โ โก ์๋ต ์์ | ์ธก์ | DNSยทTLS ์ฐ๊ฒฐ, ๋คํธ์ํฌ ์๋ณต, NginxยทBEยทDB ์ฒ๋ฆฌ ์๊ฐ |
| ์๋ต ์์ โ ํ์ ํ์ | ์ ์ธ | ํ๋ฉด์ ๊ทธ๋ฆฌ๋ ์๊ฐ |
- ์๋ฃ ์์ ์ ์๋ต ์์ ์ผ๋ก ์ ํ ์ด์ : ๋ฑ๋ก ์์ฒญ์ ์๋ต์ด ์ค๋ฉด ๊ณง๋ฐ๋ก ๋ฑ๋ก ์๋ฃ ํ์ ์ด ๋จ๋ฏ๋ก, ์๋ต ์์ ์ด ์ฌ์ฉ์๊ฐ ๊ฒฐ๊ณผ๋ฅผ ํ์ธํ๋ ์์ ๊ณผ ๊ฑฐ์ ๊ฐ์ต๋๋ค. ํ๋ฉด์ ๊ทธ๋ฆฌ๋ ์๊ฐ์ ํฌํจํ์ง ์์ผ๋ฉฐ, FE์ ๊ธฐ๋ฅ๋ณ ์ธก์ ๊ตฌ๊ฐ์ ์ถ๊ฐํ๋ฉด ํ๋ฉด ๋ฐ์ ์๋ฃ๊น์ง ์ธก์ ํ ์ ์์ต๋๋ค.
- ์ฅ์ : ์ฌ์ฉ์ ๊ธฐ๊ธฐ์์ ์ฌ๋ฏ๋ก DNSยทTLS ์ฐ๊ฒฐ, ๋คํธ์ํฌ ์๋ณต, BE ์ฒ๋ฆฌ ์๊ฐ์ด ๋ชจ๋ ํฌํจ๋๊ณ , ๊ฐ์ ๊ธฐ๊ธฐ์ ์๊ณ๋ก ์ฌ๋ฏ๋ก ์๋ฒ์์ ์๊ณ ์ฐจ์ด ์ํฅ์ด ์์ต๋๋ค. ์ด๋ฏธ ์ค์ ๋ Sentry๋ฅผ ์ฐ๋ฏ๋ก ์์ง ์๋ฒ๋ ์ฝ๋ ์์ ์ด ํ์ ์์ต๋๋ค.
- ๋จ์ : prod๋ 10%๋ง ์ํ๋งํ๋ฏ๋ก ํธ๋ํฝ์ด ์ ์ ์ด๊ธฐ์๋ ์ธก์ ๊ฐ์ด ๋ถ์กฑํ ์ ์์ต๋๋ค. ๋ฐ์ดํฐ๊ฐ Sentry ์์ ์์ด 4xx ์ ์ธ ๊ฐ์ ๊ณ์ฐ ๊ท์น์ ์์ ๋กญ๊ฒ ์ ์ฉํ๊ธฐ ์ด๋ ต๊ณ , ์ธก์ ๊ฐ์ ๋ณด๋ด๊ธฐ ์ ์ ํญ์ ๋ซ๊ฑฐ๋ ์คํ๋ผ์ธ์ด ๋๋ฉด ๊ฐ์ด ๋น ์ง๋๋ค.
- ์ด์์ ํ๊ณ: Sentry๋ 14์ผ ๋ฌด๋ฃ ์ฒดํ ๊ณ์ ํ๋๋ฅผ ํ์์ด ํจ๊ป ์ฌ์ฉํฉ๋๋ค. ๋น์ฉ ๋ฌธ์ ๋ก ๋ฉค๋ฒ ์ด๋๊ฐ ๋ถ๊ฐ๋ฅํด ์๊ธด ํ๊ณ๋ก, ๋๊ฐ ์ค์ ์ ๋ฐ๊ฟจ๋์ง ์ถ์ ํ ์ ์๊ณ ์ฒดํ ๊ธฐ๊ฐ์ด ๋๋๋ฉด ๋ฌด๋ฃ ํ๋์ ์ฌ์ฉ๋ยท๋ณด๊ด ๊ธฐ๊ฐ ์ ํ์ ๋ฐ์ต๋๋ค.
๊ฒํ ํ์ง๋ง ์ฑํํ์ง ์์ ๋ฐฉ์
| ๋ฐฉ์ | ์ฑํํ์ง ์์ ์ด์ |
|---|---|
| ๋ธ๋ผ์ฐ์ ์ธก์ ์ง์ ๊ตฌํ | ๊ณ์ฐ ๊ท์น์ ์์ ๋กญ๊ฒ ์ ํ ์ ์์ง๋ง, ์์ง APIยท์ ์ฅ์ยท๊ณ์ฐ ์ฟผ๋ฆฌ๋ฅผ ์๋ก ๋ง๋ค๊ณ ์ด์ํด์ผ ํฉ๋๋ค. |
| BE์์ ์์ฒญ ๋์ฐฉ ์๊ฐ ร 2 + ์ฒ๋ฆฌ ์๊ฐ์ผ๋ก ์ถ์ | ํด๋ผ์ด์ธํธ์ ์๋ฒ์ ์๊ณ๊ฐ ๋ง์ง ์์ ์์ฒญ ๋์ฐฉ ์๊ฐ์ ์ ํํ ์ ์ ์๊ณ , ์์ฒญ๊ณผ ์๋ต์ ํฌ๊ธฐยทํ์ ์๋๊ฐ ๋ฌ๋ผ ์๋ณต์ด ๋์นญ์ด ์๋๋๋ค. |
| Nginx ๋ก๊ทธ | ์ฝ๋ ์์ ์์ด BE ์ฒ๋ฆฌ ์๊ฐ์ ์ป์ ์ ์์ง๋ง, DNS ์กฐํยท์ฐ๊ฒฐ ์๋ฆฝ ๋ฑ ์๋ฒ ๋ฐ ๊ตฌ๊ฐ์ด ๋น ์ ธ ์ค์ ๋ณด๋ค ์งง๊ฒ ์ธก์ ๋ฉ๋๋ค. ์์ธ ๋ถ์์ฉ ๋ณด์กฐ ์งํ๋ก๋ ํ์ฉํฉ๋๋ค. |
| ํฉ์ฑ ๋ชจ๋ํฐ๋ง | ์ฌ์ฉ์๊ฐ ์์ด๋ ์ธก์ ๋์ง๋ง, ๊ณ ์ ๋ ์์นยท๊ธฐ๊ธฐ์์ ์คํ๋์ด ์ค์ ์ฌ์ฉ์ ํ๊ฒฝ์ ๋ํํ์ง ๋ชปํฉ๋๋ค. |
| ๋์ | ์๊ฐ ์ค๋ฅ ์์ฐ |
|---|---|
| ์์นจ ์๋ฆผ | ํ๊ฐ ๋์ ์๋ฆผ ์ ร 5% (์: 1,000๊ฑด์ด๋ฉด 50๊ฑด) |
| ์์ ์ฑ๊ณต๋ฅ | ์์ ๋ณ ํ๊ฐ ๋์ ๊ฑด์ ร 5% |
| ์๋ต์๊ฐ | 1์ด ์ด๊ณผ 5%, 10์ด ์ด๊ณผ 1%๋ฅผ ๊ฐ๊ฐ ํ๊ฐํ๋ฉฐ ํฉ์ฐํ์ง ์์ |
SLO ๋ฏธ๋ฌ์ ๋์ ๊ธฐ์ค์ผ๋ก ์ผ๋, ์ด์์ ์๋ฆผ์ ๋ฐ์ ์กฐ๊ฑดยท์ฌ๊ฐ๋ยท์์ ์ยท๋์ยท๋ณต๊ตฌ ์กฐ๊ฑด์ ๋ณ๋ ์๋ฆผ ์ค๊ณ์์ ์ ํฉ๋๋ค. ์๋ง ์ต์ข ํ์ ๊ณผ ์ด์ ์ค ์กฐ๊ธฐ ๊ฒฝ๋ณด๋ ๊ตฌ๋ถํ๋ฉฐ, ์๊ฐ SLO๊ฐ ๊นจ์ง ๋๊น์ง ๊ธฐ๋ค๋ฆฌ์ง ์์ต๋๋ค.
์๋๋ v2ยทv3 ์ค๊ณ ๋ฐฉํฅ์ด๋ฉฐ, ์ธ๋ถ ๊ธฐ์ค์ ํด๋น ๋ฒ์ ์ฐฉ์ ์ ํ์ ํฉ๋๋ค.
v2 ์์นจ ์๋ฆผ: SSE + Web Push + Catch-up
| ์ฑ๋ | ์ฑ๊ณตยท์คํจ ํ์ |
|---|---|
| SSE | ์ ์ก ์๋ฒ๊ฐ Redis๋ก ๋ณด๋ด๋ ACK๊ฐ ํ์ ๋ฒ์ ๋ด ์ ํํ 1๊ฐ์ด๋ฉด ์ฑ๊ณต, 0๊ฐ ๋๋ ์ฌ๋ฌ ๊ฐ์ด๋ฉด ์คํจ |
| Web Push | v1๊ณผ ๋์ผ |
| Catch-up | ์ฌ์ ์ ์ GET R/notifications๋ก ๋๋ฝ ์๋ฆผ์ ๋ณต๊ตฌํ๋ฉด ์ฑ๊ณต. 08:01 ์ดํ ๋ณต๊ตฌ๋ ์ ์ ์ฑ๊ณต์ ํฌํจํ์ง ์๊ณ ๋ณ๋ ์ธก์ |
๋ชฉํ๋ v1๊ณผ ๊ฐ์ด ์๊ฐ 95%, KST 08:01 ๊ธฐ์ค์ ๋๋ค. ๋ฐฐ์นยทPub/Sub ๊ธฐ๋ฐ์ผ๋ก ๋ฐ์กํ๋ฉฐ, ACK ์๋ณ ๋ฒ์ยท๋๊ธฐ ์๊ฐ๊ณผ SSEยทPush ๊ฒฐ๊ณผ์ ํ์ ๊ท์น์ ์ ํด์ผ ํฉ๋๋ค.
AI ์ฌ๊ณ ๋ฑ๋ก(์์์ฆ v2, ์ค๋ฌผ v3)
POST /api/v1/image-analyses โ GET /api/v1/image-analyses/{analysisId} โ POST R/ingredients ํ๋ฆ์ ํ๋์ ๋ฑ๋ก ๊ธฐ๋ฅ์ผ๋ก ์ธก์ ํฉ๋๋ค. ์ ์(202)ยท์กฐํ(200)๋ง์ผ๋ก ์ฑ๊ณต ์ฒ๋ฆฌํ์ง ์๊ณ ์ธ์ ๊ฒฐ๊ณผ์ ์ต์ข ์ ์ฅ๊น์ง ํ์ธํฉ๋๋ค.
| ๊ตฌ๋ถ | ์ธก์ ๋ฐฉ๋ฒ | ์ฉ๋ |
|---|---|---|
| ์ฒ๋ฆฌ ์ฑ๊ณต๋ฅ | ์ ํจํ ์ฌ์ง ๋ฑ๋ก ์ค ์ธ์๋ถํฐ ์ฌ๊ณ ์ ์ฅ๊น์ง ์๋ฃ๋ ๋น์จ | ์ด์ SLO |
| ์๊ฐ ๋ด ์ฑ๊ณต๋ฅ | ํ ๋๊ธฐยท์ถ๋ก ยทํ์ฒ๋ฆฌยท์ ์ฅ์ ๊ฑฐ์ณ T์ด ์์ ์ฌ๊ณ ๋ฅผ ์กฐํํ ์ ์๊ฒ ๋ ๋น์จ | ์ด์ SLO |
| ํ๋๋ณ ์ ๋ฐ๋ยท์ฌํ์จ | ์ ๋ต ์๋ฃ ๋๋น ์ด๋ฆยท์๋ยท์ ํต๊ธฐํ ์ถ์ถ ์ ํ๋ | AI ํ์ง ๋ชฉํ |
ํ์ง ํ๊ฐ์๋ ๋ํ ์ฌ์ง, ์ฌ๋์ด ํ์ธํ ์ ๋ต, ๊ฐ์ ์ ๊ทํ ๊ท์น์ด ํ์ํ๋ฉฐ, ํ๊ฐ์ ยท๋ชจ๋ธยทํ๋กฌํํธ ๋ฒ์ ์ ๊ธฐ๋กํฉ๋๋ค. confidence๋ ์ฌ์ฉ์ ๋ฌด์์ ๋น์จ์ ์ ๋ต๋ฅ ๋ก ๋์ ํ์ง ์์ต๋๋ค.
์๋ฆฌ ์ถ์ฒยท๋ ์ํผ ๊ธฐ๋ฐ ์๋น ์ฒ๋ฆฌ(v3)
| ์์ | ์ธก์ API | ํ์ ๋ฐฉํฅ |
|---|---|---|
| ์๋ฆฌ ์ถ์ฒ | POST R/recommendation-jobs โ GET R/recommendations โ GET R/recipes/{recipeId} | ์์ฑ ์ ์์ ๊ฒฐ๊ณผ ์ ๊ณต์ ๊ตฌ๋ถํ๊ณ , ์ ํจํ ์ถ์ฒยท์์ธ ์ ๊ณต๊น์ง ํ์ธ |
| ๋ ์ํผ ๊ธฐ๋ฐ ์๋น ์ฒ๋ฆฌ | POST R/cooking-records | ์ ํ ๋ ์ํผ์ ์กฐ๋ฆฌ ๊ธฐ๋กยท์ฐจ๊ฐ์ด ํ ๋ฒ๋ง ๋ฐ์๋๋์ง ํ์ธ |
๋ ์ํผ ๊ธฐ๋ฐ ์๋น ์ฒ๋ฆฌ๋ ์ถ์ฒ ๋ ์ํผ๋ฅผ ๊ธฐ์ค์ผ๋ก ์ฌ๊ณ ๋ฅผ ์ฌ์ฉํ๋ค๊ณ ๊ฐ์ฃผํ๋ฉฐ, ์ค์ ์กฐ๋ฆฌยท์ญ์ทจ ์ฌ๋ถ์ ๋ค๋ฆ ๋๋ค. ์ฌ์ฉ์๊ฐ ์๋ฆฌํ๊ฑฐ๋ ์ญ์ทจํ์ง ์์ ์๊ธฐ๋ ์ํฉ์ ์๋น์ค ์ฅ์ ์ ํฌํจํ์ง ์์ต๋๋ค.
- ๋ค๋จน์ API ๋ช ์ธ์ โ API ๊ฒฝ๋กยท๋์๊ณผ ์ฌ๊ณ API ์๋ต ์ฝ๋ ์ ์
- IBM: What is high availability? โ ๋์ ์ค์๋ ์์คํ ์ ๊ฐ์ฉ์ฑ ์์ค(์ฅ๊ธฐ ๋ชฉํ ์ฐธ๊ณ )
- Jakob Nielsen, NN/G: Response Times: The 3 Important Limits โ 1์ดยท10์ด ์๋ต์๊ฐ ๋ชฉํ ๊ทผ๊ฑฐ
- web.dev: Interaction to Next Paint (INP) โ INP ์ธก์ ๋ฒ์์ ๊ธฐ์ค
- IETF: RFC 8030 โ Generic Event Delivery Using HTTP Push โ Web Push ์ ์ ์๋ต๊ณผ ๊ธฐ๊ธฐ ์ ๋ฌ์ ๊ตฌ๋ถ
- AWS: CloudWatch Agent ์ค์ ํ์ผ โ ๋ก๊ทธ ์ ์ก ์ฃผ๊ธฐ ๊ธฐ๋ณธ๊ฐ
- AWS: Metrics concepts โ ์งํ ํด์๋์ ๋ณด๊ด ๊ธฐ๊ฐ
- AWS: High resolution metric extraction from structured logs โ 1์ด ๋จ์ ์ง๊ณ ์กฐ๊ฑด(EMF)
- ์ด๋คํฌยท์ฒ๊ธฐ์ฒ , LY Corporation: ์ ๋ขฐ์ฑ ํฅ์์ ์ํ SLI/SLO ๋์ 1ํธ โ ์ฌ์ฉ์ ์ฌ์ ์ค์ฌ์ ์งํ ์ค๊ณ
- Google SRE: Implementing SLOs โ ์งํ ์ ์์ ๋ชฉํ ์ค์
- Google SRE: Example SLO Document โ ์ธก์ ๊ฐ ๊ธฐ๋ฐ ๋ชฉํ ์ค์ ์ฌ๋ก
- Google SRE: Alerting on SLOs โ ์ค๋ฅ ์์ฐ ๊ธฐ๋ฐ ์๋ฆผ
- Google SRE: Data Processing Pipelines โ ์ฒ๋ฆฌ ํ์ดํ๋ผ์ธ์ ์ ํ์ฑ ๋ชฉํ(v2ยทv3)
- Google Cloud: Evaluate performance โ ์ ๋ฐ๋ยท์ฌํ์จ ํ๊ฐ(v2ยทv3)