feat(frontend): Phase 1 - 리팩토링을 위한 frontend-temp 프로젝트 셋업
- frontend-temp/ 폴더 생성 (Strangler Fig Pattern) - package.json: clsx 추가, 버전 2.0.0 - vite.config.js: @ path alias 추가 - 기본 폴더 구조 생성 (api, components, hooks, pages, stores, utils, constants) - docker-compose.yml: fromis9-frontend-dev 서비스 추가 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
9d365dcadb
commit
4ec368c936
22 changed files with 3461 additions and 0 deletions
|
|
@ -12,6 +12,19 @@ services:
|
|||
- app
|
||||
restart: unless-stopped
|
||||
|
||||
fromis9-frontend-dev:
|
||||
build: ./frontend-temp
|
||||
container_name: fromis9-frontend-dev
|
||||
labels:
|
||||
- "com.centurylinklabs.watchtower.enable=false"
|
||||
volumes:
|
||||
- ./frontend-temp:/app
|
||||
depends_on:
|
||||
- fromis9-backend
|
||||
networks:
|
||||
- app
|
||||
restart: unless-stopped
|
||||
|
||||
fromis9-backend:
|
||||
build: ./backend
|
||||
container_name: fromis9-backend
|
||||
|
|
|
|||
4
frontend-temp/Dockerfile
Normal file
4
frontend-temp/Dockerfile
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
# 개발 모드
|
||||
FROM node:20-alpine
|
||||
WORKDIR /app
|
||||
CMD ["sh", "-c", "npm install --include=dev && npm run dev -- --host 0.0.0.0"]
|
||||
22
frontend-temp/index.html
Normal file
22
frontend-temp/index.html
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="ko">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, viewport-fit=cover"
|
||||
/>
|
||||
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
||||
<title>fromis_9 - 프로미스나인</title>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
as="style"
|
||||
crossorigin
|
||||
href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/static/pretendard.min.css"
|
||||
/>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.jsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
3175
frontend-temp/package-lock.json
generated
Normal file
3175
frontend-temp/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
44
frontend-temp/package.json
Normal file
44
frontend-temp/package.json
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
{
|
||||
"name": "fromis9-frontend",
|
||||
"private": true,
|
||||
"version": "2.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.28.6",
|
||||
"@tanstack/react-query": "^5.90.16",
|
||||
"@tanstack/react-virtual": "^3.13.18",
|
||||
"canvas-confetti": "^1.9.4",
|
||||
"clsx": "^2.1.1",
|
||||
"dayjs": "^1.11.19",
|
||||
"framer-motion": "^11.0.8",
|
||||
"lucide-react": "^0.344.0",
|
||||
"react": "^18.2.0",
|
||||
"react-calendar": "^6.0.0",
|
||||
"react-colorful": "^5.6.1",
|
||||
"react-device-detect": "^2.2.3",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-infinite-scroll-component": "^6.1.1",
|
||||
"react-intersection-observer": "^10.0.0",
|
||||
"react-ios-time-picker": "^0.2.2",
|
||||
"react-linkify": "^1.0.0-alpha",
|
||||
"react-photo-album": "^3.4.0",
|
||||
"react-router-dom": "^6.22.3",
|
||||
"react-window": "^2.2.3",
|
||||
"swiper": "^12.0.3",
|
||||
"zustand": "^5.0.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.3.3",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@vitejs/plugin-react": "^4.3.1",
|
||||
"autoprefixer": "^10.4.22",
|
||||
"postcss": "^8.5.6",
|
||||
"tailwindcss": "^3.4.18",
|
||||
"vite": "^5.4.1"
|
||||
}
|
||||
}
|
||||
6
frontend-temp/postcss.config.js
Normal file
6
frontend-temp/postcss.config.js
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
export default {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
};
|
||||
41
frontend-temp/src/App.jsx
Normal file
41
frontend-temp/src/App.jsx
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
import { BrowserRouter, Routes, Route } from "react-router-dom";
|
||||
import { isMobile } from "react-device-detect";
|
||||
|
||||
/**
|
||||
* 프로미스나인 팬사이트 메인 앱
|
||||
*
|
||||
* Phase 1: 프로젝트 셋업 완료
|
||||
* - 기본 구조 및 설정 파일 생성
|
||||
* - React Query, React Router 설정
|
||||
* - Tailwind CSS 설정
|
||||
*
|
||||
* 다음 단계에서 유틸리티, 스토어, API, 컴포넌트들이 추가될 예정
|
||||
*/
|
||||
function App() {
|
||||
return (
|
||||
<BrowserRouter>
|
||||
<Routes>
|
||||
<Route
|
||||
path="/"
|
||||
element={
|
||||
<div className="min-h-screen flex items-center justify-center bg-gray-50">
|
||||
<div className="text-center">
|
||||
<h1 className="text-2xl font-bold text-primary mb-2">
|
||||
fromis_9 Frontend Refactoring
|
||||
</h1>
|
||||
<p className="text-gray-600">
|
||||
Phase 1 완료 - 프로젝트 셋업
|
||||
</p>
|
||||
<p className="text-sm text-gray-500 mt-2">
|
||||
디바이스: {isMobile ? "모바일" : "PC"}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
</Routes>
|
||||
</BrowserRouter>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
0
frontend-temp/src/api/.gitkeep
Normal file
0
frontend-temp/src/api/.gitkeep
Normal file
0
frontend-temp/src/components/album/.gitkeep
Normal file
0
frontend-temp/src/components/album/.gitkeep
Normal file
0
frontend-temp/src/components/common/.gitkeep
Normal file
0
frontend-temp/src/components/common/.gitkeep
Normal file
0
frontend-temp/src/components/layout/.gitkeep
Normal file
0
frontend-temp/src/components/layout/.gitkeep
Normal file
0
frontend-temp/src/components/schedule/.gitkeep
Normal file
0
frontend-temp/src/components/schedule/.gitkeep
Normal file
0
frontend-temp/src/constants/.gitkeep
Normal file
0
frontend-temp/src/constants/.gitkeep
Normal file
0
frontend-temp/src/hooks/.gitkeep
Normal file
0
frontend-temp/src/hooks/.gitkeep
Normal file
85
frontend-temp/src/index.css
Normal file
85
frontend-temp/src/index.css
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
/* 기본 스타일 */
|
||||
body {
|
||||
background-color: #fafafa;
|
||||
color: #1a1a1a;
|
||||
}
|
||||
|
||||
/* 스크롤바 스타일 */
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: #f1f1f1;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: #548360;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: #456e50;
|
||||
}
|
||||
|
||||
/* View Transitions API - 앨범 커버 이미지 부드러운 전환 */
|
||||
::view-transition-old(root),
|
||||
::view-transition-new(root) {
|
||||
animation-duration: 0.3s;
|
||||
}
|
||||
|
||||
/* 앨범 커버 트랜지션 */
|
||||
::view-transition-group(*) {
|
||||
animation-duration: 0.4s;
|
||||
animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
::view-transition-old(*) {
|
||||
animation: fade-out 0.3s ease-out both;
|
||||
}
|
||||
|
||||
::view-transition-new(*) {
|
||||
animation: fade-in 0.3s ease-in both;
|
||||
}
|
||||
|
||||
@keyframes fade-out {
|
||||
from {
|
||||
opacity: 1;
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fade-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* 라이트박스 스크롤바 숨기기 */
|
||||
.lightbox-no-scrollbar::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* 스크롤바 숨기기 유틸리티 */
|
||||
.scrollbar-hide::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
.scrollbar-hide {
|
||||
-ms-overflow-style: none;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
/* Swiper autoHeight 지원 */
|
||||
.swiper-slide {
|
||||
height: auto !important;
|
||||
}
|
||||
23
frontend-temp/src/main.jsx
Normal file
23
frontend-temp/src/main.jsx
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import React from "react";
|
||||
import ReactDOM from "react-dom/client";
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import App from "./App";
|
||||
import "./index.css";
|
||||
|
||||
const queryClient = new QueryClient({
|
||||
defaultOptions: {
|
||||
queries: {
|
||||
staleTime: 1000 * 60 * 5, // 5분
|
||||
retry: 1,
|
||||
refetchOnWindowFocus: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
ReactDOM.createRoot(document.getElementById("root")).render(
|
||||
<React.StrictMode>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<App />
|
||||
</QueryClientProvider>
|
||||
</React.StrictMode>
|
||||
);
|
||||
0
frontend-temp/src/pages/mobile/.gitkeep
Normal file
0
frontend-temp/src/pages/mobile/.gitkeep
Normal file
0
frontend-temp/src/pages/pc/.gitkeep
Normal file
0
frontend-temp/src/pages/pc/.gitkeep
Normal file
0
frontend-temp/src/stores/.gitkeep
Normal file
0
frontend-temp/src/stores/.gitkeep
Normal file
0
frontend-temp/src/utils/.gitkeep
Normal file
0
frontend-temp/src/utils/.gitkeep
Normal file
21
frontend-temp/tailwind.config.js
Normal file
21
frontend-temp/tailwind.config.js
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
/** @type {import('tailwindcss').Config} */
|
||||
export default {
|
||||
content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
primary: {
|
||||
DEFAULT: "#548360",
|
||||
dark: "#456E50",
|
||||
light: "#6A9A75",
|
||||
},
|
||||
secondary: "#F5F5F5",
|
||||
accent: "#FFD700",
|
||||
},
|
||||
fontFamily: {
|
||||
sans: ["Pretendard", "Inter", "sans-serif"],
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
};
|
||||
27
frontend-temp/vite.config.js
Normal file
27
frontend-temp/vite.config.js
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import { defineConfig } from "vite";
|
||||
import react from "@vitejs/plugin-react";
|
||||
import path from "path";
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
resolve: {
|
||||
alias: {
|
||||
"@": path.resolve(__dirname, "./src"),
|
||||
},
|
||||
},
|
||||
server: {
|
||||
host: true,
|
||||
port: 80,
|
||||
allowedHosts: true,
|
||||
proxy: {
|
||||
"/api": {
|
||||
target: "http://fromis9-backend:80",
|
||||
changeOrigin: true,
|
||||
},
|
||||
"/docs": {
|
||||
target: "http://fromis9-backend:80",
|
||||
changeOrigin: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
Loading…
Add table
Reference in a new issue