๋ถ์ฐ ์์คํ ์ ๋ก๊ทธ๋ฅผ ์ค์๊ฐ์ผ๋ก ์์งํ๊ณ , AI(LLM)๋ฅผ ํ์ฉํ ์๋ ๋ถ์ ๋ฐ RAG ๊ธฐ๋ฐ ์ฑ๋ด QA ์์คํ ์ ์ ๊ณตํ๋ ์ํฐํ๋ผ์ด์ฆ๊ธ ๋ก๊ทธ ๊ด๋ฆฌ ํ๋ซํผ์ ๋๋ค.
- AI ๊ธฐ๋ฐ ๋ก๊ทธ ๋ถ์ ํ๋ซํผ, LogLens
- ๋ฐํ ์๋ฃ
- ์์ ํฌํธํด๋ฆฌ์ค
- ํ์ ๊น๊ฑดํ : BE ๋ฆฌ๋ + INFRA ์ด์๊ท : BE + AI ํ์ข ์ฑ : BE + BE_Lib ํํ๋ฆฐ : FE ๋ฆฌ๋ ๊น๋ฏผ์ง : FE_Lib + BE ์ด์ข ํ : FE
๋ฐ์ดํฐ ํ๋ก์ฐ (ํ ์คํธ ๋ค์ด์ด๊ทธ๋จ):
Spring Boot ์ฑ (LogLens Starter)
โ
Kafka (๋ฉ์์ง ํ)
โ
Logstash (ETL)
โ
OpenSearch (๋ก๊ทธ ์ ์ฅ + ๋ฒกํฐ DB)
โ
์ฌ์ฉ์(FE) โโ BE(Spring Boot) โโ AI(FastAPI) โโ OpenSearch
โ
Redis (์บ์), MySQL (๋ฉํ๋ฐ์ดํฐ)
- ์ธํ๋ผ (Docker)
cd BE/BE/infra
docker-compose -f docker-compose-data.yml up -dMySQL: 3306, Redis: 6379
- FE
cd FE/S13P31A306
npm install
npm run dev๊ธฐ๋ณธ ๊ฐ๋ฐ ์๋ฒ: http://localhost:5173
- BE
cd BE/BE
./gradlew bootRun๊ธฐ๋ณธ ํฌํธ: 8080, ํฌ์ค์ฒดํฌ: GET /health-check
- AI
cd AI/AI
pip install -r requirements.txt
uvicorn app.main:app --reload --port 8000ํฌ์ค์ฒดํฌ: GET /api/v1/health
๊ธฐ์ ์คํ
- React 19, TypeScript 5.9, Vite 7
- ์ํ: Zustand, TanStack React Query
- ๋ผ์ฐํ : React Router 7
- UI: Radix UI, Tailwind CSS, Lucide React
- ์๊ฐํ: Nivo, Recharts, D3, ReactFlow
- ํต์ : Axios
- ๋ฌธ์: html2canvas + jsPDF, React Markdown
์ฃผ์ ์คํฌ๋ฆฝํธ
npm run dev # ๊ฐ๋ฐ ์๋ฒ ์คํ
npm run build # ํ๋ก๋์
๋น๋
npm run preview # ๋น๋ ํ๋ฆฌ๋ทฐํด๋ ๊ตฌ์กฐ ์์ฝ
FE/S13P31A306/src/
โโ pages/ # ๋ผ์ฐํ
ํ์ด์ง (13๊ฐ)
โโ components/ # ์ฌ์ฌ์ฉ ์ปดํฌ๋ํธ (30+๊ฐ)
โโ services/ # API ํด๋ผ์ด์ธํธ ์๋น์ค
โโ stores/ # Zustand ์ํ ๊ด๋ฆฌ
โโ hooks/ # ์ปค์คํ
React ํ
โโ types/ # TypeScript ํ์
์ ์
โโ router/ # ๋ผ์ฐํ
์ค์
โโ utils/ # ์ ํธ๋ฆฌํฐ ํจ์
๋ฐํ์ ๊ตฌ์ฑ
- API ๊ธฐ๋ณธ URL: ํ๊ฒฝ ๋ณ์๋ก ์ค์
- ์ธ์ฆ: Access Token + Refresh Token (JWT)
- ์ค์๊ฐ: SSE ๊ธฐ๋ฐ ์๋ฆผ ๊ตฌ๋
๊ธฐ์ ์คํ
- Spring Boot 3.5.6, Java 21, Gradle
- Web/WebFlux, Security, JPA, Redis, Actuator
- springdoc-openapi (Swagger)
๋ฐํ์
- ํ๋กํ:
dev(H2 ์ธ๋ฉ๋ชจ๋ฆฌ) /prod(MySQL) - ํฌ์ค์ฒดํฌ:
GET /health-check - Swagger UI:
/swagger-ui/index.html
AI ์ฐ๋
- WebClient๋ฅผ ํตํด AI FastAPI ํธ์ถ
- ๋ก๊ทธ ๋ถ์ ์์ฒญ โ AI ์๋น์ค โ ๊ฒฐ๊ณผ ์บ์ฑ
๋ฐ์ดํฐ๋ฒ ์ด์ค
- dev: H2 ๋ฉ๋ชจ๋ฆฌ,
ddl-auto: create - prod: MySQL 8.0, Redis 7, OpenSearch 2.17
์ฃผ์ ๋๋ฉ์ธ (13๊ฐ)
auth # ์ธ์ฆ/์ธ๊ฐ (JWT)
project # ํ๋ก์ ํธ ๊ด๋ฆฌ (Multi-Tenancy)
log # ๋ก๊ทธ ์กฐํ/ํํฐ๋ง
analysis # AI ๊ธฐ๋ฐ ๋ก๊ทธ ๋ถ์
alert # ์๋ฆผ ๊ท์น ๋ฐ ์ด๋ ฅ
notification # SSE ์ค์๊ฐ ์๋ฆผ
dashboard # ๋์๋ณด๋ ํต๊ณ
statistics # ๋ก๊ทธ ํต๊ณ ๋ถ์
component # ๋ง์ดํฌ๋ก์๋น์ค ์ปดํฌ๋ํธ
dependency # ์๋น์ค ๊ฐ ์์กด์ฑ ๊ทธ๋ํ
flow # ์์ฒญ ํ๋ฆ ์ถ์
jira # Jira ์ฐ๋
๋น๋/์คํ
./gradlew bootRun # ๊ฐ๋ฐ ์คํ
./gradlew build # ๋น๋
java -jar build/libs/*.jar๊ธฐ์ ์คํ
- FastAPI 0.109, Python 3.11, Uvicorn
- LangChain 0.2.16, LangGraph 0.2.28
- OpenAI GPT-4o mini, text-embedding-3-large
- OpenSearch 2.4 (๋ฒกํฐ ๊ฒ์)
๊ธฐ๋ฅ ๋ชจ๋
- ๋ก๊ทธ ๋ถ์: ์์ฝ, ์์ธ ๋ถ์, ํด๊ฒฐ๋ฐฉ๋ฒ ์์ฑ
- ์ฑ๋ด QA: RAG ๊ธฐ๋ฐ ์์ฐ์ด ์ง์์๋ต
- ์๋ฒ ๋ฉ: ๋ก๊ทธ ํ ์คํธ ๋ฒกํฐํ
- 2๋จ๊ณ ์บ์ฑ: Trace ๊ธฐ๋ฐ + ์ ์ฌ๋ ๊ธฐ๋ฐ (97-99% AI ๋น์ฉ ์ ๊ฐ)
์ฃผ์ ์๋ํฌ์ธํธ
- ํฌ์ค์ฒดํฌ:
GET /api/v1/health - ๋ก๊ทธ ๋ถ์:
GET /api/v1/logs/{log_id}/analysis - ์ฑ๋ด:
POST /api/v1/chatbot/ask - ์๋ฒ ๋ฉ:
POST /api/v1/embeddings - LangGraph API:
/api/v2_langgraph/*
API ๋ฒ์
- v1: ๊ธฐ๋ณธ API (LangChain ์ฒด์ธ)
- v2: ๊ฐ์ ๋ API
- v2_langgraph: LangGraph ์ํฌํ๋ก์ฐ ๊ธฐ๋ฐ
์คํ
pip install -r requirements.txt
uvicorn app.main:app --reload --port 8000ํ ์คํธ
python -m pytest tests -v- ๊ฐ ๋ชจ๋๋ณ
Dockerfile์กด์ฌ - Docker Compose: MySQL, Redis, OpenSearch, BE, AI
- Blue/Green ๋ฐฐํฌ:
infra/dev/docker/docker-compose-blue.yaml,docker-compose-green.yaml - Jenkins: CI/CD ํ์ดํ๋ผ์ธ (
docker-compose-jenkins.yml) - ๋ก๊ทธ ํ์ดํ๋ผ์ธ: Kafka โ Logstash โ OpenSearch
์ฃผ์ ํฌํธ
3306 - MySQL
6379 - Redis
8080 - BE (Spring Boot)
8000 - AI (FastAPI)
9200 - OpenSearch
5601 - OpenSearch Dashboards
- ๋ก๊ทธ ํธ๋ ๋ ๊ทธ๋ํ, ์๊ฐ๋๋ณ ํํธ๋งต
- ์๋ฌ ํต๊ณ, ์์คํ ์ํ ๋ชจ๋ํฐ๋ง
- ์ค์๊ฐ SSE ๊ธฐ๋ฐ ๋ฐ์ดํฐ ์ ๋ฐ์ดํธ
- GPT-4o mini ๊ธฐ๋ฐ ์๋ ๋ก๊ทธ ๋ถ์
- ์์ฝ, ์์ธ ๋ถ์, ํด๊ฒฐ๋ฐฉ๋ฒ ์ ์
- 2๋จ๊ณ ์บ์ฑ์ผ๋ก 97-99% ๋น์ฉ ์ ๊ฐ
- RAG, LangGraph ๊ธฐ๋ฐ ์์ฐ์ด ์ง์์๋ต
- ๋ก๊ทธ ๋ฐ์ดํฐ๋ฅผ ์์ฐ์ด๋ก ๊ฒ์ ๋๋ ์ง์ ์ ํ ํ๋ณ ํ AI Agent(ReAct Agent)๊ฐ tool์ ํ์ฉํด ์ง์ ์ฒ๋ฆฌ
- ๊ด๋ จ ๋ก๊ทธ์ ํจ๊ป ๋ต๋ณ ์ ๊ณต
- ๋ง์ดํฌ๋ก์๋น์ค ๊ฐ ํธ์ถ ๊ด๊ณ ์๊ฐํ
- ReactFlow ๊ธฐ๋ฐ ์ธํฐ๋ํฐ๋ธ ๊ทธ๋ํ
- ์๋น์ค ์ํ ๋ฐ ์ฐ๊ฒฐ ํ์ธ
- trace_id ๊ธฐ๋ฐ ๋ถ์ฐ ํธ๋ ์ด์ฑ
- ์์ฒญ ๊ฒฝ๋ก ์๊ฐํ
- ๋ณ๋ชฉ ์ง์ ํ์
- ์์ธ ํํฐ๋ง (๋ ๋ฒจ, ์๋น์ค, ์๊ฐ ๋ฑ)
- OpenSearch ๊ธฐ๋ฐ ๊ณ ์ ๊ฒ์
- ๋ก๊ทธ ๋ด๋ณด๋ด๊ธฐ ๊ธฐ๋ฅ
- ์ด๊ธฐ ์ค์ ๊ฐ์ด๋
- AI ๋ถ์ ๊ฒฐ๊ณผ ๋ฌธ์ํ
- PDF/Markdown ๋ด๋ณด๋ด๊ธฐ
- Jira ์ด์ ์ฐ๋
- React 19 + TypeScript + Vite: ์ต์ ํ๋ก ํธ์๋ ์คํ์ผ๋ก ๋น ๋ฅธ ๊ฐ๋ฐ๊ณผ ์ต์ ํ๋ ๋ฒ๋ค๋ง
- ์ํ ๊ด๋ฆฌ: Zustand + TanStack Query๋ก ํจ์จ์ ์ธ ์ํ ๊ด๋ฆฌ ๋ฐ ์๋ฒ ๋ฐ์ดํฐ ์บ์ฑ
- ์ค์๊ฐ ์๋ฆผ: SSE(Server-Sent Events)๋ก ์๋ฒ ํธ์ ์๋ฆผ, ์๋ ์ฌ์ฐ๊ฒฐ ์ง์
- UI/UX: Radix UI + Tailwind CSS๋ก ์ ๊ทผ์ฑ ์ค์, Framer Motion์ผ๋ก ๋ถ๋๋ฌ์ด ์ ๋๋ฉ์ด์
- ๋ฐ์ดํฐ ์๊ฐํ: ReactFlow(์์กด์ฑ ๊ทธ๋ํ), Recharts/D3(์ฐจํธ), html2canvas+jsPDF(๋ฌธ์ ์์ฑ)
- Spring Boot 3.5.6 + Java 21: Virtual Threads๋ก ๋์ ๋์์ฑ ์ฒ๋ฆฌ
- ์ธ์ฆ: JWT ๊ธฐ๋ฐ (Access 24h + Refresh 7d), Refresh Token Rotation์ผ๋ก ๋ณด์ ๊ฐํ
- ์ค์๊ฐ ํต์ : SSE๋ก 50๊ฐ ๋์ ์ฐ๊ฒฐ ์ง์, heartbeat๋ก ์ฐ๊ฒฐ ์ ์ง
- ๋ฐ์ดํฐ๋ฒ ์ด์ค: HikariCP ์ปค๋ฅ์ ํ ์ต์ ํ, JPA ๋ฐฐ์น ์ฒ๋ฆฌ๋ก DB ๋ถํ ์ต์ํ
- Multi-Tenancy: project_uuid ๊ธฐ๋ฐ ์๋ ํํฐ๋ง, OpenSearch ์ธ๋ฑ์ค ๋ถ๋ฆฌ
- ๋ชจ๋ํฐ๋ง: Prometheus + Actuator๋ก JVM/HTTP/DB ๋ฉํธ๋ฆญ ์์ง
- FastAPI + LangChain + LangGraph: GPT-4o mini ๊ธฐ๋ฐ ๋ก๊ทธ ๋ถ์ ์์คํ
- 2๋จ๊ณ ์บ์ฑ ์ ๋ต์ผ๋ก AI ๋น์ฉ ์ต์ ํ
- 1๋จ๊ณ (Trace ๊ธฐ๋ฐ): ๊ฐ์ ์์ฒญ ํ๋ฆ ๋ก๊ทธ ์ฌ์ฌ์ฉ โ ๋น์ฉ 97-99% ์ ๊ฐ
- 2๋จ๊ณ (์ ์ฌ๋ ๊ธฐ๋ฐ): ๋ฒกํฐ ๊ฒ์์ผ๋ก ์ ์ฌ ์๋ฌ ํจํด ๊ฐ์ง โ ๋น์ฉ 80% ์ ๊ฐ
- RAG ์ฑ๋ด: ๋ฒกํฐ ๊ฒ์ ๊ธฐ๋ฐ ๊ทผ๊ฑฐ ์๋ ๋ต๋ณ ์์ฑ
- ReAct Agent: LangGraph Tool๋ก ์ง์ ๋ถ์ โ ๋๊ตฌ ์ ํ โ ๊ฒฐ๊ณผ ์ข ํฉ
- ์ปจํ ์ด๋ํ: Docker + Docker Compose, ๋ฉํฐ ์คํ ์ด์ง ๋น๋๋ก ์ด๋ฏธ์ง ์ต์ ํ
- CI/CD: Jenkins ํ์ดํ๋ผ์ธ, Blue/Green ๋ฌด์ค๋จ ๋ฐฐํฌ
- ๋ก๊ทธ ํ์ดํ๋ผ์ธ: Fluent Bit โ Kafka โ Logstash โ OpenSearch (Logstash ๋๋น ๋ฆฌ์์ค 90% ์ ๊ฐ)
- ๋ฐ์ดํฐ ์ ์ฅ: MySQL(๋ฉํ๋ฐ์ดํฐ), Redis(์บ์/์ธ์ ), OpenSearch(๋ก๊ทธ ๊ฒ์, 30์ผ ์๋ ์ญ์ )
- ํฌ์ค์ฒดํฌ: 30์ด ๊ฐ๊ฒฉ ์ํ ํ์ธ, ์๋ ์ฌ์์
Frontend Lib (NPM Package)
์ฃผ์ ๊ธฐ๋ฅ
- ์๋ TraceID ์ ํ: ์ต์์ ํจ์๋ง ๋ํํ๋ฉด ๋ด๋ถ ํธ์ถ ์ฒด์ธ์ ์๋์ผ๋ก traceId ์ ํ
- React Hook ์ง์:
useLogLensHook์ผ๋ก React ์ปดํฌ๋ํธ์์ ๊ฐํธํ๊ฒ ์ฌ์ฉ - ๋น๋๊ธฐ ์ฒ๋ฆฌ ์๋ ์ง์: Promise, async/await ํจ์ ์๋ ์ถ์
- ์ฑ๋ฅ ์ธก์ : ํจ์ ์คํ ์๊ฐ ์๋ ์ธก์ ๋ฐ ์ฝ์ ํ์
- ๋ฏผ๊ฐ ๋ฐ์ดํฐ ๋ง์คํน: ํ๊ฒฝ๋ณ์๋ก ๋ง์คํน ํ๋ ์ค์ (password, token ๋ฑ)
- ์ง์ ๋ก๊น
:
loglens.info(),loglens.warn(),loglens.error()๋ฉ์๋ ์ ๊ณต - ์๋ ๋ก๊ทธ ์ ์ก: ์ค์ ๋ ์ฃผ๊ธฐ(๊ธฐ๋ณธ 30์ด)๋ง๋ค ๋ฐฑ์๋๋ก HTTP ์ ์ก
- ์๋ฌ ์๋ ์์ง:
captureErrors: true์ต์ ์ผ๋ก ์๋ฌ ์๋ ์์ง
Backend Lib (LogLens Spring Boot Starter)
์ฃผ์ ๊ธฐ๋ฅ
- ์๋ ๋ก๊ทธ ์์ง: @RestController, @Service, @Repository, @Component ํด๋์ค์ public ๋ฉ์๋ ์๋ ์ถ์
- ์ ํ์ ๋ก๊น : @LogMethodExecution ์ด๋ ธํ ์ด์ ์ผ๋ก ํน์ ๋ฉ์๋๋ง ๋ก๊น ๊ฐ๋ฅ
- ๋ก๊น ์ ์ธ: @NoLogging ์ด๋ ธํ ์ด์ ์ผ๋ก ํน์ ๋ฉ์๋/ํด๋์ค ์ ์ธ
- ๋ณด์:
- @Sensitive ์ด๋ ธํ ์ด์ : ํ๋ผ๋ฏธํฐ/ํ๋๋ฅผ ****๋ก ๋ง์คํน
- @ExcludeValue ์ด๋ ธํ ์ด์ : ํ๋ผ๋ฏธํฐ๋ฅผ ๋ก ์ฒ๋ฆฌ
- MDC ํตํฉ: TraceID ๊ธฐ๋ฐ ๋ถ์ฐ ์ถ์ ์ง์
- ๋น๋๊ธฐ ์ฒ๋ฆฌ: ๋ก๊ทธ ์ ์ก์ด ๋น์ฆ๋์ค ๋ก์ง์ ์ฐจ๋จํ์ง ์์
VPC (10.0.0.0/16)
โโโ Public Subnet (10.0.0.0/20, 10.0.16.0/20)
โ โโโ Internet Gateway โ ์ธ๋ถ ํธ๋ํฝ ์์
โ โโโ ALB โ HTTPS ํธ๋ํฝ ๋ถ์ฐ
โ โโโ NAT Gateway โ Private ์๋ธ๋ท ์์๋ฐ์ด๋
โ โโโ Bastion Host โ ์์ ํ SSH ์ ๊ทผ
โโโ Private Subnet (10.0.64.0/20)
โโโ Application Server (Spring Boot, MySQL, Redis)
- Security Group: ๋ฆฌ์์ค๋ณ ์ต์ ๊ถํ ์์น ์ ์ฉ
- IAM Role: EC2๊ฐ S3์ ์์ ํ๊ฒ ์ ๊ทผ (Access Key ๋ถํ์)
- HTTPS ๊ฐ์ : ACM ์ธ์ฆ์๋ก ๋ชจ๋ ํธ๋ํฝ ์ํธํ
- Bastion Host: Private ์๋ฒ ์ ๊ทผ ๋จ์ผ ์ง์ ์
User โ Route53 โ CloudFront โ S3 (React)
โ Route53 โ ALB โ Target Group (Spring Boot)
โโโ Blue (8080)
โโโ Green (8081) โ ๋ฌด์ค๋จ ์ ํ
| ๋๋ฉ์ธ | ์ฉ๋ | ๊ธฐ์ |
|---|---|---|
| www.loglens.co.kr | ํ๋ก ํธ์๋ | CloudFront + S3 |
| api.loglens.co.kr | ๋ฐฑ์๋ API | ALB โ Spring Boot |
| jenkins_be.loglens.co.kr | CI/CD | ALB โ Jenkins |
| bastion.loglens.co.kr | ๊ด๋ฆฌ ์ ์ | Bastion Host |
์ธ์คํด์ค: t2.xlarge (4 vCPU, 16GB RAM)
๊ตฌ์ฑ ์์
- Kafka: ๋ก๊ทธ ์คํธ๋ฆฌ๋ฐ, Snappy ์์ถ
- Logstash: ๋ก๊ทธ ์ ๊ทํ ๋ฐ OpenSearch ์ธ๋ฑ์ฑ
- OpenSearch 2.17: KNN ๋ฒกํฐ ๊ฒ์, ILM ์๋ ์ญ์
- FastAPI: AI ๋ถ์ API, 2๋จ๊ณ ์บ์ฑ
React App โ api.loglens.co.kr โ Route53 โ ALB โ Spring Boot
Application โ Fluent Bit โ Kafka โ Logstash โ OpenSearch
โ
AI ๋ถ์ (์บ์ฑ)
Admin โ bastion.loglens.co.kr โ Bastion Host โ Private Servers
- Fluent Bit ๋์ ์ผ๋ก ๋ฆฌ์์ค ์ฌ์ฉ๋ 90% ์ ๊ฐ
- JPA ๋ฐฐ์น ์ฒ๋ฆฌ๋ก DB ์๋ณต ์ต์ํ
- CloudFront ์บ์ฑ์ผ๋ก ์๋ต ์๋ ๊ฐ์
- AI 2๋จ๊ณ ์บ์ฑ์ผ๋ก GPT ๋น์ฉ 97-99% ์ ๊ฐ
- Kafka Snappy ์์ถ์ผ๋ก ๋์ญํญ 50% ์ ๊ฐ
- Blue/Green ๋ฐฐํฌ๋ก ๋ฌด์ค๋จ ์๋น์ค
- ์๋ ํฌ์ค์ฒดํฌ ๋ฐ ์ฌ์์
- ๋ถ์ฐ ์ถ์ (TraceID)์ผ๋ก ์๋ฌ ์์ธ ๋น ๋ฅธ ํ์
- Private ์๋ธ๋ท์ผ๋ก ์๋ฒ ๋ณดํธ
- JWT Rotation์ผ๋ก ํ ํฐ ํ์ทจ ๋ฐฉ์ด
- ๋ฏผ๊ฐ์ ๋ณด ์๋ ๋ง์คํน













