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
|
- app
|
||||||
restart: unless-stopped
|
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:
|
fromis9-backend:
|
||||||
build: ./backend
|
build: ./backend
|
||||||
container_name: fromis9-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