Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
daffc31
feat: Vite ๊ธฐ๋ฐ˜ ํ”„๋กœ์ ํŠธ ์ดˆ๊ธฐ ์…‹์—…
YounaJ00 Nov 22, 2025
36cb806
docs: ํ”„๋ก ํŠธ์—”๋“œ README.md ์ถ”๊ฐ€
YounaJ00 Nov 22, 2025
9a59b8f
chore: TailwinCSS ๋ฐ shadcn/ui ๊ธฐ๋ณธ ์„ค์ •
YounaJ00 Nov 23, 2025
260743d
feat(UI): ๊ธฐ๋ณธ UI ์ปดํฌ๋„ŒํŠธ ์ถ”๊ฐ€ ๋ฐ ๊ตฌ์„ฑ
YounaJ00 Nov 23, 2025
cca100d
feat(api): api ํด๋ผ์ด์–ธํŠธ ๋ฐ ํƒ€์ž… ์ •์˜
YounaJ00 Nov 23, 2025
cc15a1b
feat(toast): ํ† ์ŠคํŠธ ์•Œ๋ฆผ ์‹œ์Šคํ…œ ๊ตฌํ˜„
YounaJ00 Nov 23, 2025
bd36ff9
feat(list):Coin List Page ๊ตฌํ˜„ ๋ฐ ์—ฐ๋™
YounaJ00 Nov 23, 2025
705a9d5
refact(main): Main Page ๊ธฐ๋Šฅ๋ณ„ ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ
YounaJ00 Nov 24, 2025
bc4907f
feat(coin): ์ฝ”์ธ ๋ชฉ๋ก ์ƒ์ˆ˜ ๋ถ„๋ฆฌ
YounaJ00 Nov 24, 2025
40d0e53
feat(api): ๊ธฐ๋ณธ API BASE URL์„ ๋กœ์ปฌ ์„œ๋ฒ„๋กœ ๋ณ€๊ฒฝ
YounaJ00 Nov 24, 2025
d26475e
refact(coin): ์ƒ์ˆ˜ ๋ถ„๋ฆฌ ํ›„ import
YounaJ00 Nov 24, 2025
34d13bf
feat(trans): ๊ฑฐ๋ž˜ ๋‚ด์—ญ ์ปดํฌ๋„ŒํŠธ ์ถ”๊ฐ€
YounaJ00 Nov 24, 2025
2b40af1
chore: ์„ค์ • ๋ณ€๊ฒฝ ๋ฐ ๊ธฐํƒ€ ์ฝ”๋“œ ์ •๋ฆฌ
YounaJ00 Nov 24, 2025
59344cf
feat(docker): ๋„์ปค ํ™˜๊ฒฝ์—์„œ ํ”„๋ก ํŠธ์—”๋“œ ์ปจํ…Œ์ด๋„ˆ ๊ตฌ์„ฑ ์ถ”๊ฐ€
YounaJ00 Nov 24, 2025
b76cf29
feat(api): feat(frontend): ํ™˜๊ฒฝ๋ณ€์ˆ˜ ๊ธฐ๋ฐ˜ API ์„ค์ • ์ถ”๊ฐ€
YounaJ00 Nov 24, 2025
03d4602
feat(api): Vite ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ๊ธฐ๋ฐ˜ API Base URL ์ฒ˜๋ฆฌ ๋กœ์ง ๊ฐœ์„ 
YounaJ00 Nov 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions backend/app/configs/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ async def lifespan(app: FastAPI) -> AsyncIterator[None]:
await conn.run_sync(lambda _: None) # ์—ฐ๊ฒฐ ํ…Œ์ŠคํŠธ

# ์Šค์ผ€์ค„๋Ÿฌ ์‹œ์ž‘
scheduler.add_job(trade_execution_job, "interval", seconds=30)
scheduler.start()
# scheduler.add_job(trade_execution_job, "interval", seconds=30)
# scheduler.start()

yield

Expand Down
17 changes: 16 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ services:
- "3306:3306"
volumes:
- db-data:/var/lib/mysql
# - ./infra/init.sql:/docker-entrypoint-initdb.d/init.sql
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
networks:
- joo-coin
healthcheck:
Expand Down Expand Up @@ -47,6 +47,21 @@ services:
"
restart: unless-stopped

joo-coin-frontend:
build:
context: ./frontend
dockerfile: Dockerfile
container_name: joo-coin-frontend
ports:
- "5173:5173"
volumes:
- ./frontend:/app
- /app/node_modules
depends_on:
- joo-coin-backend
networks:
- joo-coin

volumes:
db-data:

Expand Down
24 changes: 24 additions & 0 deletions frontend/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
8 changes: 8 additions & 0 deletions frontend/.vite/deps/_metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"hash": "3e5e4128",
"configHash": "f8ff4908",
"lockfileHash": "608c272f",
"browserHash": "94f0d377",
"optimized": {},
"chunks": {}
}
3 changes: 3 additions & 0 deletions frontend/.vite/deps/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"type": "module"
}
19 changes: 19 additions & 0 deletions frontend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
FROM node:22-alpine

WORKDIR /app

# Install pnpm
RUN corepack enable && corepack prepare pnpm@latest --activate

# Copy package files
COPY package.json pnpm-lock.yaml ./

# Install dependencies
RUN pnpm install --frozen-lockfile

# Copy source code
COPY . .

EXPOSE 5173

CMD ["pnpm", "dev", "--host"]
54 changes: 54 additions & 0 deletions frontend/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Joo Coin Frontend

React + TypeScript + Vite ๊ธฐ๋ฐ˜์˜ ์•”ํ˜ธํ™”ํ ๊ฑฐ๋ž˜์†Œ ํ”„๋ก ํŠธ์—”๋“œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ž…๋‹ˆ๋‹ค.

## ๊ธฐ์ˆ  ์Šคํƒ

- **React 19** - UI ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
- **TypeScript** - ํƒ€์ž… ์•ˆ์ •์„ฑ
- **Vite** - ๋นŒ๋“œ ๋„๊ตฌ
- **TailwindCSS** - ์Šคํƒ€์ผ๋ง
- **shadcn/ui** - UI ์ปดํฌ๋„ŒํŠธ
- **Recharts** - ์ฐจํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
- **Axios** - HTTP ํด๋ผ์ด์–ธํŠธ

## ์ฃผ์š” ๊ธฐ๋Šฅ

### 1. ์ฝ”์ธ ๊ด€๋ฆฌ

[x] ๋‚ด ๊ฑฐ๋ž˜ ์ฝ”์ธ ๋ชฉ๋ก ์กฐํšŒ
[x] ์ฝ”์ธ ์ถ”๊ฐ€/์‚ญ์ œ
[x] ์ฝ”์ธ ๊ฒ€์ƒ‰

### 2. ์ฐจํŠธ ์กฐํšŒ

[x] ์„ ํƒํ•œ ์ฝ”์ธ์˜ OHLCV ๋ฐ์ดํ„ฐ ์‹œ๊ฐํ™”
[x] ์บ”๋“ค์Šคํ‹ฑ ์ฐจํŠธ ๋ฐ ๋ผ์ธ ์ฐจํŠธ ์ „ํ™˜
[x] ๊ฑฐ๋ž˜๋Ÿ‰ ์ฐจํŠธ

### 3. ๊ฑฐ๋ž˜ ๋‚ด์—ญ

[x] ๊ฑฐ๋ž˜ ๋‚ด์—ญ ์กฐํšŒ (ํŽ˜์ด์ง€๋„ค์ด์…˜)
[x] ์ฆ‰์‹œ ๊ฑฐ๋ž˜ ์‹คํ–‰
[x] ๊ฑฐ๋ž˜ ์ƒํƒœ ๋ฐ ์ƒ์„ธ ์ •๋ณด ํ‘œ์‹œ

## ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ

```
src/
โ”œโ”€โ”€ components/ # React ์ปดํฌ๋„ŒํŠธ
โ”‚ โ”œโ”€โ”€ ui/ # shadcn/ui ์ปดํฌ๋„ŒํŠธ
โ”‚ โ”œโ”€โ”€ CoinList.tsx # ์ฝ”์ธ ๋ชฉ๋ก ์ปดํฌ๋„ŒํŠธ
โ”‚ โ”œโ”€โ”€ CoinChart.tsx # ์ฐจํŠธ ์ปดํฌ๋„ŒํŠธ
โ”‚ โ”œโ”€โ”€ TransactionHistory.tsx # ๊ฑฐ๋ž˜ ๋‚ด์—ญ ์ปดํฌ๋„ŒํŠธ
โ”‚ โ””โ”€โ”€ Toaster.tsx # ํ† ์ŠคํŠธ ์•Œ๋ฆผ ์ปดํฌ๋„ŒํŠธ
โ”œโ”€โ”€ contexts/ # React Context
โ”‚ โ””โ”€โ”€ ToastContext.tsx # ํ† ์ŠคํŠธ ์ปจํ…์ŠคํŠธ
โ”œโ”€โ”€ lib/ # ์œ ํ‹ธ๋ฆฌํ‹ฐ ๋ฐ API
โ”‚ โ”œโ”€โ”€ api.ts # API ํด๋ผ์ด์–ธํŠธ
โ”‚ โ””โ”€โ”€ utils.ts # ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜
โ”œโ”€โ”€ hooks/ # ์ปค์Šคํ…€ ํ›…
โ”‚ โ””โ”€โ”€ use-toast.ts # ํ† ์ŠคํŠธ ํ›… (์žฌexport)
โ”œโ”€โ”€ App.tsx # ๋ฉ”์ธ ์•ฑ ์ปดํฌ๋„ŒํŠธ
โ””โ”€โ”€ main.tsx # ์ง„์ž…์ 
```
21 changes: 21 additions & 0 deletions frontend/components.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "default",
"rsc": false,
"tsx": true,
"tailwind": {
"config": "tailwind.config.js",
"css": "src/index.css",
"baseColor": "neutral",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
}
}

23 changes: 23 additions & 0 deletions frontend/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import js from '@eslint/js'
import globals from 'globals'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
import tseslint from 'typescript-eslint'
import { defineConfig, globalIgnores } from 'eslint/config'

export default defineConfig([
globalIgnores(['dist']),
{
files: ['**/*.{ts,tsx}'],
extends: [
js.configs.recommended,
tseslint.configs.recommended,
reactHooks.configs.flat.recommended,
reactRefresh.configs.vite,
],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
},
])
13 changes: 13 additions & 0 deletions frontend/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en" class="dark">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>frontend</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
44 changes: 44 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"name": "frontend",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"lint": "eslint .",
"preview": "vite preview"
},
"dependencies": {
"axios": "^1.13.2",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"lucide-react": "^0.554.0",
"react": "^19.2.0",
"react-dom": "^19.2.0",
"react-router-dom": "^7.9.6",
"recharts": "^3.4.1",
"tailwind-merge": "^3.4.0"
},
"devDependencies": {
"@eslint/js": "^9.39.1",
"@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-select": "^2.2.6",
"@radix-ui/react-slot": "^1.2.4",
"@radix-ui/react-tabs": "^1.1.13",
"@tailwindcss/postcss": "^4.1.17",
"@types/node": "^24.10.1",
"@types/react": "^19.2.5",
"@types/react-dom": "^19.2.3",
"@vitejs/plugin-react": "^5.1.1",
"autoprefixer": "^10.4.22",
"eslint": "^9.39.1",
"eslint-plugin-react-hooks": "^7.0.1",
"eslint-plugin-react-refresh": "^0.4.24",
"globals": "^16.5.0",
"tailwindcss": "^4.1.17",
"typescript": "~5.9.3",
"typescript-eslint": "^8.46.4",
"vite": "^7.2.4"
}
}
Loading