Skip to content

๐ŸŒฑ ์ด์ฝ”์—์ฝ”(Ecoยฒ) BE

License

Notifications You must be signed in to change notification settings

eco2-team/backend

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

2,298 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

Ecoยฒ Backend

Version: v1.1.1 | Changelog

Ecoยฒ ์„œ๋น„์Šค ๋™์ž‘ ์˜์ƒ

โ–ถ๏ธ Just Do it

Production-level AI Agent - Tool Calling ๊ธฐ๋ฐ˜ ์žฅ์†Œ / ๋‚ ์”จ / ์žฌํ™œ์šฉ ๊ฐ€๊ฒฉ ๊ฒ€์ƒ‰, ์›น ๊ฒ€์ƒ‰, ์ด๋ฏธ์ง€ ์ƒ์„ฑ, ํ๊ธฐ๋ฌผ ์ด๋ฏธ์ง€ ๋ถ„๋ฆฌ๋ฐฐ์ถœ ์ธ์‹ ๋ฐ ๋ถ„๋ฅ˜, ์ฑ—๋ด‡ ๊ธฐ๋Šฅ ์ œ๊ณต

  • Self-managed Kubernetes 24-Nodes ํด๋Ÿฌ์Šคํ„ฐ์—์„œ Istio Service Mesh(mTLS, Auth Offloading)์™€ ArgoCD GitOps๋กœ ์šด์˜ํ•ฉ๋‹ˆ๋‹ค.
  • Scan API (LLM x2): VU 1000 ๋ถ€ํ•˜ ํ…Œ์ŠคํŠธ ์™„๋ฃŒ โ€” 97.8% ์„ฑ๊ณต๋ฅ , 373.4 req/m throughput, E2E P95 173.3s
  • Redis Streams + Pub/Sub + State KV ๊ธฐ๋ฐ˜ Event Bus Layer๋กœ ์‹ค์‹œ๊ฐ„ SSE ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ , KEDA๋กœ ์ด๋ฒคํŠธ ๋“œ๋ฆฌ๋ธ ์˜คํ† ์Šค์ผ€์ผ๋ง์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  • RabbitMQ + TaskIQ/Celery ๋น„๋™๊ธฐ Task Queue๋กœ AI ํŒŒ์ดํ”„๋ผ์ธ์„ ์ฒ˜๋ฆฌํ•˜๊ณ , EFK + Jaeger + LangSmith๋กœ ๋กœ๊น…ยทํŠธ๋ ˆ์ด์‹ฑ์„ ์ˆ˜์ง‘ํ•ฉ๋‹ˆ๋‹ค.
  • 8๊ฐœ ๋„๋ฉ”์ธ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค(auth, users, scan, chat, character, location, info, images)๋ฅผ ๋ชจ๋…ธ๋ ˆํฌ๋กœ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
  • Service: https://frontend.dev.growbin.app

Service Architecture

Untitled-2025-12-29-1721
Edge Layer               : Route 53, AWS ALB, Istio Ingress Gateway
Service Layer            : auth, users, scan, character, location, chat, info, images (w/ Envoy Sidecar)
Integration Layer        :
  - Event Bus          : Redis Streams + Pub/Sub + State KV, Event Router, SSE Gateway
  - Worker (Storage)     : auth-worker, auth-Bus, users-worker, character-worker, character-match-worker, info-worker
  - Worker (AI)          : scan-worker (Visionโ†’Ruleโ†’Answerโ†’Reward), chat-worker (LangGraph Multi-Agent)
Persistence Layer        : PostgreSQL, Redis (Blacklist/State/Streams/Pub-Sub/Cache)
Platform Layer           : ArgoCD, Istiod, KEDA, Prometheus, Grafana, Kiali, Jaeger, LangSmith, EFK Stack

๋ณธ ์„œ๋น„์Šค๋Š” 5-Layer Architecture๋กœ ๊ตฌ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

  • Edge Layer: AWS ALB๊ฐ€ SSL Termination์„ ์ฒ˜๋ฆฌํ•˜๊ณ , ํŠธ๋ž˜ํ”ฝ์„ Istio Ingress Gateway๋กœ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. Gateway๋Š” VirtualService ๊ทœ์น™์— ๋”ฐ๋ผ North-South ํŠธ๋ž˜ํ”ฝ์„ ๋ผ์šฐํŒ…ํ•ฉ๋‹ˆ๋‹ค.
  • Service Layer: ๋ชจ๋“  ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค๋Š” Istio Service Mesh ๋‚ด์—์„œ ๋™์ž‘ํ•˜๋ฉฐ, Envoy Sidecar๋ฅผ ํ†ตํ•ด mTLS ํ†ต์‹ , ํŠธ๋ž˜ํ”ฝ ์ œ์–ด, ๋ฉ”ํŠธ๋ฆญ ์ˆ˜์ง‘์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. authโ†’users gRPC ํ†ต์‹ , chatโ†’images gRPC ํ†ต์‹ ์œผ๋กœ ๋„๋ฉ”์ธ ๊ฐ„ ๋™๊ธฐ ํ˜ธ์ถœ์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
  • Integration Layer - Event Bus: Redis Streams(๋‚ด๊ตฌ์„ฑ) + Pub/Sub(์‹ค์‹œ๊ฐ„) + State KV(๋ณต๊ตฌ) 3-tier ์ด๋ฒคํŠธ ์•„ํ‚คํ…์ฒ˜๋กœ SSE ํŒŒ์ดํ”„๋ผ์ธ์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. RabbitMQ + TaskIQ/Celery ๋น„๋™๊ธฐ Task Queue๋กœ AI ํŒŒ์ดํ”„๋ผ์ธ์„ ์ฒ˜๋ฆฌํ•˜๊ณ , KEDA๊ฐ€ ์ด๋ฒคํŠธ ๋“œ๋ฆฌ๋ธ ์˜คํ† ์Šค์ผ€์ผ๋ง์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  • Integration Layer - Worker: Storage Worker(worker-storage ๋…ธ๋“œ)๋Š” Persistence Layer์— ์ ‘๊ทผํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ๋™๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค. auth-worker๋Š” RabbitMQ์—์„œ ๋ธ”๋ž™๋ฆฌ์ŠคํŠธ ์ด๋ฒคํŠธ๋ฅผ ์†Œ๋น„ํ•ด Redis์— ์ €์žฅํ•˜๊ณ , auth-Bus๋Š” Redis Outbox ํŒจํ„ด์œผ๋กœ ์‹คํŒจ ์ด๋ฒคํŠธ๋ฅผ ์žฌ๋ฐœํ–‰ํ•ฉ๋‹ˆ๋‹ค. users-worker๋Š” Celery Batch๋กœ ์บ๋ฆญํ„ฐ ์†Œ์œ ๊ถŒ์„ PostgreSQL์— UPSERTํ•ฉ๋‹ˆ๋‹ค. info-worker๋Š” Celery Beat๋กœ ํ™˜๊ฒฝ ๋‰ด์Šค๋ฅผ ์ฃผ๊ธฐ์ ์œผ๋กœ ์ˆ˜์ง‘ํ•ฉ๋‹ˆ๋‹ค. AI Worker(worker-ai ๋…ธ๋“œ)๋Š” OpenAI/Google API์™€ ํ†ต์‹ ํ•˜๋ฉฐ, scan-worker๊ฐ€ Visionโ†’Ruleโ†’Answerโ†’Reward ์ฒด์ธ์„ gevent pool๋กœ ์ฒ˜๋ฆฌํ•˜๊ณ , chat-worker๊ฐ€ LangGraph Multi-Agent๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  • Persistence Layer: ์„œ๋น„์Šค๋Š” ์˜์†์„ฑ์„ ์œ„ํ•ด PostgreSQL, Redis๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. Redis๋Š” ์šฉ๋„๋ณ„๋กœ ๋ถ„๋ฆฌ(Blacklist/OAuth State/Streams/Pub-Sub/Cache)๋˜๋ฉฐ, Helm Chart๋กœ ๊ด€๋ฆฌ๋˜๋Š” ๋…๋ฆฝ์ ์ธ ๋ฐ์ดํ„ฐ ์ธํ”„๋ผ์ž…๋‹ˆ๋‹ค.
  • Platform Layer: Istiod๊ฐ€ Service Mesh๋ฅผ ์ œ์–ดํ•˜๊ณ , ArgoCD๊ฐ€ GitOps ๋™๊ธฐํ™”๋ฅผ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค. KEDA๊ฐ€ ์ด๋ฒคํŠธ ๋“œ๋ฆฌ๋ธ ์˜คํ† ์Šค์ผ€์ผ๋ง์„ ์ˆ˜ํ–‰ํ•˜๊ณ , Observability ์Šคํƒ(Prometheus/Grafana/Kiali, Jaeger, LangSmith, EFK Stack)์ด ๋ฉ”ํŠธ๋ฆญยทํŠธ๋ ˆ์ด์‹ฑยท๋กœ๊น…์„ ํ†ตํ•ฉ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

๊ฐ ๊ณ„์ธต์€ ์„œ๋กœ ๋…๋ฆฝ์ ์œผ๋กœ ๊ธฐ๋Šฅํ•˜๋„๋ก ์„ค๊ณ„๋˜์—ˆ์œผ๋ฉฐ, Platform Layer๊ฐ€ ์ „ ๊ณ„์ธต์„ ์ œ์–ด ๋ฐ ๊ด€์ธกํ•ฉ๋‹ˆ๋‹ค. ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์„ ์ „์ œ๋กœ ํ•œ Self-manged Kubernetes ๊ธฐ๋ฐ˜ ํด๋Ÿฌ์Šคํ„ฐ๋กœ ์ปจํ…Œ์ด๋„ˆํ™”๋œ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. Istio Service Mesh๋ฅผ ๋„์ž…ํ•˜์—ฌ mTLS ๋ณด์•ˆ ํ†ต์‹ , ํŠธ๋ž˜ํ”ฝ ์ œ์–ด(VirtualService), ์ธ์ฆ ์œ„์ž„(Auth Offloading)์„ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค. ํด๋Ÿฌ์Šคํ„ฐ์˜ ์•ˆ์ •์„ฑ๊ณผ ์„ฑ๋Šฅ์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด ๋ชจ๋‹ˆํ„ฐ๋ง ์‹œ์Šคํ…œ์„ ๋„์ž…, IaC(Infrastructure as Code) ๋ฐ GitOps ํŒŒ์ดํ”„๋ผ์ธ์„ ๊ตฌ์ถ•ํ•ด ๋ชจ๋…ธ๋ ˆํฌ ๊ธฐ๋ฐ˜ ์ฝ”๋“œ๋ฒ ์ด์Šค๊ฐ€ SSOT(Single Source Of Truth)๋กœ ๊ธฐ๋Šฅํ•˜๋„๋ก ์ œ์ž‘๋˜์—ˆ์Šต๋‹ˆ๋‹ค.


LLM Image Classification Pipeline (Scan API, Chat API ์ด๋ฏธ์ง€ ์ธ์‹)

Status: Production Ready โ€” VU 1000 ๋ถ€ํ•˜ ํ…Œ์ŠคํŠธ ์™„๋ฃŒ, 97.8% ์„ฑ๊ณต๋ฅ 

ECA49AD6-EA0C-4957-8891-8C6FA12A2916

1. End-to-End Flow (User โ†’ SSE)

flowchart LR
    subgraph Client["๐Ÿ‘ค Client"]
        CL["Browser/App"]
    end

    subgraph API["๐ŸŒ Scan API"]
        SA["POST /api/v1/scan<br/>Dispatch Chain"]
    end

    subgraph MQ["๐Ÿ“ฌ RabbitMQ"]
        VQ[("scan.vision")]
        RQ[("scan.rule")]
        AQ[("scan.answer")]
        WQ[("scan.reward")]
    end

    subgraph Workers["๐Ÿ”ง Celery Workers (gevent)"]
        VW["Vision Worker<br/>GPT-5.2 Vision"]
        RW["Rule Worker<br/>Lite RAG"]
        AW["Answer Worker<br/>GPT-5.2-mini"]
        WW["Reward Worker<br/>๋ณด์ƒ ํŒ์ •"]
    end

    subgraph Streams["๐Ÿ“Š Redis Streams"]
        RS[("scan:events:{shard}<br/>(4 shards)")]
    end

    subgraph EventBus["๐Ÿ”€ Event Bus"]
        ER["Event Router<br/>(XREADGROUP)"]
        PS[("Pub/Sub<br/>sse:events:{hash}")]
    end

    subgraph SSE["๐ŸŒ SSE Gateway"]
        SG["Pub/Sub Subscriber"]
    end

    CL -->|"POST /scan"| SA
    SA -->|"Dispatch"| VQ
    SA -.->|"202 Accepted + job_id"| CL

    VQ --> VW
    VW -->|"Chain"| RQ
    RQ --> RW
    RW -->|"Chain"| AQ
    AQ --> AW
    AW -->|"Chain"| WQ
    WQ --> WW

    VW & RW & AW & WW -->|"XADD stage"| RS
    RS -->|"XREADGROUP"| ER
    ER -->|"PUBLISH"| PS
    PS -->|"SUBSCRIBE"| SG
    SG -->|"SSE data:"| CL

    classDef client fill:#e1bee7,stroke:#7b1fa2,stroke-width:2px,color:#000
    classDef api fill:#b2dfdb,stroke:#00796b,stroke-width:2px,color:#000
    classDef mq fill:#bbdefb,stroke:#1976d2,stroke-width:2px,color:#000
    classDef worker fill:#fff9c4,stroke:#f9a825,stroke-width:2px,color:#000
    classDef streams fill:#ffccbc,stroke:#e64a19,stroke-width:2px,color:#000
    classDef eventbus fill:#b3e5fc,stroke:#0288d1,stroke-width:2px,color:#000
    classDef sse fill:#c8e6c9,stroke:#388e3c,stroke-width:2px,color:#000

    class CL client
    class SA api
    class VQ,RQ,AQ,WQ mq
    class VW,RW,AW,WW worker
    class RS streams
    class ER,PS eventbus
    class SG sse
Loading

2. Pipeline Stages

Stage Worker ์„ค๋ช… LLM
Vision scan-worker ํ๊ธฐ๋ฌผ ์ด๋ฏธ์ง€ ๋ถ„๋ฅ˜ (item_class_list.yaml 86๊ฐœ ํ’ˆ๋ชฉ) GPT-5.2 Vision
Rule scan-worker Lite RAG ๊ทœ์ • ๊ฒ€์ƒ‰ (situation_tags.yaml 80๊ฐœ ์ƒํ™ฉ) -
Answer scan-worker ๋ถ„๋ฆฌ๋ฐฐ์ถœ ๊ฐ€์ด๋“œ ์ƒ์„ฑ (18๊ฐœ JSON ๊ทœ์ •) GPT-5.2-mini
Reward scan-worker ์บ๋ฆญํ„ฐ ๋ณด์ƒ ํŒ์ • + PostgreSQL Batch Insert -

3. Event Bus Architecture

์ปดํฌ๋„ŒํŠธ ์—ญํ•  ์Šค์ผ€์ผ๋ง
Redis Streams ์ด๋ฒคํŠธ ๋กœ๊ทธ (๋‚ด๊ตฌ์„ฑ), 4 shards ๋ถ„์‚ฐ -
Event Router Streams โ†’ Pub/Sub Fan-out, Consumer Group KEDA (Pending)
Redis Pub/Sub ์‹ค์‹œ๊ฐ„ Fan-out, job_id ํ•ด์‹œ ๊ธฐ๋ฐ˜ ์ฑ„๋„ ์ƒค๋”ฉ (4 channels) ์ „์šฉ ์ธ์Šคํ„ด์Šค
SSE Gateway Pub/Sub โ†’ Client, State ๋ณต๊ตฌ KEDA (์—ฐ๊ฒฐ ์ˆ˜)

4. VU 500-1000 ๋ถ€ํ•˜ ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ

OpenAI Tier 4, KEDA minReplicas=2 / maxReplicas=5

VU ์š”์ฒญ ์ˆ˜ ์„ฑ๊ณต๋ฅ  Throughput E2E P95 ์‹คํŒจ ์ƒํƒœ
500 1,408 99.7% 351.9 req/m 108.3s 4 โœ… ์•ˆ์ •
600 1,408 99.7% 351.9 req/m 108.3s 4 โœ… ์•ˆ์ •
700 1,496 99.2% 329.1 req/m 122.3s 11 โœ… ์•ˆ์ •
800 1,386 99.7% 367.3 req/m 144.6s 4 โœ… ์•ˆ์ •
900 1,540 99.7% 405.5 req/m 149.6s 4 โญ ๊ถŒ์žฅ ํ•œ๊ณ„
1000 1,518 97.8% 373.4 req/m 173.3s 33 โš ๏ธ Probe Timeout

๋ณ‘๋ชฉ ๋ถ„์„:

  • Celery Probe I/O-bound (LLM API ๋Œ€๊ธฐ) ์ทจ์•ฝ์  ์‹๋ณ„
  • OpenAI Tier 4 TPM 61% ์‚ฌ์šฉ (์—ฌ์œ )
  • Redis Pub/Sub ์ฑ„๋„ ์ƒค๋”ฉ์œผ๋กœ Hot Key ๋ถ„์‚ฐ

Chat Agent Architecture (LangGraph)

Status: Production Ready (OpenAI Agents SDK + Responses API Fallback)

1. LangGraph StateGraph (Intent-Routed Workflow)

app.get_graph().draw_mermaid() (์ฐธ๊ณ )

Pipeline Flow:

Intent Classification โ†’ Dynamic Router (Send API) โ†’ 10์ข… ์„œ๋ธŒ์—์ด์ „ํŠธ ๋ณ‘๋ ฌ ์‹คํ–‰ โ†’ Aggregator (๊ฒฐ๊ณผ ์ˆ˜์ง‘ยทํ•„์ˆ˜ ์ปจํ…์ŠคํŠธ ๊ฒ€์ฆ) โ†’ Dynamic Summarization (ํ† ํฐ ์ž„๊ณ„๊ฐ’ ์ดˆ๊ณผ ์‹œ OpenCode ์Šคํƒ€์ผ ์••์ถ•) โ†’ Answer Node (ํ† ํฐ ์ŠคํŠธ๋ฆฌ๋ฐ)

Dynamic Routing (Send API)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋Ÿฐํƒ€์ž„์— ๋ณต์ˆ˜ ๋…ธ๋“œ๋ฅผ ๋ณ‘๋ ฌ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

  • Multi-Intent Fanout: additional_intents โ†’ ๊ฐ๊ฐ ๋ณ‘๋ ฌ Send
  • Intent ๊ธฐ๋ฐ˜ Enrichment: waste โ†’ weather ์ž๋™ ์ถ”๊ฐ€ (๋ถ„๋ฆฌ๋ฐฐ์ถœ + ๋‚ ์”จ ํŒ)
  • Conditional Enrichment: user_location ์žˆ์œผ๋ฉด weather ์ž๋™ ์ถ”๊ฐ€
  • Context Compression: ํ† ํฐ ์ž„๊ณ„๊ฐ’ ์ดˆ๊ณผ ์‹œ summarize ๋…ธ๋“œ์—์„œ ์ด์ „ ๋Œ€ํ™” ์š”์•ฝ
%%{init: {'flowchart': {'curve': 'linear'}}}%%
graph TD;
    __start__([<p>__start__</p>]):::first
    intent(intent)
    vision(vision)
    router{router}
    waste_rag(waste_rag)
    character(character)
    location(location)
    weather(weather)
    collection_point(collection_point)
    bulk_waste(bulk_waste)
    recyclable_price(recyclable_price)
    image_generation(image_generation)
    web_search(web_search)
    general(general)
    aggregator(aggregator)
    summarize(summarize)
    answer(answer)
    __end__([<p>__end__</p>]):::last

    __start__ --> intent;
    intent -->|image_url exists| vision;
    intent -->|no image| router;
    vision --> router;
    router -->|WASTE| waste_rag;
    router -->|CHARACTER| character;
    router -->|LOCATION| location;
    router -->|WEATHER| weather;
    router -->|COLLECTION_POINT| collection_point;
    router -->|BULK_WASTE| bulk_waste;
    router -->|RECYCLABLE_PRICE| recyclable_price;
    router -->|IMAGE_GENERATION| image_generation;
    router -->|WEB_SEARCH| web_search;
    router -->|GENERAL| general;
    waste_rag --> aggregator;
    character --> aggregator;
    location --> aggregator;
    weather --> aggregator;
    collection_point --> aggregator;
    bulk_waste --> aggregator;
    recyclable_price --> aggregator;
    image_generation --> aggregator;
    web_search --> aggregator;
    general --> aggregator;
    aggregator -->|tokens > threshold| summarize;
    aggregator -->|tokens <= threshold| answer;
    summarize --> answer;
    answer --> __end__;

    classDef first fill:#b2dfdb,stroke:#00796b,stroke-width:2px
    classDef last fill:#ffccbc,stroke:#e64a19,stroke-width:2px
Loading

2. Event Bus (Token Streaming Pipeline)

ํ† ํฐ ์ŠคํŠธ๋ฆฌ๋ฐ์„ ์œ„ํ•œ Redis Streams + Pub/Sub ์ด์ค‘ ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค.

flowchart LR
    subgraph Worker["๐Ÿค– Chat Worker"]
        AN["Answer Node<br/>(Token Generator)"]
    end

    subgraph Streams["๐Ÿ“Š Redis Streams"]
        RS[("chat:events:{shard}<br/>(XADD)")]
    end

    subgraph Router["๐Ÿ”€ Event Router"]
        ER["Consumer Group<br/>(XREADGROUP)"]
        RC["Pending Reclaimer<br/>(XCLAIM)"]
    end

    subgraph State["๐Ÿ’พ State KV"]
        SK[("chat:state:{job_id}<br/>(SETEX 30s)")]
    end

    subgraph PubSub["๐Ÿ“ก Redis Pub/Sub"]
        PS[("sse:events:{job_id}<br/>(PUBLISH)")]
    end

    subgraph Gateway["๐ŸŒ SSE Gateway"]
        SG["Pub/Sub Subscriber<br/>(SUBSCRIBE)"]
    end

    subgraph Client["๐Ÿ‘ค Client"]
        CL["Browser/App<br/>(EventSource)"]
    end

    AN -->|"XADD token"| RS
    RS -->|"XREADGROUP"| ER
    RS -.->|"XCLAIM (5min idle)"| RC
    RC -.->|"reprocess"| ER
    ER -->|"SETEX state"| SK
    ER -->|"PUBLISH + XACK"| PS
    SK -.->|"GET (reconnect)"| SG
    PS -->|"SUBSCRIBE"| SG
    SG -->|"SSE data:"| CL

    classDef worker fill:#fff9c4,stroke:#f9a825,stroke-width:2px,color:#000
    classDef streams fill:#ffccbc,stroke:#e64a19,stroke-width:2px,color:#000
    classDef router fill:#b3e5fc,stroke:#0288d1,stroke-width:2px,color:#000
    classDef state fill:#d1c4e9,stroke:#512da8,stroke-width:2px,color:#000
    classDef pubsub fill:#c8e6c9,stroke:#388e3c,stroke-width:2px,color:#000
    classDef gateway fill:#b2dfdb,stroke:#00796b,stroke-width:2px,color:#000
    classDef client fill:#e1bee7,stroke:#7b1fa2,stroke-width:2px,color:#000

    class AN worker
    class RS streams
    class ER,RC router
    class SK state
    class PS pubsub
    class SG gateway
    class CL client
Loading
์ปดํฌ๋„ŒํŠธ ์—ญํ•  ์Šค์ผ€์ผ๋ง
Event Router Streams โ†’ Pub/Sub Fan-out, State ๊ฐฑ์‹ , ๋ฉฑ๋“ฑ์„ฑ ๋ณด์žฅ KEDA (Pending ๋ฉ”์‹œ์ง€)
SSE Gateway Pub/Sub โ†’ Client, State ๋ณต๊ตฌ, Streams Catch-up KEDA (์—ฐ๊ฒฐ ์ˆ˜)
Redis Streams ์ด๋ฒคํŠธ ๋กœ๊ทธ (๋‚ด๊ตฌ์„ฑ), Consumer Group ์ง€์› ์ƒค๋”ฉ (4 shards)
Redis Pub/Sub ์‹ค์‹œ๊ฐ„ Fan-out, job_id ํ•ด์‹œ ๊ธฐ๋ฐ˜ ์ฑ„๋„ ์ƒค๋”ฉ (4 channels) ์ „์šฉ ์ธ์Šคํ„ด์Šค
State KV ์ตœ์‹  ์ƒํƒœ ์Šค๋ƒ…์ƒท, ์žฌ์ ‘์† ๋ณต๊ตฌ Streams Redis ๊ณต์œ 

Intent Classification

Intent ์„ค๋ช… Agent External API / Tool
WASTE ํ๊ธฐ๋ฌผ ๋ถ„๋ฅ˜/๋ถ„๋ฆฌ๋ฐฐ์ถœ ์งˆ๋ฌธ Waste RAG Agent Tag-Based Contextual Retrieval
CHARACTER ์บ๋ฆญํ„ฐ ๊ด€๋ จ ์งˆ๋ฌธ Character Agent gRPC (Character API)
WEATHER ๋‚ ์”จ ์ •๋ณด ์š”์ฒญ Weather Agent ๊ธฐ์ƒ์ฒญ API (Tool Calling)
LOCATION ์œ„์น˜/์ˆ˜๊ฑฐํ•จ ๊ฒ€์ƒ‰ Location Agent Kakao Local API (Tool Calling)
BULK_WASTE ๋Œ€ํ˜•ํ๊ธฐ๋ฌผ ๋ฐฐ์ถœ ์งˆ๋ฌธ Bulk Waste Agent ์ž์น˜๊ตฌ API (Tool Calling)
RECYCLABLE_PRICE ์žฌํ™œ์šฉํ’ˆ ์‹œ์„ธ ์กฐํšŒ Recyclable Price Agent ์‹œ์„ธ API (Tool Calling)
COLLECTION_POINT ์ˆ˜๊ฑฐํ•จ/์žฌํ™œ์šฉ์„ผํ„ฐ ๊ฒ€์ƒ‰ Collection Point Agent Kakao Local API (Tool Calling)
IMAGE_GENERATION ์ด๋ฏธ์ง€ ์ƒ์„ฑ ์š”์ฒญ Image Generation Agent Gemini 3 Pro Image + gRPC (Images API)
WEB_SEARCH ์›น ๊ฒ€์ƒ‰ ์š”์ฒญ Web Search Agent OpenAI web_search / Gemini Google Search (Native)
GENERAL ์ผ๋ฐ˜ ์งˆ๋ฌธ General Agent -

์ฃผ์š” ํŠน์ง•

ํ•ญ๋ชฉ ์„ค๋ช…
LangGraph Multi-Agent apps/chat_worker/infrastructure/orchestration/langgraph/nodes/์— 10๊ฐœ Intent๋ณ„ Agent ๊ตฌํ˜„. Intent Classification โ†’ Dynamic Router (Send API) โ†’ Aggregator โ†’ Answer Node ํŒŒ์ดํ”„๋ผ์ธ.
Intent Classification LangGraph Intent Node์—์„œ with_structured_output ๊ธฐ๋ฐ˜ 10๊ฐœ Intent ๋ถ„๋ฅ˜. Multi-Intent Fanout์œผ๋กœ ๋ณต์ˆ˜ Intent ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ.
Tool Calling Agents LLM Native Tool Calling ๊ธฐ๋ฐ˜ 6๊ฐœ ๋…ธ๋“œ โ€” weather, bulk_waste, recyclable_price, location, collection_point (Kakao Local API), web_search (OpenAI/Gemini Native).
Aggregator ๋ณ‘๋ ฌ ์‹คํ–‰๋œ ์„œ๋ธŒ์—์ด์ „ํŠธ ๊ฒฐ๊ณผ ์ˆ˜์ง‘ + ํ•„์ˆ˜ ์ปจํ…์ŠคํŠธ(weather, location) ๊ฒ€์ฆ. Fail-Open Policy๋กœ ๋ณด์กฐ ์ •๋ณด ๋ˆ„๋ฝ ์‹œ์—๋„ ์ง„ํ–‰.
Dynamic Summarization ํ† ํฐ ์ž„๊ณ„๊ฐ’(4K) ์ดˆ๊ณผ ์‹œ OpenCode ์Šคํƒ€์ผ ์ด์ „ ๋Œ€ํ™” ์š”์•ฝ. ํ•ต์‹ฌ ์ •๋ณด ๋ณด์กด + ์ปจํ…์ŠคํŠธ ์••์ถ•.
์ด๋ฏธ์ง€ ์ƒ์„ฑ Gemini 3 Pro Image๋กœ ์ด๋ฏธ์ง€ ์ƒ์„ฑ, gRPC๋กœ Images API์— ์—…๋กœ๋“œ ํ›„ CDN URL ๋ฐ˜ํ™˜. Character Reference ์ง€์›.
Token Streaming LangChain LLM ์ง์ ‘ ํ˜ธ์ถœ๋กœ ํ† ํฐ ๋‹จ์œ„ ์ŠคํŠธ๋ฆฌ๋ฐ. Event Router โ†’ Pub/Sub โ†’ SSE Gateway ์‹ค์‹œ๊ฐ„ ์ „๋‹ฌ.
Checkpoint Redis Primary + PostgreSQL Async Sync ์•„ํ‚คํ…์ฒ˜. Worker๋Š” Redis์— ์ง์ ‘ ์“ฐ๊ณ , checkpoint_syncer๊ฐ€ ๋น„๋™๊ธฐ๋กœ PG์— ์•„์นด์ด๋ธŒ.
๋ฉ”์‹œ์ง€ ์˜์†ํ™” chat-persistence-consumer๊ฐ€ Redis Streams โ†’ PostgreSQL๋กœ ๋Œ€ํ™” ๊ธฐ๋ก ์ €์žฅ.
API ๊ตฌ์กฐ apps/chat/ โ†’ FastAPI + apps/chat_worker/ LangGraph Agent. /api/v1/chat ์—”๋“œํฌ์ธํŠธ๋Š” RabbitMQ๋กœ TaskIQ Job ๋ฐœํ–‰.
ํŠธ๋ ˆ์ด์‹ฑ LangSmith ์—ฐ๋™์œผ๋กœ LangGraph ์‹คํ–‰ ํŠธ๋ ˆ์ด์Šค ์ˆ˜์ง‘. OpenTelemetry E2E ๋ถ„์‚ฐ ํŠธ๋ ˆ์ด์‹ฑ.
  • Multi-Intent Fanout: Send API๋กœ ๋ณต์ˆ˜ Intent ๋ณ‘๋ ฌ ์‹คํ–‰ + Enrichment ์ž๋™ ์ถ”๊ฐ€ (waste โ†’ weather)
  • Tool Calling ๊ธฐ๋ฐ˜ API ํ†ตํ•ฉ: LLM Native (OpenAI web_search, Gemini Google Search) + Kakao Local API (HTTP)
  • gRPC ๋‚ด๋ถ€ ํ†ต์‹ : Character API, Images API (Location gRPC deprecated โ†’ Kakao HTTP ๋Œ€์ฒด)
  • Token Streaming: LangChain LLM ์ง์ ‘ ํ˜ธ์ถœ๋กœ ์‹ค์‹œ๊ฐ„ ํ† ํฐ ์ „๋‹ฌ
  • ์ด๋ฏธ์ง€ ์ƒ์„ฑ: Gemini ๊ธฐ๋ฐ˜ ์ƒ์„ฑ + gRPC CDN ์—…๋กœ๋“œ
  • Character Reference: ์บ๋ฆญํ„ฐ ์ด๋ฆ„ ๊ฐ์ง€ ๋ฐ ์ปจํ…์ŠคํŠธ ์ „๋‹ฌ
  • Redis Primary Checkpoint: Redis ์ง์ ‘ ์“ฐ๊ธฐ + PostgreSQL Async Sync

3. LangGraph Checkpoint Architecture (Redis Primary + PG Async Sync)

Worker โ†’ PostgreSQL ์ง์ ‘ ์—ฐ๊ฒฐ๋กœ ์ธํ•œ Connection Pool ๊ณ ๊ฐˆ ๋ฌธ์ œ ํ•ด๊ฒฐ

flowchart LR
    subgraph Worker["๐Ÿค– Chat Worker"]
        LG["LangGraph<br/>Parallel Nodes"]
        RC["RedisCheckpointer<br/>(~1ms write)"]
    end

    subgraph Redis["๐Ÿ“Š Redis"]
        RK[("checkpoint:{thread_id}<br/>TTL 24h")]
    end

    subgraph Syncer["๐Ÿ”„ Checkpoint Syncer"]
        CS["Batch Processor<br/>(5s interval, 50/batch)"]
    end

    subgraph PostgreSQL["๐Ÿ’พ PostgreSQL"]
        PG[("checkpoints table<br/>(Archive)")]
    end

    LG -->|"put()"| RC
    RC -->|"SET + queue"| RK
    RK -->|"poll"| CS
    CS -->|"UPSERT batch"| PG
    PG -.->|"cold start read"| RC

    classDef worker fill:#fff9c4,stroke:#f9a825,stroke-width:2px,color:#000
    classDef redis fill:#ffccbc,stroke:#e64a19,stroke-width:2px,color:#000
    classDef syncer fill:#b3e5fc,stroke:#0288d1,stroke-width:2px,color:#000
    classDef pg fill:#c8e6c9,stroke:#388e3c,stroke-width:2px,color:#000

    class LG,RC worker
    class RK redis
    class CS syncer
    class PG pg
Loading
์ปดํฌ๋„ŒํŠธ ์—ญํ•  ์—ฐ๊ฒฐ ํ’€
RedisCheckpointer Worker์—์„œ ์ง์ ‘ Redis ์“ฐ๊ธฐ (~1ms) Redis ์—ฐ๊ฒฐ
ReadThroughCheckpointer Redis miss ์‹œ PG ์ฝ๊ธฐ + Redis ์Šน๊ฒฉ PG 2 conn (์ฝ๊ธฐ ์ „์šฉ)
checkpoint_syncer Redis โ†’ PG ๋น„๋™๊ธฐ ๋ฐฐ์น˜ ๋™๊ธฐํ™” PG 5 conn (๋‹จ์ผ ํ”„๋กœ์„ธ์Šค)

๊ฐœ์„  ํšจ๊ณผ: Worker PG ์—ฐ๊ฒฐ 192 โ†’ 8 (96% ๊ฐ์†Œ), KEDA 10 pods ์Šค์ผ€์ผ๋ง ์‹œ์—๋„ 45 conn ์œ ์ง€


Services Snapshot

์„œ๋น„์Šค ์„ค๋ช… ์ด๋ฏธ์ง€/ํƒœ๊ทธ
auth JWT ์ธ์ฆ/์ธ๊ฐ€ (RS256) docker.io/mng990/eco2:auth-{env}-latest
users ์‚ฌ์šฉ์ž ์ •๋ณด ๊ด€๋ฆฌ (gRPC) docker.io/mng990/eco2:users-{env}-latest
scan Lite RAG + GPT-5.2 Vision ํ๊ธฐ๋ฌผ ๋ถ„๋ฅ˜ docker.io/mng990/eco2:scan-{env}-latest
chat LangGraph Multi-Agent ์ฑ—๋ด‡ (10 Intents) docker.io/mng990/eco2:chat-{env}-latest
character ์บ๋ฆญํ„ฐ ์ œ๊ณต docker.io/mng990/eco2:character-{env}-latest
location ์ง€๋„/์ˆ˜๊ฑฐํ•จ ๊ฒ€์ƒ‰ docker.io/mng990/eco2:location-{env}-latest
info ํ™˜๊ฒฝ ๋‰ด์Šค ์กฐํšŒ docker.io/mng990/eco2:info-{env}-latest
images ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ (gRPC) docker.io/mng990/eco2:images-{env}-latest

Celery Workers โœ…

Worker ๋…ธ๋“œ ์„ค๋ช… Queue Scaling
scan-worker worker-ai AI ํŒŒ์ดํ”„๋ผ์ธ ์ฒ˜๋ฆฌ (Visionโ†’Ruleโ†’Answerโ†’Reward) scan.vision, scan.rule, scan.answer, scan.reward KEDA (RabbitMQ)
character-match-worker worker-storage ์บ๋ฆญํ„ฐ ๋งค์นญ ์ฒ˜๋ฆฌ character.match KEDA (RabbitMQ)
character-worker worker-storage ์บ๋ฆญํ„ฐ ์†Œ์œ ๊ถŒ ์ €์žฅ (batch) character.reward KEDA (RabbitMQ)
users-worker worker-storage ์œ ์ € ์บ๋ฆญํ„ฐ ์†Œ์œ ๊ถŒ PostgreSQL UPSERT users.character KEDA (RabbitMQ)
info-worker worker-storage ํ™˜๊ฒฝ ๋‰ด์Šค ์ˆ˜์ง‘ (Celery Beat) info.collect_news ๋‹จ์ผ ์ธ์Šคํ„ด์Šค
celery-beat worker-storage DLQ ์žฌ์ฒ˜๋ฆฌ ์Šค์ผ€์ค„๋ง - ๋‹จ์ผ ์ธ์Šคํ„ด์Šค

TaskIQ Workers (LangGraph) โœ…

Worker ๋…ธ๋“œ ์„ค๋ช… Exchange / Queue Scaling
chat-worker worker-ai LangGraph Multi-Agent ์‹คํ–‰ (10 Intents, timeout 120s, retry 2) chat_tasks โ†’ chat.process KEDA (RabbitMQ)
checkpoint-syncer worker-storage Redis โ†’ PostgreSQL ์ฒดํฌํฌ์ธํŠธ ๋ฐฐ์น˜ ๋™๊ธฐํ™” (5s interval) - ๋‹จ์ผ ์ธ์Šคํ„ด์Šค
chat-persistence-consumer worker-storage Redis Streams โ†’ PostgreSQL ๋ฉ”์‹œ์ง€ ์ €์žฅ - ๋‹จ์ผ ์ธ์Šคํ„ด์Šค
๐Ÿ“‹ TaskIQ Worker ์ƒ์„ธ ์„ค์ •
# chat-worker ์„ค์ •
Exchange: chat_tasks (direct)
Queue: chat.process (DLX, TTL ์„ค์ •)
Workers: 4 (concurrent)
Max Async Tasks: 10
Timeout: 120s
Retry: 2ํšŒ

# ํŠธ๋ ˆ์ด์‹ฑ
- aio-pika Instrumentation (MQ ๋ฉ”์‹œ์ง€ ์ถ”์ )
- OpenAI/Gemini Instrumentation (LLM API ํ˜ธ์ถœ)
- LangSmith OTEL (LangGraph โ†’ Jaeger ํ†ตํ•ฉ)

Token Blacklist Event Bus โœ…

JWT ํ† ํฐ ๋ฌดํšจํ™”๋ฅผ ์œ„ํ•œ Redis-backed Outbox ํŒจํ„ด. ๋ถ„์‚ฐ ํ™˜๊ฒฝ์—์„œ ๋ธ”๋ž™๋ฆฌ์ŠคํŠธ ์ด๋ฒคํŠธ์˜ At-Least-Once ์ „๋‹ฌ์„ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค.

Worker ๋…ธ๋“œ ์„ค๋ช… ์ž…๋ ฅ ์ถœ๋ ฅ
auth-worker worker-storage ๋ธ”๋ž™๋ฆฌ์ŠคํŠธ ์ด๋ฒคํŠธ ์ˆ˜์‹  โ†’ Redis KV ์ €์žฅ RabbitMQ blacklist.events Redis blacklist:{jti}
auth-Bus worker-storage Redis Outbox ํด๋ง โ†’ RabbitMQ ์žฌ๋ฐœํ–‰ Redis outbox:blacklist RabbitMQ blacklist.events

Event Bus Components โœ…

Component ์„ค๋ช… Scaling
event-router Redis Streams โ†’ Pub/Sub Fan-out, State KV ๊ด€๋ฆฌ KEDA (Streams Pending)
sse-gateway Pub/Sub ๊ตฌ๋… โ†’ SSE ํด๋ผ์ด์–ธํŠธ ์ „๋‹ฌ KEDA (์—ฐ๊ฒฐ ์ˆ˜)

๊ฐ ๋„๋ฉ”์ธ์€ ๊ณตํ†ต FastAPI ํ…œํ”Œ๋ฆฟยทDockerfileยทํ…Œ์ŠคํŠธ๋ฅผ ๊ณต์œ ํ•˜๊ณ , Kustomize overlay์—์„œ ์ด๋ฏธ์ง€ ํƒœ๊ทธ์™€ ConfigMap/Secret๋งŒ ๋ถ„๊ธฐํ•ฉ๋‹ˆ๋‹ค.


Async Task Pipeline (Scan: Celery + GEVENT, Chat: Taskiq + Asyncio) โœ…

Status: RabbitMQ + Celery + KEDA ์ด๋ฒคํŠธ ๋“œ๋ฆฌ๋ธ ์˜คํ† ์Šค์ผ€์ผ๋ง ์™„๋ฃŒ

flowchart LR
    subgraph Client["๐Ÿ‘ค Client"]
        CL["Browser/App"]
    end

    subgraph API["๐ŸŒ Scan API"]
        SA["POST /api/v1/scan<br/>Dispatch Chain"]
    end

    subgraph MQ["๐Ÿ“ฌ RabbitMQ"]
        VQ[("scan.vision")]
        RQ[("scan.rule")]
        AQ[("scan.answer")]
        WQ[("scan.reward")]
    end

    subgraph Workers["๐Ÿ”ง Celery Workers (gevent)"]
        VW["Vision Worker<br/>GPT Vision ๋ถ„์„"]
        RW["Rule Worker<br/>RAG ๊ทœ์ • ๊ฒ€์ƒ‰"]
        AW["Answer Worker<br/>GPT ๋‹ต๋ณ€ ์ƒ์„ฑ"]
        WW["Reward Worker<br/>๋ณด์ƒ ํŒ์ •"]
    end

    subgraph External["๐Ÿค– OpenAI API"]
        OAI["GPT-4o Vision<br/>GPT-4o-mini"]
    end

    subgraph Streams["๐Ÿ“Š Redis Streams"]
        RS[("scan:events:*<br/>(Event Bus๋กœ ์ „๋‹ฌ)")]
    end

    subgraph DB["๐Ÿ’พ PostgreSQL"]
        PG[("๊ฒฐ๊ณผ ์ €์žฅ")]
    end

    subgraph Scale["โšก KEDA"]
        KD["ํ ๊ธธ์ด ๊ธฐ๋ฐ˜<br/>์˜คํ† ์Šค์ผ€์ผ๋ง"]
    end

    CL -->|POST| SA
    SA -->|Dispatch| VQ
    SA -.->|202 Accepted| CL

    VQ --> VW
    VW -->|API Call| OAI
    VW -->|XADD| RS
    VW -->|Chain| RQ

    RQ --> RW
    RW -->|XADD| RS
    RW -->|Chain| AQ

    AQ --> AW
    AW -->|API Call| OAI
    AW -->|XADD| RS
    AW -->|Chain| WQ

    WQ --> WW
    WW -->|Batch Insert| PG
    WW -->|XADD stage=done| RS

    KD -.->|Monitor| MQ
    KD -.->|Scale| Workers

    classDef client fill:#e1bee7,stroke:#7b1fa2,stroke-width:2px,color:#000
    classDef api fill:#b2dfdb,stroke:#00796b,stroke-width:2px,color:#000
    classDef mq fill:#bbdefb,stroke:#1976d2,stroke-width:2px,color:#000
    classDef worker fill:#fff9c4,stroke:#f9a825,stroke-width:2px,color:#000
    classDef external fill:#ffcc80,stroke:#e65100,stroke-width:2px,color:#000
    classDef streams fill:#ffccbc,stroke:#e64a19,stroke-width:2px,color:#000
    classDef db fill:#c8e6c9,stroke:#388e3c,stroke-width:2px,color:#000
    classDef scale fill:#b3e5fc,stroke:#0288d1,stroke-width:2px,color:#000

    class CL client
    class SA api
    class VQ,RQ,AQ,WQ mq
    class VW,RW,AW,WW worker
    class OAI external
    class RS streams
    class PG db
    class KD scale
Loading
๐Ÿ“‹ Sequence Diagram (์ƒ์„ธ ํ๋ฆ„)
sequenceDiagram
    participant Client
    participant ScanAPI as Scan API
    participant RabbitMQ
    participant KEDA
    participant VisionWorker as Vision Worker
    participant RuleWorker as Rule Worker
    participant AnswerWorker as Answer Worker
    participant RewardWorker as Reward Worker
    participant RedisStreams as Redis Streams
    participant PostgreSQL

    Client->>ScanAPI: POST /api/v1/scan
    ScanAPI->>RabbitMQ: Dispatch Chain (job_id)
    ScanAPI-->>Client: 202 Accepted {job_id}

    KEDA->>RabbitMQ: ํ ๊ธธ์ด ๋ชจ๋‹ˆํ„ฐ๋ง
    KEDA->>VisionWorker: Scale Up (๋ฉ”์‹œ์ง€ ์ฆ๊ฐ€ ์‹œ)

    RabbitMQ->>VisionWorker: scan.vision queue
    VisionWorker->>VisionWorker: GPT Vision ๋ถ„์„
    VisionWorker->>RedisStreams: XADD stage=vision
    VisionWorker->>RabbitMQ: Chain โ†’ scan.rule

    RabbitMQ->>RuleWorker: scan.rule queue
    RuleWorker->>RuleWorker: RAG ๊ทœ์ • ๊ฒ€์ƒ‰
    RuleWorker->>RedisStreams: XADD stage=rule

    RuleWorker->>RabbitMQ: Chain โ†’ scan.answer
    RabbitMQ->>AnswerWorker: scan.answer queue
    AnswerWorker->>AnswerWorker: GPT ๋‹ต๋ณ€ ์ƒ์„ฑ
    AnswerWorker->>RedisStreams: XADD stage=answer

    AnswerWorker->>RabbitMQ: Chain โ†’ reward.character
    RabbitMQ->>RewardWorker: reward.character queue
    RewardWorker->>PostgreSQL (Batch): ๋ณด์ƒ ์ €์žฅ
    RewardWorker->>RedisStreams: XADD stage=done
Loading
์ปดํฌ๋„ŒํŠธ ์—ญํ•  Queue ์Šค์ผ€์ผ๋ง
scan-worker Vision ๋ถ„์„, RAG ๊ฒ€์ƒ‰, ๋‹ต๋ณ€ ์ƒ์„ฑ, ๋ณด์ƒ ํŒ์ • scan.vision, scan.rule, scan.answer, scan.reward KEDA (ํ ๊ธธ์ด)
character-match-worker ์บ๋ฆญํ„ฐ ๋งค์นญ ์ฒ˜๋ฆฌ character.match KEDA (ํ ๊ธธ์ด)
character-worker ์บ๋ฆญํ„ฐ ์†Œ์œ ๊ถŒ ์ €์žฅ (batch) character.reward KEDA (ํ ๊ธธ์ด)
celery-beat DLQ ์žฌ์ฒ˜๋ฆฌ ์Šค์ผ€์ค„๋ง (5๋ถ„ ์ฃผ๊ธฐ) - ๋‹จ์ผ ์ธ์Šคํ„ด์Šค
RabbitMQ AMQP ๋ฉ”์‹œ์ง€ ๋ธŒ๋กœ์ปค vhost: eco2 Quorum Queue

Logging Pipeline (EFK Stack)

flowchart LR
    subgraph Pods["Kubernetes Pods"]
        API["API Pods<br/>(auth, scan, chat...)"]
        Workers["Celery Workers<br/>(scan, character-match, character)"]
        Infra["Infra Pods<br/>(istio, argocd...)"]
    end

    subgraph FluentBit["Fluent Bit (DaemonSet)"]
        Tail["Tail Input<br/>(/var/log/containers/*.log)"]
        Parser["Parser<br/>(JSON, regex)"]
        Filter["Filter<br/>(kubernetes metadata)"]
        Output["Output<br/>(es plugin)"]
    end

    subgraph EFK["EFK Stack"]
        ES[("Elasticsearch<br/>(3 nodes)")]
        Kibana["Kibana<br/>(UI)"]
    end

    API -->|stdout/stderr| Tail
    Workers -->|stdout/stderr| Tail
    Infra -->|stdout/stderr| Tail

    Tail --> Parser
    Parser --> Filter
    Filter --> Output
    Output -->|HTTP/9200| ES

    ES --> Kibana

    classDef pods fill:#326CE5,stroke:#fff,color:white
    classDef fluent fill:#009688,stroke:#fff,color:white
    classDef efk fill:#FF9800,stroke:#fff,color:white

    class API,Workers,Infra pods
    class Tail,Parser,Filter,Output fluent
    class ES,Kibana efk
Loading
์ปดํฌ๋„ŒํŠธ ์—ญํ•  ์„ค์ •
Fluent Bit ๋กœ๊ทธ ์ˆ˜์ง‘ ๋ฐ ํฌ์›Œ๋”ฉ (DaemonSet) /var/log/containers/*.log ์ˆ˜์ง‘, JSON ํŒŒ์‹ฑ
Elasticsearch ๋กœ๊ทธ ์ €์žฅ ๋ฐ ์ธ๋ฑ์‹ฑ 3-node cluster, ์ธ๋ฑ์Šค: logstash-YYYY.MM.DD
Kibana ๋กœ๊ทธ ๊ฒ€์ƒ‰ ๋ฐ ์‹œ๊ฐํ™” Discover, Dashboard, Alerting

๋กœ๊ทธ ํฌ๋งท (JSON ๊ตฌ์กฐํ™”)

{
  "timestamp": "2025-12-22T10:30:00.000Z",
  "level": "INFO",
  "logger": "scan.vision_task",
  "message": "Vision analysis completed",
  "task_id": "550e8400-e29b-41d4-a716-446655440000",
  "user_id": "123e4567-e89b-12d3-a456-426614174000",
  "duration_ms": 2340,
  "kubernetes": {
    "namespace": "scan",
    "pod_name": "scan-worker-5d8f9b7c4-x2k9p",
    "container_name": "scan-worker"
  }
}

Bootstrap Overview

Cluster   : kubeadm Self-Managed (25 Nodes)
GitOps    :
  Layer0 - Terraform (AWS ์ธํ”„๋ผ)
  Layer1 - Ansible (kubeadm, CNI)
  Layer2 - ArgoCD App-of-Apps Sync-wave + Kustomize/Helm
  Layer3 - GitHub Actions + Docker Hub
Architecture :
  Edge Layer        - Route 53, AWS ALB, Istio Ingress Gateway
  Service Layer     - auth, users, scan, character, location, chat, info, images
  Integration Layer :
    - Event Bus   - Redis Streams + Pub/Sub + State KV, Event Router, SSE Gateway
    - Worker (Storage) - auth-worker, auth-Bus, users-worker, character-worker, info-worker, chat-persistence-consumer
    - Worker (AI)   - scan-worker (Visionโ†’Ruleโ†’Answerโ†’Reward), chat-worker (LangGraph Multi-Agent)
    - KEDA (Event-driven Autoscaling)
  Persistence Layer - PostgreSQL, Redis (Blacklist/State/Streams/Pub-Sub/Cache ๋ถ„๋ฆฌ)
  Platform Layer    - ArgoCD, Istiod, KEDA, Observability (Prometheus, Grafana, EFK, Jaeger, LangSmith)
Network   : Calico CNI + Istio Service Mesh (mTLS)
Node Isolation :
  - worker-storage  - Taint: domain=worker-storage:NoSchedule (Persistence ์ ‘๊ทผ Worker ์ „์šฉ)
  - worker-ai       - Taint: domain=worker-ai:NoSchedule (AI/OpenAI/Google API ํ˜ธ์ถœ Worker ์ „์šฉ)
  1. Terraform์œผ๋กœ AWS ์ธํ”„๋ผ๋ฅผ ๊ตฌ์ถ•ํ•ฉ๋‹ˆ๋‹ค.
  2. Ansible๋กœ ๊ตฌ์ถ•๋œ AWS ์ธํ”„๋ผ๋ฅผ ์—ฎ์–ด K8s ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ๊ตฌ์„ฑํ•˜๊ณ , ArgoCD root-app์„ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.
  3. ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ๋Š” ArgoCD root-app๊ณผ sync๋œ ์ƒํƒœ์ด๋ฉฐ, root-app์€ develop ๋ธŒ๋žœ์น˜๋ฅผ ๋ฐ”๋ผ๋ด…๋‹ˆ๋‹ค.
  4. develop ๋ธŒ๋žœ์น˜์— push๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด CI ํŒŒ์ดํ”„๋ผ์ธ์„ ๊ฑฐ์ณ ํ…Œ์ŠคํŠธ, ๋„์ปค ์ด๋ฏธ์ง€ ํŒจํ‚ค์ง•, ํ—ˆ๋ธŒ ์—…๋กœ๋“œ๊นŒ์ง€ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  5. ArgoCD root-app์€ develop ๋ธŒ๋žœ์น˜์˜ ๋ณ€๊ฒฝ์‚ฌํ•ญ์ด ๊ฐ์ง€๋˜๋ฉด ํ•ด๋‹น ํŒŒํŠธ๋ฅผ ์—…๋ฐ์ดํŠธํ•ด ์ฝ”๋“œ ๋ณ€๊ฒฝ์ด ํด๋Ÿฌ์Šคํ„ฐ๋กœ ๋ฐ˜์˜๋ฉ๋‹ˆ๋‹ค.

GitOps Architecture

9093CE45-C239-4549-B1FA-10D2800BAD58_1_105_c

ArgoCD App-of-Apps ํŒจํ„ด ๊ธฐ๋ฐ˜ GitOps. ๋ชจ๋“  ๋ฆฌ์†Œ์Šค๋Š” sync-wave๋กœ ์˜์กด์„ฑ ์ˆœ์„œ ๋ณด์žฅ.

Wave ๋ ˆ์ด์–ด ๋ฆฌ์†Œ์Šค
0-10 ํ”Œ๋žซํผ CRD, Namespace, RBAC, Istio, NetworkPolicy, Secrets
15-32 ์ธํ”„๋ผ ALB, Monitoring, PostgreSQL, Redis, RabbitMQ
35-50 ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ KEDA, APIs, Workers, Event Router, Routing
  • App-of-Apps: ๋ฃจํŠธ ์•ฑ โ†’ ApplicationSet ์ƒ์„ฑ โ†’ sync-wave ๊ฐ’์œผ๋กœ ๋ฐฐํฌ ์ˆœ์„œ ๊ฐ•์ œ
  • Sync Hook: PostSync Job์œผ๋กœ DB ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์ž๋™ ์‹คํ–‰
  • CI/CD: ์ฝ”๋“œ ๋ณ€๊ฒฝ โ†’ GitHub Actions โ†’ Docker Hub โ†’ ArgoCD Auto-Sync

Release Summary (v1.0.8 - v1.1.1)

  • Redis Pub/Sub ์ฑ„๋„ ์ƒค๋”ฉ & ๋ถ€ํ•˜ ํ…Œ์ŠคํŠธ VU 1000 โœ… (New!)

    • job_id ํ•ด์‹œ ๊ธฐ๋ฐ˜ ์ฑ„๋„ ์ƒค๋”ฉ: sse:events:{job_id} โ†’ sse:events:{hash(job_id) % 4} Hot Key ๋ถ„์‚ฐ
    • KEDA ScaledObject ์ตœ์ ํ™”: minReplicas 1โ†’2 (Cold Start ๋ฐฉ์ง€), maxReplicas 3โ†’5
    • VU 500-1000 ๋ถ€ํ•˜ ํ…Œ์ŠคํŠธ ์™„๋ฃŒ: VU 900๊นŒ์ง€ 99.7% ์„ฑ๊ณต๋ฅ , VU 1000์—์„œ 97.8% ๋‹ฌ์„ฑ
    • ๋ณ‘๋ชฉ ๋ถ„์„: Celery Probe I/O-bound(LLM API) ์ทจ์•ฝ์  ์‹๋ณ„, OpenAI Tier 4 TPM 61% ์‚ฌ์šฉ (์—ฌ์œ )
  • OpenAI Agents SDK Migration โœ…

    • Primary + Fallback ๊ตฌ์กฐ: Agents SDK ์‹คํŒจ ์‹œ Responses API๋กœ ์ž๋™ ์ „ํ™˜
    • 6๊ฐœ Function Calling ๋…ธ๋“œ: web_search, bulk_waste, weather, recyclable_price, location, collection_point
    • Streaming Safety: _yielded ํ”Œ๋ž˜๊ทธ๋กœ ๋ถ€๋ถ„ ๋ฐ์ดํ„ฐ ์ „์†ก ์‹œ fallback ๋ฐฉ์ง€
    • google-genai 1.60.0: system_instruction, FunctionCallingConfigMode enum ์ ์šฉ
  • Redis Primary Checkpoint ์•„ํ‚คํ…์ฒ˜ โœ… (New!)

    • Connection Pool ๊ณ ๊ฐˆ ํ•ด๊ฒฐ: Worker โ†’ PG ์ง์ ‘ ์—ฐ๊ฒฐ ์ œ๊ฑฐ, 192 โ†’ 8 conn (96% ๊ฐ์†Œ)
    • Redis Primary: Worker๊ฐ€ Redis์— ์ง์ ‘ ์“ฐ๊ธฐ (~1ms)
    • PG Async Sync: checkpoint_syncer๊ฐ€ 5์ดˆ ๊ฐ„๊ฒฉ ๋ฐฐ์น˜ ๋™๊ธฐํ™”
    • Cold Start Fallback: ReadThroughCheckpointer๋กœ Redis miss ์‹œ PG ์ฝ๊ธฐ + ์Šน๊ฒฉ
  • Event Bus ์•ˆ์ •์„ฑ ๊ฐœ์„  โœ… (New!)

    • ACK Policy ์ˆ˜์ •: ์ฒ˜๋ฆฌ ์‹คํŒจ ์‹œ XACK ์Šคํ‚ต โ†’ Reclaimer ์žฌ์ฒ˜๋ฆฌ
    • ๋ฉ€ํ‹ฐ๋„๋ฉ”์ธ Reclaimer: scan/chat ๋ณ‘๋ ฌ XAUTOCLAIM
    • Redis ์ธ์Šคํ„ด์Šค ๋ผ์šฐํŒ… ์ˆ˜์ •: ProgressNotifier โ†’ get_redis_streams()
  • LangGraph Multi-Agent ์•„ํ‚คํ…์ฒ˜ โœ…

    • 10๊ฐœ Intent ๋ถ„๋ฅ˜: WASTE, CHARACTER, LOCATION, BULK_WASTE, RECYCLABLE_PRICE, COLLECTION_POINT, WEATHER, IMAGE_GENERATION, WEB_SEARCH, GENERAL
    • ์ด๋ฏธ์ง€ ์ƒ์„ฑ: Gemini 3 Pro Image + gRPC CDN Upload, Character Reference ์ง€์›
    • Token Streaming: LangChain LLM ์ง์ ‘ ํ˜ธ์ถœ, Event Router Unicode ์ˆ˜์ •
    • ๋ฉ”์‹œ์ง€ ์˜์†ํ™”: chat-persistence-consumer (Redis Streams โ†’ PostgreSQL)
    • ๋ถ„์‚ฐ ํŠธ๋ ˆ์ด์‹ฑ: LangSmith ์—ฐ๋™, OpenTelemetry E2E ํŠธ๋ ˆ์ด์‹ฑ
  • Info ์„œ๋น„์Šค ํ”„๋กœ๋น„์ €๋‹ โœ… (New!)

    • Info API/Worker: 3-Tier Architecture (FastAPI + Celery Beat + PostgreSQL + Redis)
    • NewsData API ์—ฐ๋™: ํ™˜๊ฒฝ/์—๋„ˆ์ง€/AI ๋‰ด์Šค ์ž๋™ ์ˆ˜์ง‘
    • Claude Code Skills: chat-agent-flow ๋“ฑ ํ”„๋กœ์ ํŠธ ํŠนํ™” ๊ฐ€์ด๋“œ
  • Clean Architecture ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ โœ… (New!)

    • ๋””๋ ‰ํ† ๋ฆฌ ๊ตฌ์กฐ ์ „ํ™˜: domains/ โ†’ apps/ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜
    • RabbitMQ Named Exchange: reward.events Fanout Exchange, Cross-Domain Task Routing
    • CI/CD ํŒŒ์ดํ”„๋ผ์ธ ์ •๋น„: apps/ ๊ฒฝ๋กœ ๊ธฐ๋ฐ˜ ํŠธ๋ฆฌ๊ฑฐ
  • Event Bus Layer + AI ํŒŒ์ดํ”„๋ผ์ธ โœ…

    • Redis Streams(๋‚ด๊ตฌ์„ฑ) + Pub/Sub(์‹ค์‹œ๊ฐ„) + State KV(๋ณต๊ตฌ) 3-tier ์ด๋ฒคํŠธ ์•„ํ‚คํ…์ฒ˜
    • Event Router: Consumer Group(XREADGROUP)์œผ๋กœ Streams ์†Œ๋น„, Pub/Sub Fan-out, ๋ฉฑ๋“ฑ์„ฑ ๋ณด์žฅ
    • SSE Gateway: Pub/Sub ๊ตฌ๋… ๊ธฐ๋ฐ˜ ์‹ค์‹œ๊ฐ„ ์ „๋‹ฌ, State ๋ณต๊ตฌ, Streams Catch-up
    • Celery Chain(Visionโ†’Ruleโ†’Answerโ†’Reward): GPT-5.2 Vision + GPT-5.2-mini ์กฐํ•ฉ
๐Ÿ“Š ๋ถ€ํ•˜ ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ (Scan Pipeline) - OpenAI Tier 4, KEDA min=2/max=5
VU ์š”์ฒญ ์ˆ˜ ์„ฑ๊ณต๋ฅ  Throughput E2E P95 ์‹คํŒจ ์ƒํƒœ
500 1,408 99.7% 351.9 req/m 108.3s 4 โœ… ์•ˆ์ •
600 1,408 99.7% 351.9 req/m 108.3s 4 โœ… ์•ˆ์ •
700 1,496 99.2% 329.1 req/m 122.3s 11 โœ… ์•ˆ์ •
800 1,386 99.7% 367.3 req/m 144.6s 4 โœ… ์•ˆ์ •
900 1,540 99.7% 405.5 req/m 149.6s 4 โญ ๊ถŒ์žฅ ํ•œ๊ณ„
1000 1,518 97.8% 373.4 req/m 173.3s 33 โš ๏ธ Probe Timeout

๊ฐœ์„  ์‚ฌํ•ญ (v1.1.1):

  • Redis Pub/Sub ์ฑ„๋„ ์ƒค๋”ฉ (job_id ํ•ด์‹œ ๊ธฐ๋ฐ˜) โ†’ Hot Key ๋ถ„์‚ฐ
  • KEDA ScaledObject ์กฐ์ •: minReplicas 1โ†’2, maxReplicas 3โ†’5
  • Cold Start ๋ฐฉ์ง€๋กœ ์‹คํŒจ์œจ 37.7% ๊ฐ์†Œ (VU 1000 ๊ธฐ์ค€ 53๊ฑดโ†’33๊ฑด)
  • KEDA ์ด๋ฒคํŠธ ๋“œ๋ฆฌ๋ธ ์˜คํ† ์Šค์ผ€์ผ๋ง โœ…

    • scan-worker: RabbitMQ ํ ๊ธธ์ด ๊ธฐ๋ฐ˜ ์ž๋™ ์Šค์ผ€์ผ๋ง (2-5 replicas, Cold Start ๋ฐฉ์ง€)
    • chat-worker: RabbitMQ chat.process ํ ๊ธฐ๋ฐ˜ ์Šค์ผ€์ผ๋ง
    • event-router: Redis Streams pending ๋ฉ”์‹œ์ง€ ๊ธฐ๋ฐ˜ ์Šค์ผ€์ผ๋ง
    • Prometheus Adapter ์—ฐ๋™์œผ๋กœ ์ปค์Šคํ…€ ๋ฉ”ํŠธ๋ฆญ ๊ธฐ๋ฐ˜ HPA ๊ตฌํ˜„
  • 24-node ํด๋Ÿฌ์Šคํ„ฐ ํ™•์žฅ โœ…

    • ์‹ ๊ทœ ๋…ธ๋“œ: chat-worker, info, info-worker, chat-persistence-consumer ์ „์šฉ ๋…ธ๋“œ ์ถ”๊ฐ€
    • Redis ์ธ์Šคํ„ด์Šค ๋ถ„๋ฆฌ: Streams(๋‚ด๊ตฌ์„ฑ) / Pub/Sub(์‹ค์‹œ๊ฐ„) / Cache(LRU)
    • Grafana ๋Œ€์‹œ๋ณด๋“œ: 24-node ์ „์ฒด ๋ชจ๋‹ˆํ„ฐ๋ง ๋Œ€์‹œ๋ณด๋“œ

Article

๐Ÿ“ ์ด์ฝ”์—์ฝ”(Ecoยฒ) ๋ฐฑ์—”๋“œ/์ธํ”„๋ผ ๊ฐœ๋ฐœ ๋ธ”๋กœ๊ทธ

์ฃผ์š” ๊ธฐ์ˆ  ๋ฌธ์„œ:


Status

v1.1.1 - Redis Pub/Sub Sharding & VU 1000 Load Test โญ Latest

  • โœ… Redis Pub/Sub ์ฑ„๋„ ์ƒค๋”ฉ: job_id ํ•ด์‹œ ๊ธฐ๋ฐ˜ Hot Key ๋ถ„์‚ฐ (4 shards)
  • โœ… KEDA ScaledObject ์ตœ์ ํ™”: minReplicas 2, maxReplicas 5 (Cold Start ๋ฐฉ์ง€)
  • โœ… VU 500-1000 ๋ถ€ํ•˜ ํ…Œ์ŠคํŠธ ์™„๋ฃŒ: VU 900๊นŒ์ง€ 99.7% ์„ฑ๊ณต๋ฅ 
  • โœ… ๋ณ‘๋ชฉ ๋ถ„์„ ์™„๋ฃŒ: Celery Probe I/O-bound ์ทจ์•ฝ์  ์‹๋ณ„
  • โœ… OpenAI Tier 4 ๊ฒ€์ฆ: TPM 61% ์‚ฌ์šฉ, Rate Limit 0๊ฑด

v1.1.0 - Chat Agent & Agents SDK

  • โœ… LangGraph Multi-Agent ์•„ํ‚คํ…์ฒ˜ ์™„๋ฃŒ (10๊ฐœ Intent ๋ถ„๋ฅ˜)
  • โœ… OpenAI Agents SDK Migration: Primary + Responses API Fallback ์ด์ค‘ ๊ตฌ์กฐ
  • โœ… 6๊ฐœ Function Calling ๋…ธ๋“œ: web_search, bulk_waste, weather, recyclable_price, location, collection_point
  • โœ… Redis Primary Checkpoint: Worker PG ์—ฐ๊ฒฐ 96% ๊ฐ์†Œ (192 โ†’ 8)
  • โœ… Gemini ์ด๋ฏธ์ง€ ์ƒ์„ฑ ํŒŒ์ดํ”„๋ผ์ธ + gRPC CDN Upload
  • โœ… Event Bus ์•ˆ์ •์„ฑ: ACK Policy ์ˆ˜์ •, ๋ฉ€ํ‹ฐ๋„๋ฉ”์ธ Reclaimer
  • โœ… 24-node ํด๋Ÿฌ์Šคํ„ฐ ํ™•์žฅ: Grafana ๋Œ€์‹œ๋ณด๋“œ ์ถ”๊ฐ€
  • โœ… ๋ถ„์‚ฐ ํŠธ๋ ˆ์ด์‹ฑ: LangSmith + OpenTelemetry E2E

v1.0.9 - Info ์„œ๋น„์Šค & Context ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜

  • โœ… Info API/Worker 3-Tier Architecture ์™„๋ฃŒ
  • โœ… NewsData API ์—ฐ๋™ ํ™˜๊ฒฝ ๋‰ด์Šค ์ˆ˜์ง‘
  • โœ… Claude Code Skills ๋„์ž… (chat-agent-flow ๋“ฑ)
  • โœ… Celery Beat ์•ˆ์ •ํ™” (standalone sidecar)

v1.0.8 - Clean Architecture ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜

  • โœ… domains/ โ†’ apps/ ๊ตฌ์กฐ ์ „ํ™˜ ์™„๋ฃŒ
  • โœ… RabbitMQ Named Exchange ์ด๋ฒคํŠธ ๋ผ์šฐํŒ… (reward.events Fanout)
  • โœ… CI/CD ํŒŒ์ดํ”„๋ผ์ธ ์ •๋น„ (apps/ ๊ฒฝ๋กœ ๊ธฐ๋ฐ˜)
  • โœ… DB/Redis ์—ฐ๊ฒฐ ์ •๊ทœํ™”

v1.0.7 - Event Bus & KEDA

  • โœ… Redis Streams + Pub/Sub + State KV ๊ธฐ๋ฐ˜ Event Bus Layer ์™„๋ฃŒ
  • โœ… Event Router, SSE Gateway ์ปดํฌ๋„ŒํŠธ ๊ฐœ๋ฐœ ์™„๋ฃŒ
  • โœ… KEDA ์ด๋ฒคํŠธ ๋“œ๋ฆฌ๋ธ ์˜คํ† ์Šค์ผ€์ผ๋ง ์ ์šฉ (scan-worker, event-router, character-match-worker)
  • โœ… Celery ๋น„๋™๊ธฐ AI ํŒŒ์ดํ”„๋ผ์ธ ์™„๋ฃŒ (Visionโ†’Ruleโ†’Answerโ†’Reward)

v1.0.6 - Observability

  • โœ… EFK ๋กœ๊น… ํŒŒ์ดํ”„๋ผ์ธ (Fluent Bit โ†’ Elasticsearch โ†’ Kibana)
  • โœ… ๋ถ„์‚ฐ ํŠธ๋ ˆ์ด์‹ฑ (Jaeger + OpenTelemetry + Kiali)
  • โœ… Alertmanager ์•Œ๋ฆผ ์‹œ์Šคํ…œ (Slack)

v1.0.5 - Service Mesh & Auth Offloading

  • โœ… Istio Service Mesh Migration ์™„๋ฃŒ
  • โœ… gRPC ๋‚ด๋ถ€ ํ†ต์‹  Migration ์™„๋ฃŒ
  • โœ… Auth-Offloading ์™„๋ฃŒ, ๋„๋ฉ”์ธ๋ณ„ ๋…๋ฆฝ์„ฑ ํ™•๋ณด
  • โœ… ext-authz ์„ฑ๋Šฅ ํŠœ๋‹ (Grafana: VU 2500, RPS 1200, p99 200-300ms)

v1.0.0 - Initial Release

  • โœ… Terraform ยท Ansible bootstrap ยท ArgoCD Sync-wave
  • โœ… GitOps Sync-Wave ์žฌ์ •๋ ฌ (00~70) + upstream Helm/CRD ๋ถ„๋ฆฌ
  • โœ… Docker Hub ์ด๋ฏธ์ง€ ํŒŒ์ดํ”„๋ผ์ธ + External Secrets ์šด์˜
  • โœ… API ๊ฐœ๋ฐœ ์™„๋ฃŒ, ํ”„๋ก ํŠธ-๋ฐฑ-AI ์—ฐ๋™ ์™„๋ฃŒ

About

๐ŸŒฑ ์ด์ฝ”์—์ฝ”(Ecoยฒ) BE

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors