아키텍처¶
SeMu-GPT 2026은 세무 법령·예규·판례·상담사례 코퍼스를 Elasticsearch에 색인하고, OpenAI 기반 RAG(Retrieval-Augmented Generation) 파이프라인으로 사용자 질의에 답변하는 모노레포 시스템이다. 프론트엔드(Next.js), 백엔드(Kotlin/Spring Boot), 데이터 파이프라인(Python CLI)의 3개 deployable과 MySQL/Elasticsearch/Redis 인프라로 구성된다.
시스템 구성¶
graph TD
subgraph Client["클라이언트"]
BROWSER[웹 브라우저]
end
subgraph Edge["엣지 / CDN"]
CF[Cloudflare
Workers + Tunnel]
ALB[AWS ALB
prod 전용]
end
subgraph App["애플리케이션 계층"]
FE[Frontend
Next.js 16 / React 19]
BE[Backend
Kotlin / Spring Boot 3.1]
end
subgraph Data["데이터 계층"]
MYSQL[(MySQL 8.0
거래/사용자 데이터)]
ES[(Elasticsearch 8.17
법령 코퍼스 + 임베딩)]
REDIS[(Redis 7
캐시)]
end
subgraph Pipeline["데이터 파이프라인 (오프라인)"]
COL[Collector
Python CLI]
IDX[Indexer
Python CLI]
end
subgraph External["외부 서비스"]
OPENAI[OpenAI
GPT-5 + Embeddings]
LF[Langfuse
프롬프트 관리]
TOSS[Toss Payments]
SENS[Naver Cloud SENS
SMS]
SENTRY[Sentry]
end
BROWSER --> CF
BROWSER --> ALB
CF --> FE
ALB --> FE
ALB --> BE
FE -- HTTP/SSE --> BE
BE --> MYSQL
BE --> ES
BE --> REDIS
BE -- 프롬프트 fetch --> LF
BE -- 채팅/임베딩 --> OPENAI
BE -- 결제 confirm/webhook --> TOSS
BE -- SMS 발송 --> SENS
FE -- 에러 리포팅 --> SENTRY
COL -- JSONL --> IDX
IDX -- bulk index --> ES
IDX -- 임베딩 생성 --> OPENAI
컴포넌트 책임¶
| 컴포넌트 | 기술 스택 | 책임 | 위치 |
|---|---|---|---|
| Frontend | Next.js 16.1 (App Router), React 19.2, Tailwind 3.4, Zustand 5 | 채팅 UI, 멤버십·결제·관리자 화면, SSE 스트림 렌더링 | apps/frontend/ |
| Backend | Kotlin 1.8, Spring Boot 3.1, Spring Security, JPA + QueryDSL, ES Java Client 8.6 | 인증/계정/멤버십/결제 API, RAG 오케스트레이션, ES 검색, SSE 스트리밍 | apps/backend/ |
| Data Pipeline | Python 3.11+, Typer, BeautifulSoup, Selenium, openai SDK | 외부 사이트 크롤링 → JSONL → ES 색인 + 임베딩 생성 | packages/data-pipeline/ |
| MySQL | MySQL 8.0 (RDS prod / Docker dev) | 사용자, 결제, 멤버십, 대화 세션, 쿠폰 등 OLTP | RDS tax-gpt (prod), docker-compose.dev.yml |
| Elasticsearch | ES 8.17 + analysis-nori (한국어), dense_vector 3072차원 | 법령/시행령/판례/예규/상담 코퍼스 검색 (BM25 + kNN) | Docker (dev/prod 모두 컨테이너) |
| Redis | Redis 7 | Spring 캐시, 세션 보조 | Docker (dev/prod 모두 컨테이너) |
| Langfuse (외부) | SaaS | 프롬프트 버전 관리, LLM 모델/temperature config 외부화 | LangfusePromptService |
| OpenAI (외부) | GPT-5 계열, text-embedding-3-large | 답변 생성, HyDE, intent routing, 임베딩 | OpenAI Kotlin client + Python SDK |
| Toss Payments (외부) | Toss V2 API | 결제 confirm + webhook | TossWebhookController, 결제 페이지 |
| Naver Cloud SENS (외부) | SENS SMS REST API | 휴대폰 인증 코드 발송 | SensMessageSender (MessageSender 구현체) |
| Sentry (외부) | @sentry/nextjs v10 |
프론트엔드 에러 모니터링 | apps/frontend/sentry.*.config.ts |
통신 패턴¶
| 패턴 | 사용처 | 비고 |
|---|---|---|
| HTTP REST (JSON) | Frontend ↔ Backend (/auth, /accounts, /conversations, /payments 등) |
JWT Bearer 토큰 인증 |
| SSE 스트리밍 | POST /conversations/stream, POST /conversations/{id}/turns/stream |
RAG 응답 점진 스트리밍 + citation_update 이벤트 |
| Webhook | Toss → POST /webhooks/tosspayments |
결제 상태 변경 비동기 통보 |
| Elasticsearch REST | Backend ↔ ES (8.6 Java client) + 일부 low-level RestClient (RRF) | BM25 + kNN 하이브리드 검색 |
| JPA / JDBC | Backend ↔ MySQL | QueryDSL로 동적 쿼리 |
| Spring Cache (Redis) | Backend 내부 캐시 | TTL 단위 설정, Langfuse 프롬프트 캐시는 in-memory 5분 TTL |
| OpenAI HTTP API | Backend OpenAI client + Pipeline openai SDK |
Chat Completions, Embeddings |
외부 의존성¶
| 서비스 | 용도 | 인증 / 시크릿 위치 |
|---|---|---|
| OpenAI | LLM 답변 생성 + 임베딩 | yaml openai.token (env override: OPENAI_TOKEN) |
| Langfuse | 프롬프트 버저닝 + 모델 config (rag-final-answer, hyde-generator 등 8개) |
LANGFUSE_PUBLIC_KEY / LANGFUSE_SECRET_KEY |
| Toss Payments V2 | 결제 위젯 + confirm/webhook | TOSS_SECRET_KEY (백엔드), NEXT_PUBLIC_TOSS_* (프론트) |
| Naver Cloud SENS | 휴대폰 인증 SMS 발송 | ncp.access-key, ncp.secret-key, ncp.sens.sms.service-id, ncp.sens.sms.calling-number (application-prod.yml) |
| Cloudflare Tunnel | dev 백엔드를 공인 도메인에 노출 (Lightsail box → semu-gpt-dev.bootalk.co.kr) |
systemd cloudflared, tunnel ID 078d8083-... |
| Cloudflare Workers | dev 프론트엔드 호스팅 (semu-chat-dev.bootalk.co.kr) |
CLOUDFLARE_API_TOKEN (GH Secrets) |
| Sentry | 프론트엔드 런타임 에러 (org bootalk, project semugpt) |
NEXT_PUBLIC_SENTRY_DSN |
백엔드 Sentry는 미설치 상태(
CLAUDE.md"Pre-cutover 코드 수정" 참조).
인프라¶
개발 환경 (dev)¶
- Backend: AWS Lightsail (
semugpt-backend, ap-northeast-2, $24/mo, Static IP3.39.17.132) - systemd
semugpt-backend(Spring Boot fat jar, port 8080) - Docker Compose:
mysql+elasticsearch+redis - Cloudflare Tunnel
semugpt-backend→semu-gpt-dev.bootalk.co.kr - Frontend: Cloudflare Workers (
semugpt-frontend-dev) @opennextjs/cloudflare빌드 → KV 자산 + Worker- GitHub Actions
deploy-frontend-dev.yml(push todevelop, pathsapps/frontend/**) - URL:
semu-chat-dev.bootalk.co.kr
운영 환경 (prod, soft launch)¶
semugpt.co.kr apex/www/api/pro는 레거시 tax-gpt (EC2 + ALB + RDS) 가 그대로 운영 중.
새 버전은 new.semugpt.co.kr (frontend) 와 api-new.semugpt.co.kr (backend) 로 병행 운영 (Issue #151).
- Backend (계획): AWS Lightsail
semugpt-prod(large_3_0, 8GB, $44/mo) - systemd
semugpt-backend(port 8080) + systemdsemugpt-frontend(port 3000) - Docker: ES + Redis (MySQL은 RDS 재사용)
- VPC peering: Lightsail VPC ↔ default VPC (ALB 도달용, 활성 ✅)
- ALB (재사용):
semu-gpt-alb(HTTPS:443, ACM*.semugpt.co.kr) - host=
api-new→ TG-backend-2026 (priority 100) - host=
new→ TG-frontend-2026 (priority 110) - RDS:
tax-gpt(MySQL 8.0.44, db.t3.micro, 20GB) - 신규 database
semugpt_2026(account/phone_auth/membership 부분 마이그레이션 완료 — 2026-05-11) - DNS: Route 53
semugpt.co.kr.(zoneZ0917222THSORQW5ECCW)
상세는 운영 런북 운영 배포 및 프로젝트 루트 CLAUDE.md의 "Production Infrastructure" 섹션 참조.
빌드/배포 흐름¶
| 컴포넌트 | 트리거 | 빌드 | 배포 |
|---|---|---|---|
| Frontend (dev) | develop push (apps/frontend/**) |
GitHub Actions: pnpm build:cf (@opennextjs/cloudflare) |
pnpm deploy:cf → Cloudflare Workers |
| Backend (dev) | 수동 (ssh semugpt-aws) |
git pull + Gradle bootJar |
sudo systemctl restart semugpt-backend |
| Frontend (prod) | 미정 (수동) | 동일 | new.semugpt.co.kr Worker 또는 Lightsail systemd |
| Backend (prod) | 수동 | 동일 | Lightsail systemd |
| Data Pipeline | 로컬 CLI (uv run semugpt-collect, uv run semugpt-index) |
— | ES bulk API 직접 호출 |