diff --git a/package-lock.json b/package-lock.json
index 572fadc..4850d3e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,6 +11,7 @@
"@tailwindcss/vite": "^4.1.18",
"react": "^19.2.0",
"react-dom": "^19.2.0",
+ "react-router-dom": "^7.12.0",
"tailwindcss": "^4.1.18"
},
"devDependencies": {
@@ -1872,6 +1873,19 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/cookie": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz",
+ "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
@@ -3058,6 +3072,44 @@
"node": ">=0.10.0"
}
},
+ "node_modules/react-router": {
+ "version": "7.12.0",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.12.0.tgz",
+ "integrity": "sha512-kTPDYPFzDVGIIGNLS5VJykK0HfHLY5MF3b+xj0/tTyNYL1gF1qs7u67Z9jEhQk2sQ98SUaHxlG31g1JtF7IfVw==",
+ "license": "MIT",
+ "dependencies": {
+ "cookie": "^1.0.1",
+ "set-cookie-parser": "^2.6.0"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=18",
+ "react-dom": ">=18"
+ },
+ "peerDependenciesMeta": {
+ "react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-router-dom": {
+ "version": "7.12.0",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.12.0.tgz",
+ "integrity": "sha512-pfO9fiBcpEfX4Tx+iTYKDtPbrSLLCbwJ5EqP+SPYQu1VYCXdy79GSj0wttR0U4cikVdlImZuEZ/9ZNCgoaxwBA==",
+ "license": "MIT",
+ "dependencies": {
+ "react-router": "7.12.0"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=18",
+ "react-dom": ">=18"
+ }
+ },
"node_modules/resolve-from": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
@@ -3128,6 +3180,12 @@
"semver": "bin/semver.js"
}
},
+ "node_modules/set-cookie-parser": {
+ "version": "2.7.2",
+ "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz",
+ "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==",
+ "license": "MIT"
+ },
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
diff --git a/package.json b/package.json
index 00d7353..6191494 100644
--- a/package.json
+++ b/package.json
@@ -13,6 +13,7 @@
"@tailwindcss/vite": "^4.1.18",
"react": "^19.2.0",
"react-dom": "^19.2.0",
+ "react-router-dom": "^7.12.0",
"tailwindcss": "^4.1.18"
},
"devDependencies": {
diff --git a/src/App.jsx b/src/App.jsx
index 53eb971..bbf75f1 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -1,11 +1,23 @@
import './App.css'
+import { BrowserRouter, Routes, Route } from "react-router-dom";
+import MainPage from './pages/MainPage'
+import CoinDetailPage from './pages/CoinDetailPage';
+import NewsDetailPage from './pages/NewsDetailPage';
+import GamePage from './pages/GamePage';
+import LeaderBoardPage from './pages/LeaderBoardPage';
function App() {
return (
- <>
-
CoinSight
- >
+
+
+ } />
+ } />
+ } />
+ } />
+ } />
+
+
)
}
diff --git a/src/components/common/Navbar.jsx b/src/components/common/Navbar.jsx
new file mode 100644
index 0000000..5bf7b0b
--- /dev/null
+++ b/src/components/common/Navbar.jsx
@@ -0,0 +1,35 @@
+import { useNavigate } from "react-router-dom";
+
+const Navbar = () => {
+ const nav = useNavigate();
+ return (
+
+
+ CoinSight
+
+
+
+
nav("/")}
+ className="cursor-pointer"
+ >
+ 메인
+
+
nav("/game")}
+ className="cursor-pointer"
+ >
+ 게임
+
+
nav("/leaderboard")}
+ className="cursor-pointer"
+ >
+ 리더보드
+
+
+
+ )
+}
+
+export default Navbar;
\ No newline at end of file
diff --git a/src/index.css b/src/index.css
index f173aa4..b5f37f0 100644
--- a/src/index.css
+++ b/src/index.css
@@ -1 +1,7 @@
-@import 'tailwindcss';
\ No newline at end of file
+@import 'tailwindcss';
+
+body {
+ background-color: #FAFAFA;
+ margin: 0;
+ padding: 0;
+}
\ No newline at end of file
diff --git a/src/pages/CoinDetailPage.jsx b/src/pages/CoinDetailPage.jsx
new file mode 100644
index 0000000..3489df7
--- /dev/null
+++ b/src/pages/CoinDetailPage.jsx
@@ -0,0 +1,83 @@
+import { useEffect, useState } from "react";
+import Navbar from "../components/common/Navbar";
+
+const CoinDetailPage = () => {
+ const coinName = "KRW-BTC";
+ const [currentPrice, setCurrentPrice] = useState(0);
+ const [tradePrice, setTradePrice] = useState(0);
+ const [fluctuationRange, setFluctuationRange] = useState(0);
+ const [isPositive, setIsPositive] = useState(true);
+
+ const formatPrice = (value) => {
+ if (!value) return "0억";
+ const formatPrice = Number(value) / 100000000;
+ return `${formatPrice.toLocaleString(undefined, {maximumFractionDigits: 1})}억`;
+ }
+
+ useEffect (() => {
+ const options = {method: 'GET', headers: {accept: 'application/json'}};
+
+ fetch(`https://api.bithumb.com/v1/ticker?markets=${coinName}`, options)
+ .then(response => response.json())
+ .then(response => {
+ console.log(response);
+ const formattedPrice = formatPrice(response[0].acc_trade_price_24h);
+ setTradePrice(formattedPrice);
+ const p = response[0].trade_price.toLocaleString('ko-KR');
+ setCurrentPrice(p);
+ })
+ .catch(err => console.error(err));
+
+ fetch(`https://api.bithumb.com/public/candlestick/BTC_KRW/1h`, options)
+ .then(res => res.json())
+ .then(res => {
+ const data = res.data;
+ const len = data.length;
+ const currentPrice = parseFloat(data[len - 1][2]);
+ const prevPrice = parseFloat(data[len - 2][2]);
+
+ const changeRate = ((currentPrice - prevPrice) / prevPrice) * 100;
+ setFluctuationRange(changeRate.toFixed(2));
+ if (changeRate < 0) setIsPositive(false);
+ })
+ .catch(err => console.error(err));
+ }, [coinName]);
+
+ return (
+
+
+
+
+
+
+ 비트코인(BTC)
+
+
+
+ 2026년 01월 23일
+
+
+
+
+
+
현재가
+
₩{currentPrice}
+
+
+
+
1시간 등락
+
{fluctuationRange}%
+
+
+
+
24시간 거래대금
+
₩{tradePrice}
+
+
+
+
+
+ )
+}
+
+export default CoinDetailPage;
\ No newline at end of file
diff --git a/src/pages/GamePage.jsx b/src/pages/GamePage.jsx
new file mode 100644
index 0000000..349ed36
--- /dev/null
+++ b/src/pages/GamePage.jsx
@@ -0,0 +1,12 @@
+import Navbar from "../components/common/Navbar"
+
+const GamePage = () => {
+ return (
+
+
+ game page
+
+ )
+}
+
+export default GamePage;
\ No newline at end of file
diff --git a/src/pages/LeaderBoardPage.jsx b/src/pages/LeaderBoardPage.jsx
new file mode 100644
index 0000000..832d298
--- /dev/null
+++ b/src/pages/LeaderBoardPage.jsx
@@ -0,0 +1,12 @@
+import Navbar from "../components/common/Navbar"
+
+const LeaderBoardPage = () => {
+ return (
+ <>
+
+ LeaderBoardPage
+ >
+ )
+}
+
+export default LeaderBoardPage;
\ No newline at end of file
diff --git a/src/pages/MainPage.jsx b/src/pages/MainPage.jsx
new file mode 100644
index 0000000..a5a4161
--- /dev/null
+++ b/src/pages/MainPage.jsx
@@ -0,0 +1,12 @@
+import Navbar from "../components/common/Navbar";
+
+const MainPage = () => {
+ return (
+
+
+ main page
+
+ )
+}
+
+export default MainPage;
\ No newline at end of file
diff --git a/src/pages/NewsDetailPage.jsx b/src/pages/NewsDetailPage.jsx
new file mode 100644
index 0000000..116d298
--- /dev/null
+++ b/src/pages/NewsDetailPage.jsx
@@ -0,0 +1,12 @@
+import Navbar from "../components/common/Navbar";
+
+const NewsDetailPage = () => {
+ return (
+
+
+ News Detail Page
+
+ )
+}
+
+export default NewsDetailPage;
\ No newline at end of file