# stock-frontend 한국 주식 분석 플랫폼의 **웹 대시보드**. Next.js 기반으로 APISIX 게이트웨이를 통해 모든 백엔드 서비스의 데이터를 시각화합니다. ## 기능 - **대시보드**: 서비스 상태, 스크리닝 결과 요약, Stream 통계 실시간 표시 - **종목 목록**: 검색, KOSPI/KOSDAQ 필터, 시가총액 기준 정렬, 등락률 표시 - **종목 상세**: 가격 정보, 밸류에이션 지표(PER/PBR/ROE), AI 분석, 공시 목록 - **스크리닝**: 전략별 스크리닝 실행 트리거 + 결과 테이블 표시 - **파이프라인 모니터링**: 6개 서비스 상태, Redis Stream 큐 길이, 데이터 흐름도 ## 페이지 구성 | 경로 | 페이지 | 설명 | |------|--------|------| | `/` | 대시보드 | 전체 현황, 서비스 상태, 최근 스크리닝 결과 | | `/stock` | 종목 목록 | 검색, 필터, 종목 카드 그리드 | | `/stock/[code]` | 종목 상세 | 가격, 밸류에이션, AI 분석, 공시 | | `/screening` | 스크리닝 | 실행 트리거, 결과 테이블 | | `/pipeline` | 파이프라인 | 서비스 상태, Stream 모니터링 | ## 기술 스택 | 기술 | 버전 | 용도 | |------|------|------| | Next.js | 16.1 | React 프레임워크 (App Router) | | React | 19.2 | UI 라이브러리 | | TypeScript | 5.x | 타입 안전성 | | Tailwind CSS | 4.x | 유틸리티 CSS | | Lucide React | 0.575 | 아이콘 | | Recharts | 3.7 | 차트 (향후 사용) | ## API 클라이언트 모든 API 호출은 `src/lib/api.ts`의 타입 안전한 클라이언트를 통해 APISIX 게이트웨이(`/api/v1/...`)로 전달됩니다. ```typescript import { fetchStocks, fetchStock, fetchScreeningLatest } from "@/lib/api"; // 종목 검색 const { total, stocks } = await fetchStocks({ search: "삼성", market: "KOSPI" }); // 종목 상세 const detail = await fetchStock("005930"); // 스크리닝 결과 const screening = await fetchScreeningLatest(10); ``` ### API 클라이언트 함수 목록 | 함수 | 게이트웨이 경로 | 설명 | |------|---------------|------| | `fetchAllHealth()` | `GET /{svc}/health` | 전체 서비스 헬스체크 | | `fetchAllStreams()` | `GET /{svc}/streams` | 전체 Stream 정보 | | `fetchStocks()` | `GET /kis/stocks` | 종목 목록 | | `fetchStock(code)` | `GET /kis/stocks/{code}` | 종목 상세 | | `fetchScreeningLatest()` | `GET /screening/results/latest` | 스크리닝 결과 | | `fetchCatalystResults(code)` | `GET /catalyst/results/{code}` | 공시/카탈리스트 | | `fetchAnalysisResults(code)` | `GET /analysis/results/{code}` | AI 분석 결과 | | `triggerScreening()` | `POST /screening/screen` | 스크리닝 실행 | | `triggerDartFinancials()` | `POST /dart/collect/financials` | DART 수집 | | `triggerKisCollect()` | `POST /kis/collect/stocks` | KIS 수집 | | `triggerNewsCrawl()` | `POST /news/collect/news` | 뉴스 수집 | ## 프로젝트 구조 ``` stock-frontend/ ├── package.json ├── next.config.ts ├── Dockerfile # 멀티 스테이지 빌드 ├── .dockerignore ├── src/ │ ├── app/ │ │ ├── layout.tsx # 루트 레이아웃 (Sidebar 포함) │ │ ├── page.tsx # 대시보드 │ │ ├── globals.css # Tailwind 글로벌 스타일 │ │ ├── pipeline/ │ │ │ └── page.tsx # 파이프라인 모니터링 │ │ ├── screening/ │ │ │ └── page.tsx # 스크리닝 │ │ └── stock/ │ │ ├── page.tsx # 종목 목록 │ │ └── [code]/ │ │ └── page.tsx # 종목 상세 │ ├── components/ │ │ ├── sidebar.tsx # 사이드바 네비게이션 │ │ └── stat-card.tsx # 통계 카드 컴포넌트 │ └── lib/ │ ├── api.ts # 게이트웨이 API 클라이언트 │ └── types.ts # 공통 타입 정의 └── public/ ``` ## 빠른 시작 ### 로컬 개발 ```bash npm install npm run dev ``` `http://localhost:3000`에서 접근 가능. 기본적으로 게이트웨이 `http://localhost:9080/api/v1`에 연결합니다. ### Docker ```bash # stock-gateway의 docker-compose 사용 (권장) cd ../stock-gateway && docker compose up stock-frontend # 단독 빌드 docker build --build-arg NEXT_PUBLIC_API_URL=http://localhost:9080/api/v1 -t stock-frontend . docker run -p 3000:3000 stock-frontend ``` ## 환경변수 | 변수 | 설명 | 기본값 | |------|------|--------| | `NEXT_PUBLIC_API_URL` | APISIX 게이트웨이 URL | `http://localhost:9080/api/v1` | > `NEXT_PUBLIC_*` 변수는 **빌드 타임**에 번들에 포함됩니다. Docker에서는 `ARG`로 빌드 시 주입합니다. ## Docker 빌드 구조 ```dockerfile # Stage 1: 의존성 설치 FROM node:20-alpine AS deps RUN npm ci # Stage 2: 빌드 (API URL 주입) FROM node:20-alpine AS builder ARG NEXT_PUBLIC_API_URL=http://localhost:9080/api/v1 ENV NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL RUN npm run build # Stage 3: 프로덕션 실행 FROM node:20-alpine AS runner COPY --from=builder .next/standalone ./ CMD ["node", "server.js"] ``` ## 의존성 - Node.js >= 20 - Next.js 16.1 (App Router, standalone output) - React 19, TypeScript 5, Tailwind CSS 4