diff --git a/backend/server.js b/backend/server.js
new file mode 100644
index 0000000..18a5018
--- /dev/null
+++ b/backend/server.js
@@ -0,0 +1,29 @@
+import express from "express";
+import path from "path";
+import { fileURLToPath } from "url";
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+
+const app = express();
+const PORT = process.env.PORT || 80;
+
+// JSON 파싱
+app.use(express.json());
+
+// 정적 파일 서빙 (프론트엔드 빌드 결과물)
+app.use(express.static(path.join(__dirname, "dist")));
+
+// API 라우트 (추후 구현)
+app.get("/api/health", (req, res) => {
+ res.json({ status: "ok", timestamp: new Date().toISOString() });
+});
+
+// SPA 폴백 - 모든 요청을 index.html로
+app.get("*", (req, res) => {
+ res.sendFile(path.join(__dirname, "dist", "index.html"));
+});
+
+app.listen(PORT, () => {
+ console.log(`🌸 fromis_9 서버가 포트 ${PORT}에서 실행 중입니다`);
+});
diff --git a/frontend/index.html b/frontend/index.html
new file mode 100644
index 0000000..cac28aa
--- /dev/null
+++ b/frontend/index.html
@@ -0,0 +1,18 @@
+
+
+
+
+
+ fromis_9 - 프로미스나인
+
+
+
+
+
+
+
+
+
diff --git a/frontend/postcss.config.js b/frontend/postcss.config.js
new file mode 100644
index 0000000..2aa7205
--- /dev/null
+++ b/frontend/postcss.config.js
@@ -0,0 +1,6 @@
+export default {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+};
diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx
new file mode 100644
index 0000000..580b84f
--- /dev/null
+++ b/frontend/src/App.jsx
@@ -0,0 +1,39 @@
+import { BrowserRouter, Routes, Route } from 'react-router-dom';
+import { BrowserView, MobileView } from 'react-device-detect';
+
+// PC 페이지
+import PCHome from './pages/pc/Home';
+import PCMembers from './pages/pc/Members';
+import PCDiscography from './pages/pc/Discography';
+import PCSchedule from './pages/pc/Schedule';
+
+// PC 레이아웃
+import PCLayout from './components/pc/Layout';
+
+function App() {
+ return (
+
+
+
+
+ } />
+ } />
+ } />
+ } />
+
+
+
+
+ {/* 모바일 버전은 추후 구현 */}
+
+
+
fromis_9
+
모바일 버전은 준비 중입니다.
+
+
+
+
+ );
+}
+
+export default App;
diff --git a/frontend/src/components/pc/Footer.jsx b/frontend/src/components/pc/Footer.jsx
new file mode 100644
index 0000000..63c6dd7
--- /dev/null
+++ b/frontend/src/components/pc/Footer.jsx
@@ -0,0 +1,72 @@
+import { Instagram, Youtube, Twitter } from 'lucide-react';
+import { socialLinks } from '../../data/dummy';
+
+function Footer() {
+ return (
+
+ );
+}
+
+export default Footer;
diff --git a/frontend/src/components/pc/Header.jsx b/frontend/src/components/pc/Header.jsx
new file mode 100644
index 0000000..8857fd8
--- /dev/null
+++ b/frontend/src/components/pc/Header.jsx
@@ -0,0 +1,72 @@
+import { NavLink } from 'react-router-dom';
+import { Instagram, Youtube, Twitter } from 'lucide-react';
+import { socialLinks } from '../../data/dummy';
+
+function Header() {
+ const navItems = [
+ { path: '/', label: '홈' },
+ { path: '/members', label: '멤버' },
+ { path: '/discography', label: '디스코그래피' },
+ { path: '/schedule', label: '스케줄' },
+ ];
+
+ return (
+
+
+
+ {/* 로고 */}
+
+ fromis_9
+
+
+ {/* 네비게이션 */}
+
+
+ {/* SNS 링크 */}
+
+
+
+
+ );
+}
+
+export default Header;
diff --git a/frontend/src/components/pc/Layout.jsx b/frontend/src/components/pc/Layout.jsx
new file mode 100644
index 0000000..3ad6eda
--- /dev/null
+++ b/frontend/src/components/pc/Layout.jsx
@@ -0,0 +1,14 @@
+import Header from './Header';
+import Footer from './Footer';
+
+function Layout({ children }) {
+ return (
+
+
+ {children}
+
+
+ );
+}
+
+export default Layout;
diff --git a/frontend/src/data/dummy.js b/frontend/src/data/dummy.js
new file mode 100644
index 0000000..79b6aae
--- /dev/null
+++ b/frontend/src/data/dummy.js
@@ -0,0 +1,125 @@
+// 더미 멤버 데이터
+export const members = [
+ {
+ id: 1,
+ name: "송하영",
+ birthDate: "1997.03.25",
+ position: "리더, 메인보컬, 메인댄서",
+ imageUrl:
+ "https://i.namu.wiki/i/M9XsM0yLkPOEwQJBAnVn2rMqo4kXRfv-AkvWNvgAX1m2IUWX1IECPIZ1sqH6tDMAmpqYQefaP1ydJz7hUZ6Zxw.webp",
+ instagram: "https://www.instagram.com/hayoung_0325/",
+ },
+ {
+ id: 2,
+ name: "박지원",
+ birthDate: "1998.10.20",
+ position: "메인보컬",
+ imageUrl:
+ "https://i.namu.wiki/i/M9XsM0yLkPOEwQJBAnVn2rMqo4kXRfv-AkvWNvgAX1lE7WfQKMuTmQCCJcXhPLv65cQCTMHWFhzhjJZIEbAKbQ.webp",
+ instagram: "https://www.instagram.com/jiwon_1020/",
+ },
+ {
+ id: 3,
+ name: "이채영",
+ birthDate: "2000.06.14",
+ position: "래퍼",
+ imageUrl:
+ "https://i.namu.wiki/i/M9XsM0yLkPOEwQJBAnVn2rMqo4kXRfv-AkvWNvgAX1lqvGHXpz1iuLHTnVmAEdbgahPaQEZA7VOxLLdB-pK_hQ.webp",
+ instagram: "https://www.instagram.com/chaeyoung_0614/",
+ },
+ {
+ id: 4,
+ name: "이나경",
+ birthDate: "2000.05.01",
+ position: "리드보컬",
+ imageUrl:
+ "https://i.namu.wiki/i/M9XsM0yLkPOEwQJBAnVn2rMqo4kXRfv-AkvWNvgAX1kGZHhKV9nNDi9mSwBCKKl5QGcHNT8_EZxLKSv6QmtVmg.webp",
+ instagram: "https://www.instagram.com/nakyung_0501/",
+ },
+ {
+ id: 5,
+ name: "백지헌",
+ birthDate: "2003.04.17",
+ position: "막내",
+ imageUrl:
+ "https://i.namu.wiki/i/M9XsM0yLkPOEwQJBAnVn2rMqo4kXRfv-AkvWNvgAX1n2pqk4sWJWC_FGvQpEmLxSJC1tuhIwq8cWnqt-HMv_gw.webp",
+ instagram: "https://www.instagram.com/jiheon_0417/",
+ },
+];
+
+// 더미 앨범 데이터
+export const albums = [
+ {
+ id: 1,
+ title: "Unlock My World",
+ albumType: "정규",
+ releaseDate: "2023.06.05",
+ titleTrack: "Unlock My World",
+ coverUrl:
+ "https://i.namu.wiki/i/KDu-5K16r75g3eCGiYiOqRBNJLKfmimubzXR1bSY2C39dxGbAG1nZqKYn_uqxjShKmN0HRjqJjM1DQfbHwXhsQ.webp",
+ },
+ {
+ id: 2,
+ title: "from our Memento Box",
+ albumType: "미니",
+ releaseDate: "2022.06.27",
+ titleTrack: "Stay This Way",
+ coverUrl:
+ "https://i.namu.wiki/i/RJ-v7VHvnbV2-M7S1YBn35LLQ1PV4rrLM-QE5qE0-C_p5xYx6vb0fB0O5oXPZsMo0kOWPLyE_45Cpt1kkQa5xg.webp",
+ },
+ {
+ id: 3,
+ title: "Midnight Guest",
+ albumType: "미니",
+ releaseDate: "2022.01.17",
+ titleTrack: "DM",
+ coverUrl:
+ "https://i.namu.wiki/i/yPAOeX6xBp_Bxs0wNLX-4IWLvqoTJoiZPAcDFdFHiUXTM3YLKtfSbEOqr3ofAZGdPNnBxNBKXQ0bZKBJjWG1hg.webp",
+ },
+ {
+ id: 4,
+ title: "Talk & Talk",
+ albumType: "싱글",
+ releaseDate: "2024.09.05",
+ titleTrack: "Supersonic",
+ coverUrl:
+ "https://i.namu.wiki/i/jYC5xE6SyC-eDlQWMHrx2OIKHKkJGkgj-_zCeMIgw8CbvU-d6c5kGE4Zy3cwkiZ7kpRG5Hmo5WfCN0uqUWpyiw.webp",
+ },
+];
+
+// 더미 스케줄 데이터
+export const schedules = [
+ {
+ id: 1,
+ date: "2025-01-02",
+ time: "19:00",
+ title: "유튜브 [스프 : 스튜디오 프로미스나인 30화]",
+ platform: "YouTube",
+ members: ["전원"],
+ },
+ {
+ id: 2,
+ date: "2025-01-05",
+ time: "18:00",
+ title: "SBS 인기가요 출연",
+ platform: "SBS",
+ members: ["전원"],
+ },
+ {
+ id: 3,
+ date: "2025-01-10",
+ time: "20:00",
+ title: '팬미팅 "FLOVER DAY"',
+ platform: "올림픽공원",
+ members: ["전원"],
+ },
+];
+
+// 공식 SNS 링크
+export const socialLinks = {
+ youtube: "https://www.youtube.com/c/officialfromis9",
+ instagram: "https://www.instagram.com/officialfromis9/",
+ twitter: "https://twitter.com/realfromis_9",
+ tiktok: "https://www.tiktok.com/@officialfromis_9",
+ fancafe: "https://cafe.daum.net/officialfromis9",
+};
diff --git a/frontend/src/index.css b/frontend/src/index.css
new file mode 100644
index 0000000..5fa87d9
--- /dev/null
+++ b/frontend/src/index.css
@@ -0,0 +1,28 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+/* 기본 스타일 */
+body {
+ font-family: "Noto Sans KR", sans-serif;
+ background-color: #fafafa;
+ color: #1a1a1a;
+}
+
+/* 스크롤바 스타일 */
+::-webkit-scrollbar {
+ width: 8px;
+}
+
+::-webkit-scrollbar-track {
+ background: #f1f1f1;
+}
+
+::-webkit-scrollbar-thumb {
+ background: #548360;
+ border-radius: 4px;
+}
+
+::-webkit-scrollbar-thumb:hover {
+ background: #456e50;
+}
diff --git a/frontend/src/main.jsx b/frontend/src/main.jsx
new file mode 100644
index 0000000..c57caa6
--- /dev/null
+++ b/frontend/src/main.jsx
@@ -0,0 +1,10 @@
+import React from 'react';
+import ReactDOM from 'react-dom/client';
+import App from './App';
+import './index.css';
+
+ReactDOM.createRoot(document.getElementById('root')).render(
+
+
+
+);
diff --git a/frontend/src/pages/pc/Discography.jsx b/frontend/src/pages/pc/Discography.jsx
new file mode 100644
index 0000000..0ef4276
--- /dev/null
+++ b/frontend/src/pages/pc/Discography.jsx
@@ -0,0 +1,104 @@
+import { motion } from 'framer-motion';
+import { Calendar, Music } from 'lucide-react';
+import { albums } from '../../data/dummy';
+
+function Discography() {
+ return (
+
+
+ {/* 헤더 */}
+
+
+ 디스코그래피
+
+
+ 프로미스나인의 음악을 만나보세요
+
+
+
+ {/* 앨범 그리드 */}
+
+ {albums.map((album, index) => (
+
+ {/* 앨범 커버 */}
+
+

+
+ {/* 앨범 타입 배지 */}
+
+ {album.albumType}
+
+
+ {/* 호버 오버레이 */}
+
+
+
+ {/* 앨범 정보 */}
+
+
{album.title}
+
+ {album.titleTrack}
+
+
+
+ {album.releaseDate}
+
+
+
+ ))}
+
+
+ {/* 통계 */}
+
+
+
+
+
+
+
+
+ );
+}
+
+export default Discography;
diff --git a/frontend/src/pages/pc/Home.jsx b/frontend/src/pages/pc/Home.jsx
new file mode 100644
index 0000000..229046f
--- /dev/null
+++ b/frontend/src/pages/pc/Home.jsx
@@ -0,0 +1,149 @@
+import { motion } from 'framer-motion';
+import { Link } from 'react-router-dom';
+import { Calendar, Users, Disc3, ArrowRight } from 'lucide-react';
+import { members, schedules, albums } from '../../data/dummy';
+
+function Home() {
+ return (
+
+ {/* 히어로 섹션 */}
+
+
+
+
+ fromis_9
+ 프로미스나인
+
+ 인사드리겠습니다. 둘, 셋!
+ 이제는 약속해 소중히 간직해,
+ 당신의 아이돌로 성장하겠습니다!
+
+
+ 멤버 보기
+
+
+
+
+
+ {/* 장식 */}
+
+
+
+ {/* 퀵 링크 섹션 */}
+
+
+
+
+
+
멤버
+
5명의 멤버를 만나보세요
+
+
+
+
디스코그래피
+
앨범과 음악을 확인하세요
+
+
+
+
스케줄
+
다가오는 일정을 확인하세요
+
+
+
+
+
+ {/* 멤버 미리보기 */}
+
+
+
+
+ {members.map((member, index) => (
+
+
+

+
+
+
{member.name}
+
{member.position.split(',')[0]}
+
+
+ ))}
+
+
+
+
+ {/* 스케줄 미리보기 */}
+
+
+
+
+ {schedules.slice(0, 3).map((schedule) => (
+
+
+
+ {schedule.date.split('-')[2]}
+
+
+ {schedule.date.split('-')[1]}월
+
+
+
+
{schedule.title}
+
{schedule.platform} · {schedule.time}
+
+
+ {schedule.members.join(', ')}
+
+
+ ))}
+
+
+
+
+ );
+}
+
+export default Home;
diff --git a/frontend/src/pages/pc/Members.jsx b/frontend/src/pages/pc/Members.jsx
new file mode 100644
index 0000000..f5862d0
--- /dev/null
+++ b/frontend/src/pages/pc/Members.jsx
@@ -0,0 +1,108 @@
+import { motion } from 'framer-motion';
+import { Instagram, Calendar } from 'lucide-react';
+import { members } from '../../data/dummy';
+
+function Members() {
+ return (
+
+
+ {/* 헤더 */}
+
+
+ 멤버
+
+
+ 프로미스나인의 5명의 멤버를 소개합니다
+
+
+
+ {/* 멤버 그리드 */}
+
+ {members.map((member, index) => (
+
+
+ {/* 이미지 */}
+
+

+
+
+ {/* 정보 */}
+
+
{member.name}
+
{member.position}
+
+
+
+ {member.birthDate}
+
+
+ {/* 인스타그램 링크 */}
+
+
+ Instagram
+
+
+
+ {/* 호버 효과 - 컬러 바 */}
+
+
+
+ ))}
+
+
+ {/* 그룹 정보 */}
+
+
+
+
+
+ );
+}
+
+export default Members;
diff --git a/frontend/src/pages/pc/Schedule.jsx b/frontend/src/pages/pc/Schedule.jsx
new file mode 100644
index 0000000..77e22df
--- /dev/null
+++ b/frontend/src/pages/pc/Schedule.jsx
@@ -0,0 +1,126 @@
+import { motion } from 'framer-motion';
+import { Calendar, Clock, MapPin, Users } from 'lucide-react';
+import { schedules } from '../../data/dummy';
+
+function Schedule() {
+ // 스케줄을 날짜별로 그룹핑
+ const groupedSchedules = schedules.reduce((acc, schedule) => {
+ const date = schedule.date;
+ if (!acc[date]) {
+ acc[date] = [];
+ }
+ acc[date].push(schedule);
+ return acc;
+ }, {});
+
+ const formatDate = (dateStr) => {
+ const date = new Date(dateStr);
+ const days = ['일', '월', '화', '수', '목', '금', '토'];
+ return {
+ month: date.getMonth() + 1,
+ day: date.getDate(),
+ weekday: days[date.getDay()],
+ };
+ };
+
+ return (
+
+
+ {/* 헤더 */}
+
+
+ 스케줄
+
+
+ 프로미스나인의 다가오는 일정을 확인하세요
+
+
+
+ {/* 스케줄 타임라인 */}
+
+ {Object.entries(groupedSchedules).map(([date, daySchedules], groupIndex) => {
+ const formatted = formatDate(date);
+ return (
+
+ {/* 타임라인 라인 */}
+
+
+ {/* 날짜 원 */}
+
+
+ {formatted.month}월
+ {formatted.day}
+
+
{formatted.weekday}
+
+
+ {/* 스케줄 카드들 */}
+
+ {daySchedules.map((schedule, index) => (
+
+
{schedule.title}
+
+
+
+
+ {schedule.time}
+
+
+
+ {schedule.platform}
+
+
+
+ {schedule.members.join(', ')}
+
+
+
+ ))}
+
+
+ );
+ })}
+
+
+ {/* 빈 스케줄 메시지 (스케줄이 없을 때) */}
+ {Object.keys(groupedSchedules).length === 0 && (
+
+ )}
+
+ {/* 안내 */}
+
+ 스케줄은 DC Inside 갤러리에서 자동으로 수집됩니다.
+ 일정은 변경될 수 있으니 공식 채널을 확인해 주세요.
+
+
+
+ );
+}
+
+export default Schedule;
diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js
new file mode 100644
index 0000000..4a7b79b
--- /dev/null
+++ b/frontend/tailwind.config.js
@@ -0,0 +1,23 @@
+/** @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: ['"Noto Sans KR"', "sans-serif"],
+ },
+ },
+ },
+ plugins: [],
+};
diff --git a/frontend/vite.config.js b/frontend/vite.config.js
new file mode 100644
index 0000000..77a11e3
--- /dev/null
+++ b/frontend/vite.config.js
@@ -0,0 +1,10 @@
+import { defineConfig } from "vite";
+import react from "@vitejs/plugin-react";
+
+export default defineConfig({
+ plugins: [react()],
+ server: {
+ host: true,
+ port: 5173,
+ },
+});