FastAPI & Redis ์บ์ฑ ์ต์ ํ: DB ์กฐํ ๋ณ๋ชฉ ํด๊ฒฐ ๋ฐ TTFB(์ฒซ ๋ฐ์ดํธ ๋ก๋ฉ ์๊ฐ) 90% ๋จ์ถ๊ธฐ
์น์ฌ์ดํธ์ ์์ง์ ์ ๋ณด์ฑ ๊ธ์ ์๋ฌด๋ฆฌ ๋ง์ด ์์ฑํ๋๋ผ๋, ์ฌ์ฉ์๊ฐ ๋งํฌ๋ฅผ ํด๋ฆญํ์ ๋ ํ๋ฉด์ด ๋จ๊ธฐ๊น์ง 1~2์ด์ฉ ๊ฑธ๋ฆฐ๋ค๋ฉด ์ ์ ๋ ๋ฏธ๋ จ ์์ด '๋ค๋ก ๊ฐ๊ธฐ' ๋ฒํผ์ ๋๋ฆ ๋๋ค. ๊ตฌ๊ธ ์ ๋์ผ์ค ์ฌ์ฌ ๊ธฐ์ค๊ณผ SEO ๊ฒ์ ์์ ์๊ณ ๋ฆฌ์ฆ ์ญ์ 'ํ์ด์ง ๋ก๋ฉ ์๋(Page Speed)'์ '์ฝ์ด ์น ๋ฐ์ดํ(Core Web Vitals)'์ ์ฌ์ดํธ ํ์ง ํ๊ฐ์ ์ ๋์ ์ธ ์งํ๋ก ํ์ฉํฉ๋๋ค.
์ ๊ฐ ์ด์ํ๋ ํ์ด์ฌ FastAPI ์ปค๋ฎค๋ํฐ์ ๊ฒฝ์ฐ, ํธ๋ํฝ์ด ๋ชฐ๋ฆฌ๋ ์ ๋ ์๊ฐ๋๋ง ๋๋ฉด ๋ฉ์ธ ํ์ด์ง์ ์ฒซ ๋ฒ์งธ ์๋ต ์๋์ธ TTFB(Time to First Byte)๊ฐ 800~1,000ms๊น์ง ๋๋ ค์ง๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ต๋๋ค. ๋ธ๋ผ์ฐ์ ๊ฐ ์ฒซ ๋ฐ์ดํธ๋ฅผ ๋ฐ๊ธฐ๊น์ง 1์ด ๊ฐ๊น์ด ๋ฉํ๊ฒ ๊ธฐ๋ค๋ ค์ผ ํ๋, ๊ตฌ๊ธ ์์น ์ฝ์์ ์ฑ๋ฅ ๋ฆฌํฌํธ์๋ '๋๋ฆผ(Slow)' ๊ฒฝ๊ณ ๊ฐ ๋ค์ด์ค๊ธฐ ์์ํ์ต๋๋ค.
๋ ๋ง์ ์ ์ ๋ฅผ ์์ฉํ๊ณ ๊ตฌ๊ธ์ ๊ธฐ์ ์ ๊ฒ์ฆ์ ์๋ฒฝํ๊ฒ ํต๊ณผํ๊ธฐ ์ํด, DB I/O ๋ณ๋ชฉ์ ๊ทผ๋ณธ์ ์ผ๋ก ํด๊ฒฐํ๋ Redis ์ธ๋ฉ๋ชจ๋ฆฌ ์บ์ฑ ์ํคํ ์ฒ ์์ ์ ์ฐฉ์ํ์ต๋๋ค.
1. ๋ฒ์ธ ๋ถ์: ๋งค๋ฒ ๋์คํฌ๋ฅผ ๋๋๋ฆฌ๋ ๋ฌด๊ฑฐ์ด SQL ์ฟผ๋ฆฌ
๊ฐ๋ฐ์ ๋๊ตฌ(F12)์ Network ํญ๊ณผ FastAPI APM ํ๋กํ์ผ๋ฌ๋ฅผ ๋์ ๋ฐฑ์๋ ๋ด๋ถ ์ํ ์๊ฐ์ ์ธก์ ํด ๋ณธ ๊ฒฐ๊ณผ, ์์ธ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค(PostgreSQL) ํธ์ถ ๋ฐฉ์์ ์์์ต๋๋ค.
์ปค๋ฎค๋ํฐ ๋ฉ์ธ ํ์ด์ง ํ๋๋ฅผ ๋ ๋๋งํ๊ธฐ ์ํด์๋ ๋ค์๊ณผ ๊ฐ์ ์ฟผ๋ฆฌ๋ค์ด ๋์์ ์คํ๋ฉ๋๋ค.
์๋จ ๊ณ ์ ๊ณต์ง์ฌํญ ๋ชฉ๋ก ์กฐํ (ORDER BY created_at DESC)
์ค์๊ฐ ์ค์๊ฐ ์ธ๊ธฐ๊ธ TOP 10 ์ฐ์ถ (LIKE, VIEW COUNT ๊ธฐ์ค ์ ๋ ฌ)
์ ์ฒด ์นดํ ๊ณ ๋ฆฌ๋ณ ์ต์ ๊ฒ์๊ธ 5๊ฐ์ฉ ์ถ์ถ (JOIN ๋ฐ Subquery)
์ฌ์ดํธ ์ค์๊ฐ ํต๊ณ (์ ์ฒด ํ์์, ์ค๋ ์์ฑ๋ ๊ธ ์)
์ ์ 1๋ช ์ด ๋ฉ์ธ ํ์ด์ง์ ์ ์ํ ๋๋ง๋ค ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ ๊ณ ์ฑ๋ฅ SSD ๋์คํฌ๋ฅผ 10๋ฒ ์ด์ ์๋ณตํ๋ฉฐ ๋๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ๋ณตํด์ ๊ณ์ฐํ๊ณ ์์์ต๋๋ค. ๋์ ์ ์์๊ฐ 100๋ช ๋ง ๋์ด๋ ์ด๋น 1,000๋ฒ์ด ๋๋ ๋ฌด๊ฑฐ์ด Disk I/O๊ฐ ์ ๋ฆฌ๋ฉฐ DB CPU ์ ์ ์จ์ด 90%๋ฅผ ๋ซ์ด๋ฒ๋ฆฐ ๊ฒ์ ๋๋ค.
๋์คํฌ ๊ธฐ๋ฐ์ RDBMS๋ ๋ฐ์ดํฐ์ ์์์ฑ์ ๋ณด์ฅํ๋ ๋ฐ ํนํ๋์ด ์์ ๋ฟ, 1์ด์ ์์ฒ ๋ฒ์ฉ ๋ฐ๋ณต๋๋ '์ฝ๊ธฐ ์ ์ฉ(Read-Only) ์์ฒญ'์ ์ฒ๋ฆฌํ๊ธฐ์๋ ๊ตฌ์กฐ์ ์ธ ํ๊ณ๊ฐ ์์์ต๋๋ค.
2. ํด๊ฒฐ์ฑ 1๋จ๊ณ: Cache-Aside ํจํด๊ณผ ๋น๋๊ธฐ Redis ๊ตฌํ
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๋ฐ์ดํฐ ์ฝ๊ธฐ ์๋๊ฐ ๋๋ ธ์ด(ns) ๋จ์์ ๊ฐ๊น์ด Redis(Remote Dictionary Server) ์ธ๋ฉ๋ชจ๋ฆฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ํคํ ์ฒ ์ค์์ ๋ฐฐ์นํ์ต๋๋ค.
FastAPI์ ๋น๋๊ธฐ(async/await) ์ด๋ฒคํธ ๋ฃจํ๊ฐ ๋ฉ์ถ์ง ์๋๋ก, redis-py ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋น๋๊ธฐ ๋ชจ๋(redis.asyncio)์ ํ์ฉํ์ฌ Cache-Aside(Look-Aside) ํจํด์ ๊ตฌํํ์ต๋๋ค.

์ด ๊ตฌ์กฐ์์๋ ์ ์ ๊ฐ ๋ฉ์ธ ํ์ด์ง ์์ฒญ์ ๋ณด๋์ ๋ ๋ฐฑ์๋๊ฐ ๋ค์๊ณผ ๊ฐ์ด ๋์ํฉ๋๋ค.
Cache Hit (์บ์ ์ฑ๊ณต): ๋จผ์ Redis ๋ฉ๋ชจ๋ฆฌ์์
main:popular_postsํค๋ฅผ ์กฐํํฉ๋๋ค. ๋ฐ์ดํฐ๊ฐ ์กด์ฌํ๋ฉด DB๋ฅผ ๊ฑฐ์น์ง ์๊ณ 0.005์ด ๋ง์ ์ฆ์ ์ ์ ์๊ฒ ์๋ตํฉ๋๋ค.Cache Miss (์บ์ ์คํจ): Redis์ ๋ฐ์ดํฐ๊ฐ ์์ผ๋ฉด ๋ฐ์ดํฐ๋ฒ ์ด์ค(PostgreSQL)์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์จ ๋ค, ์ด๋ฅผ Redis์ ์ ์ฅ(TTL 5๋ถ)ํ๊ณ ์ ์ ์๊ฒ ์๋ตํฉ๋๋ค.
3. ํด๊ฒฐ์ฑ 2๋จ๊ณ: ์บ์ ์คํฌํผ๋(Cache Stampede)์ ๋ฌดํจํ(Invalidation) ๋์
์บ์๋ฅผ ๋์ ํ ๋ ๊ฐ์ฅ ์ฃผ์ํด์ผ ํ ํจ์ ์ด ๋ฐ๋ก ์บ์ ์คํฌํผ๋(Cache Stampede) ํ์๊ณผ ๋ฐ์ดํฐ ๋ถ์ผ์น(Stale Data) ๋ฌธ์ ์ ๋๋ค.
์บ์ ๋ฌดํจํ (Cache Invalidation): ๊ด๋ฆฌ์๊ฐ ์๋ก์ด ๊ณต์ง์ฌํญ์ ๋ฑ๋กํ๊ฑฐ๋ ์ธ๊ธฐ๊ธ ์์๊ฐ ๊ธ๋ณํ์ ๋, ๊ธฐ์กด ์บ์๊ฐ ๋ง๋ฃ๋ ๋๊น์ง ์ ์ ๊ฐ ์๋ ๋ฐ์ดํฐ๋ฅผ ๋ณด๊ณ ์์ผ๋ฉด ์ ๋ฉ๋๋ค. ์ด๋ฅผ ์ํด ๊ฒ์๊ธ ์์ฑ/์์ API ์คํ ์
await redis_client.delete("main:popular_posts")์ฝ๋๋ฅผ ์ฐ๋ํ์ฌ, ์ด๋ฒคํธ ๋ฐ์ ์ฆ์ ์บ์๋ฅผ ์์์ ์ผ๋ก ์ญ์ ํ๋๋ก ์ค๊ณํ์ต๋๋ค.TTL(Time-To-Live) ๋ถ์ฐ: ๋ชจ๋ ์บ์์ ๋ง๋ฃ ์๊ฐ์ ๋์ผํ๊ฒ 300์ด(5๋ถ)๋ก ์ค์ ํ๋ฉด, 5๋ถ๋ง๋ค ๋ชจ๋ ์บ์๊ฐ ๋์์ ํฐ์ง๋ฉด์ DB๋ก ์๊ฐ์ ์ธ ํธ๋ํฝ ํญ์ฃผ๊ฐ ๋ชฐ๋ฆฝ๋๋ค. ์ด๋ฅผ ๋ง๊ธฐ ์ํด TTL ๊ฐ์
random.randint(-30, 30)์ด ๋จ์์ ์งํฐ(Jitter)๋ฅผ ๋ถ์ฌํ์ฌ ์บ์ ๋ง๋ฃ ์์ ์ ์์ฐ์ค๋ฝ๊ฒ ๋ถ์ฐ์์ผฐ์ต๋๋ค.
๋งบ์ผ๋ฉฐ: 45ms์ ๊ธฐ์ , SEO์ ์ ๋์ผ์ค ์น์ธ์ ์ง๋ฆ๊ธธ
Redis ์บ์ฑ ๋ ์ด์ด๋ฅผ ์ ์ฉํ ํ, ๋ฉ์ธ ํ์ด์ง ๋ก๋ฉ ์๋๋ ๊ทธ์ผ๋ง๋ก ๊ฐ๋ฒฝ์ ๋ง์ดํ์ต๋๋ค.
TTFB (Time to First Byte): 850ms -> 45ms (94.7% ๊ฐ์)
DB CPU ์ ์ ์จ: ํผํฌ ํ์ 85% -> 8% ์ดํ ์ ์ง
๊ตฌ๊ธ ์์น ์ฝ์ LCP (Largest Contentful Paint): 2.8์ด -> 0.9์ด ๋ฌ์ฑ
๊ตฌ๊ธ ์ ๋์ผ์ค 2026 ์ฒดํฌ๋ฆฌ์คํธ์ ํต์ฌ ์์์ธ "Fast loading website (๋น ๋ฅธ ๋ก๋ฉ ์๋)"๋ ๋จ์ํ CSS๋ ์ด๋ฏธ์ง๋ฅผ ์์ถํ๋ ๊ฒ๋ง์ผ๋ก ์๋ฒฝํด์ง์ง ์์ต๋๋ค. ๋ฐฑ์๋ ๋จ์์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ฌด๊ฑฐ์ด ์ฐ์ฐ์ ๋ฉ๋ชจ๋ฆฌ ์์ค์ผ๋ก ๋์ด์ฌ๋ ค ์๋ต ์๋(TTFB)๋ฅผ ๊ทน๋ํํ๋ ์์ง๋์ด๋ง์ด ๋ท๋ฐ์นจ๋์ด์ผ ํฉ๋๋ค.
1์ธ ๊ฐ๋ฐ์๋ก์ ์ธํ๋ผ ํจ์จ์ฑ์ ๊ทน๋ํํ๊ณ ์ ์ ์ ๊ฒ์์์ง ๋ด ๋ชจ๋์๊ฒ ๊ทน์์ ์พ์ ํจ์ ์ ๋ฌผํ ์ด๋ฒ Redis ์บ์ฑ ๊ตฌ์ถ ๊ฒฝํ์, ์น์ฌ์ดํธ์ ๊ธฐ์ ์ ์์ฑ๋(E-E-A-T)๋ฅผ ์ฆ๋ช ํ๋ ๊ฐ๋ ฅํ ์์ฐ์ด ๋ ๊ฒ์ ๋๋ค.
์์ฃผ ๋ฌป๋ ์ง๋ฌธ (FAQ)
Q1. ๋ฉ๋ชจ๋ฆฌ ์ฉ๋์ด ์์ ์ ์ฌ์ VPS ์๋ฒ์์๋ Redis๋ฅผ ์ฌ์ฉํ ์ ์๋์?
A. ๋ค, ์ถฉ๋ถํ ๊ฐ๋ฅํฉ๋๋ค. Redis๋ C์ธ์ด๋ก ์์ฑ๋์ด ๋งค์ฐ ๊ฐ๋ณ๊ธฐ ๋๋ฌธ์, ํ
์คํธ ํํ์ ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๊ฐ ์์ฒ ๊ฐ๋ฅผ ์บ์ฑํ๋๋ผ๋ ์๋ชจ๋๋ RAM ์ฉ๋์ ์์ญ ๋ฉ๊ฐ๋ฐ์ดํธ(MB) ์์ค์ ๋ถ๊ณผํฉ๋๋ค. ๋ํ redis.conf ํ์ผ์์ maxmemory 256mb์ ๊ฐ์ด ์ต๋ ๋ฉ๋ชจ๋ฆฌ ํ๋๋ฅผ ์ง์ ํ๊ณ , ๋ฉ๋ชจ๋ฆฌ๊ฐ ์ฐจ๋ฉด ๊ฐ์ฅ ์ค๋๋ ์บ์๋ฅผ ์๋์ผ๋ก ์ง์ฐ๋ maxmemory-policy allkeys-lru ์ต์
์ ์ค์ ํด ๋๋ฉด ์ ์ฌ์ ์๋ฒ์์๋ ์์ ์ ์ผ๋ก ์ด์ํ ์ ์์ต๋๋ค.
Q2. Redis ์บ์์ ๋ธ๋ผ์ฐ์ ์บ์(HTTP Cache-Control)๋ ์ด๋ป๊ฒ ๋ค๋ฅธ๊ฐ์?
A. ๋ธ๋ผ์ฐ์ ์บ์๋ ์ ์ ์ ๊ฐ์ธ ๊ธฐ๊ธฐ(์ค๋งํธํฐ, PC)์ ์ ์ ํ์ผ(์ด๋ฏธ์ง, CSS, JS)์ ์ ์ฅํ์ฌ ์ฌ๋ค์ด๋ก๋๋ฅผ ๋ง๋ ํด๋ผ์ด์ธํธ ์ธก ๊ธฐ์ ์ ๋๋ค. ๋ฐ๋ฉด Redis ์บ์๋ ์๋ฒ ๋ด๋ถ์ ๋ฉ๋ชจ๋ฆฌ์ DB ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๋ API ์๋ต ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ์ฌ, ๋ชจ๋ ์ ์ ๊ฐ ๊ณตํต์ผ๋ก ์์ฒญํ๋ ๋ฐฑ์๋ ์ฐ์ฐ ๋ถํ๋ฅผ ์ค์ฌ์ฃผ๋ ์๋ฒ ์ธก ๊ธฐ์ ์ ๋๋ค. ๋ ๊ธฐ์ ์ ํจ๊ป ์ ์ฉํด์ผ ์๋ฒฝํ ์๋ ์ต์ ํ๊ฐ ์ด๋ฃจ์ด์ง๋๋ค.
Q3. ์ค์๊ฐ์ฑ์ด ์ค์ํ ๋๊ธ์ด๋ ์ข์์ ์๋ Redis์ ์บ์ฑํด๋ ๋๋์?
A. ์ค์๊ฐ์ด ์๋ช
์ธ ๋ฐ์ดํฐ๋ ์บ์ TTL์ 3~5์ด ์ ๋๋ก ๋งค์ฐ ์งง๊ฒ ๊ฐ์ ธ๊ฐ๊ฑฐ๋, DB์ ์ง์ ์ฐ๊ธฐ ์ ์ Redis์ INCR(์์์ ์ฆ๊ฐ) ๋ช
๋ น์ด๋ฅผ ํ์ฉํด ๋ฉ๋ชจ๋ฆฌ์์ ๋จผ์ ์ซ์๋ฅผ ์ฌ๋ฆฐ ๋ค ์ฃผ๊ธฐ์ ์ผ๋ก DB์ ๋๊ธฐํํ๋ 'Write-Back' ํจํด์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ๋ฐ์ดํฐ์ ํน์ฑ์ ๋ง์ถฐ ์ ์ ํ ์บ์ฑ ์ ๋ต์ ์ ํํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค.
๐ฌ ๋๊ธ 0๊ฐ