๊ฐ์ธํ์ ์ฐฉ์: ํจ์ AI์ LLM ๋น์ฉ ํญ๋ฐ ํด๊ฒฐ๊ธฐ
MiroFish V3.2๋ก API ํธ์ถ์ O(N)์์ O(K) ํ์ด๋ธ๋ฆฌ๋ ์ํคํ ์ฒ๋ก ์ค์ธ ๋ฐฉ๋ฒ
๊ฐ์ ํผํ (Virtual Try-On)๊ณผ AI ์คํ์ผ๋ง์ ์ธํ๋ผ ์ธก๋ฉด์์ ๊ณ ์ ํ ๊ณผ์ ๋ฅผ ์ ์ํฉ๋๋ค: ์ด๊ฐ์ธํ ํธ๋ฆด๋ ๋ง (The Hyper-Personalization Trilemma). 10,000๋ช ์ ํ์ฑ ์ฌ์ฉ์์๊ฒ ๋งค์ผ 3๊ฐ์ "์ค๋์ ์ถ์ฒ ์ฝ๋(OOTD)"๋ฅผ ์์ฑํ๊ณ ์ ํ์ง๋ง, ๋งค์ผ 10,000๊ฐ์ ๊ณ ์ ํ ์คํ์ผ ํ๋กฌํํธ๋ฅผ Qwen3.5-Flash์ ๊ฐ์ LLM์ผ๋ก ๋ผ์ฐํ ํ๋ฉด ์ฆ๊ฐ์ ์ธ API ํ์ฐ(API bankruptcy)์ ์ง๋ฉดํ๊ฒ ๋ฉ๋๋ค. ์ด๋ฌํ ํญ๋ชฉ์ ์ง์ ์์ฑํ๋ ์๊ฐ ๋ณต์ก๋๋ ์ฌ์ฉ์ ๊ธฐ๋ฐ(N)์ ๋น๋กํ์ฌ ์ผ๋ก ํ์ฅ๋ฉ๋๋ค.
ํธ๋ํฝ์ด ์ฆ๊ฐํ ๋ ๋จ์ํ LLM ์์ฑ์๋ง ์์กดํ๋ ๊ฒ์ ์ฌ์ ์ ์ธ ์์ด ํ์์ ๋๋ค. ์ต๊ทผ ์งํ๋ MiroFish V3.2 ๋ฐฑ์๋ ๊ฐํธ์์, ์์ง๋์ด๋ง ํ์ ์๊ฒฉํ ๋ชฉํ๋ฅผ ์ธ์ ์ต๋๋ค: 1:1 ๋ง์ถคํ ํ๋ ์ด์ ํ์ง์ ์ ์งํ๋ฉด์ API ํธ์ถ์ ์๊ฐ ๋ณต์ก๋๋ฅผ ์์ ๋ก ๊ธฐํ๊ธ์์ ์ผ๋ก ์ค์ด๋ ๊ฒ์ด์์ต๋๋คโ์ฌ๊ธฐ์ ๋ ์๊ฒฉํ๊ฒ ์ ํ๋, ์ ํํ ์คํ์ผ ํด๋ฌ์คํฐ ์ธํธ๋ฅผ ๋ํ๋ ๋๋ค.
์ฐ๋ฆฌ๊ฐ ์ด๋ป๊ฒ "๊ฐ์ธํ์ ์ฐฉ์(Illusion of Personalization)"๋ฅผ ์ค๊ณํ๋์ง ์๊ฐํฉ๋๋ค.
๐ ์ํคํ ์ฒ์ ์์ ํ ๋ถ๋ฆฌ (Phase A vs. Phase B)
V3.2 ์ด์ ์๋ ์ฌ์ฉ์๊ฐ ์ฑ์ ์ด ๋๋ง๋ค Supabase์์ ์คํ์ผ ์ ํธ๋๋ฅผ ์กฐํํ๊ณ , ์ด๋ฅผ LLM ํ๋กฌํํธ์ ๋ด์ Qwen์ด ์์์ JSON ๋ฐฐ์ด์ ๋ฐํํ ๋๊น์ง ๋๊ธฐํ์ต๋๋ค. ์ด๋ ๋๋ฆฌ๊ณ ๋น์ฉ์ด ๋ง์ด ๋ค์์ต๋๋ค.
์ฐ๋ฆฌ๋ ์์ฑ ์์ง์ ์๋น ๋ ์ด์ด์์ ๋ฌผ๋ฆฌ์ ์ผ๋ก ๋ถ๋ฆฌํจ์ผ๋ก์จ ์ด๋ฅผ ํด๊ฒฐํ์ต๋๋ค.
N+1 ์ฟผ๋ฆฌ ๋ฐฉ์ด
์ฐ๋ฆฌ๋ ๋จ์ผ ๋๋ ์ฟผ๋ฆฌ๋ก ์ฌ์ฉ์ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ ๋ฐฐ์น ์์
์ ์์ํฉ๋๋ค. ๋งค์ผ ๋ฐค ๋ฐฐ์น ์์
์ด ์์๋ ๋ ์ฌ์ฉ์์ Style DNA, JSONB Rules(์ข์์/์ซ์ด์), ๊ทธ๋ฆฌ๊ณ Timezone์ ์ถ์ถํฉ๋๋ค. ์ด๋ ์ด๊ธฐ AI ๋ํผ(wrapper) ์ฑ๋ค์ ๊ดด๋กญํ๋ ์ ํ์ ์ธ N+1 ๋ฐ์ดํฐ๋ฒ ์ด์ค ํธ๋ฉ์ ๋ฐฉ์งํฉ๋๋ค.
Phase A: ๊ฒฐ์ ๋ก ์ ํด๋ฌ์คํฐ๋ง (O(K))
๋ฒ์ LLM ํธ์ถ ๋์ ์ฌ์ฉ์๋ค์ ๊ฒฐ์ ๋ก ์ ์ธ ์๊ฐ์ ๋ฒํท์ผ๋ก ๊ทธ๋ฃนํํฉ๋๋ค. ์ฌ์ฉ์ ํ๋กํ์ ํด์๋์ด ์๋ฅผ ๋ค์ด 20260420_Minimal_Sunny์ ๊ฐ์ ํด๋ฌ์คํฐ ID์ ๋งคํ๋ฉ๋๋ค.
10,000๋ช
์ ์ฌ์ฉ์์ ๋ํด ์๊ณ ๋ฆฌ์ฆ์ ์ผ๋ฐ์ ์ผ๋ก ์ ํํ 30๊ฐ์ ํด๋ฌ์คํฐ๋ฅผ ์์ฑํฉ๋๋ค.
๋ฐ๋ผ์ LLM์ ์ ํํ 30๋ฒ๋ง ํธ์ถ๋ฉ๋๋ค. ๊ฐ API ํธ์ถ์ ํด๋น ํด๋ฌ์คํฐ์ ๋งคํ๋ 20๊ฐ์ ๊ณ ํ์ง ์๋ฅ ๊ตฌ์ฑ(๋ฎ 10๊ฐ, ์ธ์ถ(NightOut) 10๊ฐ)์ ๋ฐ์ง๋ "์บ์ ํ"์ ์์ฑํฉ๋๋ค. ์ด๊ฒ๋ค์ ๊ณ ์ ์ธ๋ฉ๋ชจ๋ฆฌ Redis ๋ ์ด์ด์ ์ ์ฅ๋ฉ๋๋ค.
Phase B: ์๋น ๋ ์ด์ด (The Serving Layer)
์ค์ ์ฌ์ฉ์ ์์ฒญ ๋ฃจํ ๋ด๋ถโ์ฌ์ฉ์๊ฐ ์ฑ์ ์ฌ๋ ์๊ฐโLLM ํธ์ถ์ 0ํ์ ๋๋ค. ์ฌ์ฉ์๊ฐ ๋ณด๋ ๋ชจ๋ ๊ฒ์ 20๊ฐ ํญ๋ชฉ์ ์บ์ ํ์์ ์ง์ ๊ฐ์ ธ์ต๋๋ค. ์ด ๋ง๋ฒ์ ํ์ ๊ฒ์ํ๊ณ UI๋ฅผ ๋ ๋๋งํ๋ ์ฌ์ด์ ๋ฐ์ํ๋ ํ์ดํ๋ผ์ธ์ ์ ์ ์ผ๋ก ์์กดํฉ๋๋ค.
โ๏ธ ์ ๋ก ์ฝ์คํธ "๋ผ์คํธ ๋ง์ผ" ๊ฐ์ธํ ํ์ดํ๋ผ์ธ
๋ง์ฝ 300๋ช
์ ์ฌ์ฉ์๊ฐ ๋์ผํ Minimal_Sunny ํด๋ฌ์คํฐ๋ฅผ ๊ณต์ ํ๋ค๋ฉด, ์ด๋ค์ด ์์ ํ ๋๊ฐ์ ์ฑ์ ๋ณด๊ฒ ๋๋ ๊ฒ์ ์ด๋ป๊ฒ ๋ง์ ์ ์์๊น์? ์ฐ๋ฆฌ๋ LLM์ ๋ค์ ํธ์ถํ์ง ์๊ณ ๋ ๋งค์ฐ ๋น ๋ฅธ 5๋จ๊ณ Python/Node ํ์ดํ๋ผ์ธ์ ์ฌ์ฉํด "1:1 ๊ฐ์ธํ์ ์ฐฉ์"๋ฅผ ๋ง๋ค์ด๋
๋๋ค.
1. ์์ธกํ ์๊ฐ ํํฐ (Anticipatory Time Filter)
์ฑ์ ์ฌ์ฉ์์ ๋๋ฐ์ด์ค IANA ์๊ฐ๋์ ๋๊ธฐํํฉ๋๋ค. ์ฌ๋ฌด์ค ์ง์ฅ์ธ๋ค์ด ์ ๋ ํ๋์ ๊ณํํ๊ธฐ ์์ํ์ฌ ์ ํ์จ์ด ๊ฐ์ฅ ๋์ ์ฌ๋ฆฌ์ ์๊ฐ์ธ **์คํ 3์(15:00)**๊ฐ ๋๋ฉด, ํ์ดํ๋ผ์ธ์ด ์๋์ผ๋ก "NightOut" ํญ๋ชฉ์ ์ฐ์ ์์๋ฅผ ๋์ ๋๋ค.
2. ํ๋ ํํฐ (JSONB Veto)
์ฌ์ฉ์๊ฐ ๋ช
์ํ style_rules.disliked_categories๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํด๋ฌ์คํฐ ํญ๋ชฉ์ ์ฆ์ ๊ฑฐ๋ถํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ์ฌ์ฉ์๊ฐ ์น๋ง(skirts)๋ฅผ ๊ฑฐ๋ถํ๋ฉด ์ฆ์ ๋ชฉ๋ก์์ ์ ์ธ๋ฉ๋๋ค.
UI ์ถฉ๋์ ๋ฐฉ์งํ๊ธฐ ์ํด **๊ฑฐ๋ถ ์ผ์ค์ผ์ด๋(Veto Cascade)**๋ฅผ ๊ตฌํํฉ๋๋ค: ์๊ฒฉํ ๊ฑฐ๋ถ ๊ท์น์ผ๋ก ์ธํด ์ฐ๋ฐ์ ์ผ๋ก ์บ์ ํ์ด 0๊ฐ ํญ๋ชฉ์ผ๋ก ์ค์ด๋ค ๊ฒฝ์ฐ, ์ผ์ค์ผ์ด๋๋ UI๊ฐ ํญ์ ๋ ๋๋ง๋ ์ ์๋๋ก ๊ฐ์ฅ ์๊ฒฉํ ํํฐ๋ฅผ ์ฐ์ํ๊ฒ ๋กค๋ฐฑํฉ๋๋ค.
3. ๊ฐ์ค์น ์ ์ ๋ฐ ์ํํธ ์ฌ์ ๋ ฌ (Weighted Scoring & Soft Re-Rank)
์์ดํ
๋ค์ ๊ฒฐ์ ๋ก ์ ๋์ง(nudge)๋ฅผ ๋ฐ์ต๋๋ค. preferred_colors์ ๋ํด ๋ฐฐ์๋ฅผ ์ ์ฉํ๊ณ liked_categories์ ๋ํด ๋ฅผ ์ ์ฉํฉ๋๋ค. ์คํ์ผ์ ์์ง๋ ฅ์ ์ฒ๋ฆฌํ๊ธฐ ์ํด ์ด๊ฒฝ๋ **32์ฐจ์ ์ฝ์ฌ์ธ ํ๋ก์(32D Cosine Proxy)**๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์ฃ์ง ๋
ธ๋์ ๋ฌด๊ฑฐ์ด ์ ๊ธฐ๊ฐ๋ฐ์ดํธ ๋ชจ๋ธ์ด๋ numpy ํ
์๋ฅผ ๋ก๋ํ๋ ๋์ , ๋ฐ๋ฆฌ์ด ๋จ์์ ์ฌ์ ๋ ฌ์ ์ํด ์๋ฒ ๋ฉ์ ๋จ ์ธ ๊ฐ์ง ํต์ฌ ์ฐจ์(Vibe, Trend, Dare)์ผ๋ก ์ถ์ํฉ๋๋ค.
4. 1e-9 ์งํฐ (๋์ ์ ์ฒ๋ฆฌ๊ธฐ)
์ ํ๋ ์บ์์ ์ํํธ ๊ท์น์ ์ ์ฉํ ๋, ๋ง์ ์์๋ค์ด ์ ํํ ๋์ผํ ์ ์(์: 4.5)๋ฅผ ๋ฐ๊ฒ ๋ฉ๋๋ค. ๋์ ์ ๋ํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ ๋ ฌ์ ๋น๊ฒฐ์ ๋ก ์ ์ด๋ฉฐ ๋ฆฌ๋ ๋๋ง ์ ์์ดํ ์ด ์๊ฐ์ ์ผ๋ก "๊น๋นก๊ฑฐ๋ ค(flicker)" ์ฐฉ์๋ฅผ ๊นฐ ์ ์์ต๋๋ค. ์ฐ๋ฆฌ๋ ์์ ๋ ผ๋ฆฌ๋ฅผ ๋ฐฉํดํ์ง ์์ผ๋ฉด์ ์ ๋์ ์ธ ๊ณ์ธต ๊ตฌ์กฐ๋ฅผ ๋ณด์ฅํ๊ธฐ ์ํด ๊ทน์๋์ ์งํฐ(jitter)๋ฅผ ์ฃผ์ ํฉ๋๋ค:
import random def score_outfit(item, user_prefs): base_score = apply_soft_rules(item, user_prefs) # 1e-9 ์งํฐ๋ ๋์ ์ ๋ํด ์๋ฒฝํ๊ณ ์์ ์ ์ธ ์ ํ์ ๋ณด์ฅํฉ๋๋ค jitter = random.random() * 1e-9 return base_score + jitter
5. ์ด์ง์ญ์ UI ์ฃผ์ (Hyper-Local UI Injection)
๋ง์ง๋ง์ผ๋ก, UI ํ ์คํธ ๊ณต๊ฐ์ ์ฌ์ฉ์์ ์์น๋ฅผ ๋์ ์ผ๋ก ํฉ์ฑํฉ๋๋ค. ์ผ๋ฐ์ ์ธ "์ค๋์ ์ฝ๋์ ๋๋ค"๊ฐ *"Torrance์์์ ์คํ๋ฅผ ์ํ ๊ฐ๋ณ๊ณ ๋ฏธ๋๋ฉํ ๋ฃฉ"*์ผ๋ก ๋ณํ๋ฉ๋๋ค. ์ฐ๋ฆฌ๋ ์ด๊ฒ์ ํฌ์ถ ์ฟ ํค ํจ๊ณผ(fortune-cookie effect)๋ผ๊ณ ๋ถ๋ฆ ๋๋ค. AI ์ปดํจํ ๋น์ฉ์ด ์ ํ ๋ค์ง ์์ผ๋ฉด์๋ ์ฌ๋ฆฌ์ ๊ฐ๊ทน์ ๋ฉ์ฐ๊ณ , ์ผ๋ฐ์ ์ธ ํด๋ฌ์คํฐ ๊ฒฐ๊ณผ๋ฌผ์ด ๋ง์น ๋ง์ถคํ์ผ๋ก ๋๊ปด์ง๊ฒ ๋ง๋ญ๋๋ค.
์๋์์ ๋ผ์คํธ ๋ง์ผ ํ์ดํ๋ผ์ธ ์๋ฎฌ๋ ์ดํฐ๋ฅผ ํ ์คํธํด๋ณด์ธ์:
Breaks sorting ties cleanly without database roundtrips.
A breezy minimalist look for your Afternoon in Torrance
Live Re-Ranking Pool (0 LLM Calls)
Beige Silk Midi Skirt
Navy Oversized Blazer
White Linen Wide Pants
Black Velvet Slip Dress
Red Leather Mini Skirt
โก ์๋ฌต์ ํผ๋๋ฐฑ (์ฃ์ง ํจ์๋ณด๋ค DB ํธ๋ฆฌ๊ฑฐ๊ฐ ์ฐ์ํ ์ด์ )
์์คํ
์ ์ฑ๋ฅ์ ์๋ฌต์ ํผ๋๋ฐฑ ๋ฃจํ์ ํ์ง์ ๋น๋กํฉ๋๋ค. ์ฐ๋ฆฌ๋ "์ฝ๋ ์คํํธ(Cold Start)" ๋ฌธ์ ๋ฅผ ์ฐํํ๋ฉด์ JSONB Rules๋ฅผ ์ง์์ ์ผ๋ก ์ธ๋ฐํ๊ฒ ์กฐ์ ํ๊ธฐ ์ํด ์ฌ์ฉ์ "์ข์์"์์ ์ ํธ๋๋ฅผ ๋งค๋๋ฝ๊ฒ ์ถ์ถํ ๋ฐฉ๋ฒ์ด ํ์ํ์ต๋๋ค.
ํธ๋ ์ด๋์คํ ๋ถ์:
์ฒ์์๋ Like ์ด๋ฒคํธ๋ฅผ Postgres ์ธ์คํด์ค๋ฅผ ์
๋ฐ์ดํธํ๋ Serverless Edge Functions๋ก ๋ณด๋์ต๋๋ค. ํ์ง๋ง ์ฐ๋ฆฌ๋ ์ด๋ฅผ ๋น ๋ฅด๊ฒ ๊ฑฐ์ ํ์ต๋๋ค. ์ฃ์ง ํจ์๋ 50-300ms์ HTTP ์ค๋ฒํค๋์ ์ฝ๋ ์คํํธ ๋ฌธ์ ๋ฅผ ๊ฒช์ต๋๋ค. ๋ ์น๋ช
์ ์ธ ๊ฒ์, ์ฃ์ง ํจ์์ ๋ฎคํ
์ด์
(mutation) ๋ก์ง์ ๋ ๊ฒฝ์ฐ DB ํธ๋์ญ์
์ด ์คํจํ์ ๋ ๋ณต์กํ ์๋ ์ฌ์๋ ๋ก์ง์ ์์ฑํด์ผ ํ๋ค๋ ์ ์ด์์ต๋๋ค.
์น์: ์ฐ๋ฆฌ๋ Native PostgreSQL Triggers์ PL/pgSQL์ ์ฌ์ฉํ์ฌ ์ด ๋ก์ง์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ ์ด์ด๋ก ์ง์ ์ด๋์์ผฐ์ต๋๋ค. ~2ms ๋ด์ ์๋ฒฝํ ์์์ฑ(atomicity)์ผ๋ก ์คํ๋ฉ๋๋ค.
์์์ '์ข์์' ํ์๊ฐ ๋๋ฉด ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ ์ฆ์ ์นดํ
๊ณ ๋ฆฌ ์นํ๋๋ฅผ ๊ณ์ฐํ๊ณ Style DNA JSONB ์ด์ ๋ค์ดํฐ๋ธ๋ก ์
์ํธํฉ๋๋ค:
CREATE OR REPLACE FUNCTION update_user_style_dna() RETURNS TRIGGER AS $$ BEGIN -- || ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ JSONB ๋ถ๋ถ ๋ณํฉ(Partial deep merge) UPDATE users SET style_dna = COALESCE(style_dna, '{}'::jsonb) || jsonb_build_object( 'preferred_colors', array_to_json(ARRAY( SELECT DISTINCT elements FROM ( SELECT jsonb_array_elements_text(COALESCE(style_dna->'preferred_colors', '[]'::jsonb)) AS elements UNION SELECT NEW.item_color AS elements ) AS unique_colors )) ) WHERE id = NEW.user_id; RETURN NEW; END; $$ LANGUAGE plpgsql;
๐ง ๊ฒฐ๋ก : SmartWorkLab์ ์์ง๋์ด๋ง ์ฒ ํ
์ง์ ํ ์์ง๋์ด๋ง์ AWS ์ฒญ๊ตฌ์๊ฐ ๋ถํ ๋๊น์ง ๋ฌธ์ ์ LLM ์ฐ์ฐ ๋ฆฌ์์ค๋ฅผ ์์๋ถ๋ ๊ฒ์ด ์๋๋๋ค. ํ๋ฅญํ ์์ง๋์ด๋ง์ ๋ฐ์ดํฐ ํ์ดํ๋ผ์ธ, ์ ๋ต์ ํด๋ฌ์คํฐ๋ง, ๊ทธ๋ฆฌ๊ณ ์ฌ๋ฆฌ์ ์ธ UX ํ์ด๋ฐ์ ํจ๊ณผ์ ์ผ๋ก ํ์ฉํ๋ ๊ฒ์ ๋๋ค.
์ API ์ข ์์ฑ์ ์ ๊ฑฐํ๊ณ ์ต์ ํ๋ ๋ผ์คํธ ๋ง์ผ ํ์ดํ๋ผ์ธ์ ๋ง์คํฐํจ์ผ๋ก์จ, ์ฐ๋ฆฌ๋ API "๋น์ฉ ํญ๋ฐ"์ ํด๊ฒฐํ์ ๋ฟ๋ง ์๋๋ผ ์ด๊ฐ์ธํ๋ฅผ ๋ฌดํํ ํ์ฅํ ์ ์๋ ์ํคํ ์ฒ ํ๋ ์์ํฌ๋ฅผ ๊ตฌ์ถํ์ต๋๋ค.
Updated 4/20/2026