14f5bef1c42d7257891afb083486af5de280cff0
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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/...)로 전달됩니다.
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/
빠른 시작
로컬 개발
npm install
npm run dev
http://localhost:3000에서 접근 가능. 기본적으로 게이트웨이 http://localhost:9080/api/v1에 연결합니다.
Docker
# 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 빌드 구조
# 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
Description
Languages
TypeScript
96.2%
CSS
1.6%
JavaScript
1.1%
Dockerfile
1.1%