# π Stock Oracle Frontend
React + Next.jsλ‘ κ΅¬μΆλ Stock Oracle μΉ νλ‘ νΈμλμ
λλ€.
## β¨ μ£Όμ κΈ°λ₯
### π λμ보λ
- μ€μκ° μμ€ν
μν λͺ¨λν°λ§
- λ°μ΄ν°λ² μ΄μ€ ν΅κ³ μμ½
- λΉ λ₯Έ μ‘μ
λ²νΌ
- λ°μ΄ν° νμ§ κ°μ
### π λ°μ΄ν° μ‘°ν
- μ£Όμ μ’
λͺ©λ³ μ¬λ¬΄ λ°μ΄ν° κ²μ
- λΆκΈ°λ³/μ°κ°/μ 체 κΈ°κ° μ‘°ν
- μ€μ vs μΆμ λ°μ΄ν° νμ
- μ¬λ¬΄ μ§ν κ³μ° κ²°κ³Ό ν¬ν¨
### πΎ DB μν
- λ°μ΄ν°λ² μ΄μ€ νν© μ€μκ° λͺ¨λν°λ§
- νμ¬, μ¬λ¬΄ λ°μ΄ν°, μ£Όκ° λ°μ΄ν° ν΅κ³
- λ°μ΄ν° μμ€λ³ λΆν¬
- λ°μ΄ν° νμ§ λΆμ
### βοΈ μ€μ
- API URL μ€μ
- μλ μλ‘κ³ μΉ¨ μ΅μ
- UI ν
λ§ μ ν
- μμ€ν
μ 보 νμΈ
## π λΉ λ₯Έ μμ
### λ‘컬 κ°λ° νκ²½
```bash
# μμ‘΄μ± μ€μΉ
cd frontend
npm install
# νκ²½ λ³μ μ€μ
cp .env.example .env.local
# κ°λ° μλ² μμ
npm run dev
```
μΉ λΈλΌμ°μ μμ `http://localhost:3000` μ μ
### Dockerλ‘ μ€ν
```bash
# μ΄λ―Έμ§ λΉλ
docker build -t stock-oracle-frontend .
# 컨ν
μ΄λ μ€ν
docker run -p 3000:3000 -e NEXT_PUBLIC_API_URL=http://localhost:18001/api/v1 stock-oracle-frontend
```
### Portainerλ‘ μ 체 μ€ν λ°°ν¬
```bash
# μ 체 μ€ν λ°°ν¬ (API + Frontend + DB + Nginx)
docker-compose -f portainer/docker-compose.full-stack.yml up -d
```
μ μ URL: `https://localhost` (Nginxλ₯Ό ν΅ν ν΅ν© μ μ)
## π οΈ κΈ°μ μ€ν
### Frontend Framework
- **Next.js 14** - React λ©ν νλ μμν¬
- **React 18** - UI λΌμ΄λΈλ¬λ¦¬
- **TypeScript** - νμ
μμ μ±
### Styling & UI
- **Tailwind CSS** - μ νΈλ¦¬ν° CSS νλ μμν¬
- **Lucide React** - μμ΄μ½ λΌμ΄λΈλ¬λ¦¬
- **Responsive Design** - λͺ¨λ°μΌ μΉνμ λμμΈ
### Data Management
- **Axios** - HTTP ν΄λΌμ΄μΈνΈ
- **React Query** - μλ² μν κ΄λ¦¬
- **SWR ν¨ν΄** - λ°μ΄ν° νμΉ μ λ΅
### Charts & Visualization
- **Recharts** - React μ°¨νΈ λΌμ΄λΈλ¬λ¦¬
- **Date-fns** - λ μ§ μ²λ¦¬
## π νλ‘μ νΈ κ΅¬μ‘°
```
frontend/
βββ components/ # μ¬μ¬μ© κ°λ₯ν μ»΄ν¬λνΈ
β βββ Layout.tsx # λ©μΈ λ μ΄μμ
β βββ StockQuery.tsx # μ£Όμ λ°μ΄ν° μ‘°ν
β βββ DatabaseStats.tsx # DB μν λͺ¨λν°λ§
βββ lib/ # μ νΈλ¦¬ν° λ° μ€μ
β βββ api.ts # API ν΄λΌμ΄μΈνΈ λ° νμ
βββ pages/ # Next.js νμ΄μ§
β βββ index.tsx # λμ보λ
β βββ query.tsx # λ°μ΄ν° μ‘°ν
β βββ database.tsx # DB μν
β βββ settings.tsx # μ€μ
βββ styles/ # μ€νμΌμνΈ
β βββ globals.css # κΈλ‘λ² CSS
βββ public/ # μ μ νμΌ
```
## π§ νκ²½ λ³μ
### .env.local μ€μ
```bash
# API μ€μ
NEXT_PUBLIC_API_URL=http://localhost:18001/api/v1
# μ ν리μΌμ΄μ
μ€μ
NEXT_PUBLIC_APP_NAME=Stock Oracle
NEXT_PUBLIC_APP_VERSION=1.0.0
# κΈ°λ₯ νλκ·Έ
NEXT_PUBLIC_ENABLE_ANALYTICS=false
NEXT_PUBLIC_ENABLE_PWA=false
```
### νλ‘λμ
νκ²½
```bash
# Docker νκ²½μμ μλ μ€μ
NEXT_PUBLIC_API_URL=http://api:8000/api/v1
NODE_ENV=production
```
## π API μ°λ
### API ν΄λΌμ΄μΈνΈ
`lib/api.ts`μμ λͺ¨λ API νΈμΆμ κ΄λ¦¬ν©λλ€:
```typescript
// μ¬λ¬΄ λ°μ΄ν° μ‘°ν
const data = await stockApi.getFinancialData({
ticker: 'AAPL',
start_date: '2024-01-01',
end_date: '2024-12-31',
period_type: 'quarterly',
include_metrics: true
});
// λ°μ΄ν°λ² μ΄μ€ ν΅κ³ μ‘°ν
const stats = await stockApi.getDatabaseStats();
```
### μ£Όμ API μλν¬μΈνΈ
- `POST /api/v1/financial/data` - μ¬λ¬΄ λ°μ΄ν° μ‘°ν
- `POST /api/v1/price/data` - μ£Όκ° λ°μ΄ν° μ‘°ν
- `GET /api/v1/database/stats` - DB ν΅κ³
- `GET /api/v1/tickers` - μ¬μ© κ°λ₯ν μ’
λͺ© λͺ©λ‘
## π¨ UI/UX νΉμ§
### λ°μν λμμΈ
- **Desktop First**: λν νλ©΄ μ°μ μ€κ³
- **Mobile Optimized**: λͺ¨λ°μΌ κΈ°κΈ° μλ²½ μ§μ
- **Tablet Friendly**: νλΈλ¦Ώ νκ²½ μ΅μ ν
### μ¬μ©μ κ²½ν
- **μ§κ΄μ λ€λΉκ²μ΄μ
**: λͺ
νν λ©λ΄ ꡬ쑰
- **μ€μκ° νΌλλ°±**: λ‘λ© μν λ° μλ¬ μ²λ¦¬
- **λ°μ΄ν° μκ°ν**: μ°¨νΈμ κ·Έλνλ‘ μ΄ν΄νκΈ° μ¬μ΄ νν
### μ κ·Όμ±
- **ν€λ³΄λ λ€λΉκ²μ΄μ
**: ν€λ³΄λλ§μΌλ‘ λͺ¨λ κΈ°λ₯ μ κ·Ό
- **Screen Reader**: μ€ν¬λ¦° 리λ μ§μ
- **κ³ λλΉ λͺ¨λ**: μκ°μ μ κ·Όμ± κ³ λ €
## π μ£Όμ μ»΄ν¬λνΈ
### Layout μ»΄ν¬λνΈ
```typescript
// μ 체 λ μ΄μμ λ° λ€λΉκ²μ΄μ
{children}
```
### StockQuery μ»΄ν¬λνΈ
```typescript
// μ£Όμ λ°μ΄ν° μ‘°ν νΌ λ° κ²°κ³Ό νμ
```
### DatabaseStats μ»΄ν¬λνΈ
```typescript
// λ°μ΄ν°λ² μ΄μ€ ν΅κ³ λ° μν λͺ¨λν°λ§
```
## π§ͺ κ°λ° λꡬ
### κ°λ° μλ²
```bash
npm run dev # κ°λ° μλ² μμ
npm run build # νλ‘λμ
λΉλ
npm run start # νλ‘λμ
μλ² μμ
npm run lint # ESLint μ€ν
```
### νμ
체ν¬
```bash
npx tsc --noEmit # TypeScript νμ
체ν¬
```
## π λ°°ν¬
### Vercel λ°°ν¬
```bash
# Vercel CLIλ‘ λ°°ν¬
vercel --prod
```
### Docker λ°°ν¬
```bash
# μ΄λ―Έμ§ λΉλ λ° λ°°ν¬
docker build -t stock-oracle-frontend .
docker run -p 3000:3000 stock-oracle-frontend
```
### Portainer ν΅ν© λ°°ν¬
```bash
# μ 체 μ€ν λ°°ν¬
./portainer/quick-deploy.sh
```
## π± λΈλΌμ°μ μ§μ
- **Chrome** 90+
- **Firefox** 88+
- **Safari** 14+
- **Edge** 90+
## π 보μ κ³ λ €μ¬ν
### API ν΅μ
- **HTTPS Only**: νλ‘λμ
μμ HTTPS κ°μ
- **CORS μ€μ **: μ μ ν CORS μ μ±
- **Rate Limiting**: API νΈμΆ μ ν
### λ°μ΄ν° 보νΈ
- **μ
λ ₯ κ²μ¦**: λͺ¨λ μ¬μ©μ μ
λ ₯ κ²μ¦
- **XSS λ°©μ§**: Reactμ κΈ°λ³Έ XSS 보νΈ
- **CSRF λ°©μ§**: SameSite μΏ ν€ μ€μ
## π λ¬Έμ ν΄κ²°
### μΌλ°μ μΈ λ¬Έμ
#### API μ°κ²° μ€ν¨
```bash
# API μλ² μν νμΈ
curl http://localhost:18001/api/v1/database/stats
# νκ²½ λ³μ νμΈ
echo $NEXT_PUBLIC_API_URL
```
#### λΉλ μ€ν¨
```bash
# μΊμ ν΄λ¦¬μ΄
rm -rf .next node_modules
npm install
npm run build
```
#### Docker μ€ν λ¬Έμ
```bash
# ν¬νΈ μΆ©λ νμΈ
netstat -tlnp | grep 3000
# 컨ν
μ΄λ λ‘κ·Έ νμΈ
docker logs stock-oracle-frontend
```
## π μ±λ₯ μ΅μ ν
### μ΄λ―Έμ§ μ΅μ ν
- **Next.js Image**: μλ μ΄λ―Έμ§ μ΅μ ν
- **WebP μ§μ**: μ΅μ μ΄λ―Έμ§ ν¬λ§· μ¬μ©
### μ½λ λΆν
- **Dynamic Import**: νμν λλ§ μ»΄ν¬λνΈ λ‘λ
- **Tree Shaking**: μ¬μ©νμ§ μλ μ½λ μ κ±°
### μΊμ± μ λ΅
- **Static Generation**: μ μ νμ΄μ§ μμ±
- **API Cache**: React Queryλ‘ API μλ΅ μΊμ±
## π€ κΈ°μ¬ κ°μ΄λ
1. Fork the repository
2. Create your feature branch (`git checkout -b feature/AmazingFeature`)
3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
4. Push to the branch (`git push origin feature/AmazingFeature`)
5. Open a Pull Request
## π λΌμ΄μ μ€
MIT License - μμΈν λ΄μ©μ LICENSE νμΌμ μ°Έμ‘°νμΈμ.