- ํ๋ก์ ํธ ๊ฐ์
- ์ฃผ์ ๊ธฐ๋ฅ
- ๊ธฐ์ ์คํ
- ํ๋ก์ ํธ ๊ตฌ์กฐ
- ์ค์น ๋ฐ ์คํ
- ์ฌ์ฉ์ ์ญํ ๋ณ ๊ธฐ๋ฅ
- ์ฃผ์ ํ์ด์ง
- API ์ฐ๋
- ์ํ ๊ด๋ฆฌ
- ์ปดํฌ๋ํธ ๊ตฌ์กฐ
- ๊ฐ๋ฐ ๊ฐ์ด๋
- ๋ฐฐํฌ
KBE5 HomeAid Frontend๋ ์ ๋ฌธ ๋งค๋์ ๊ฐ ์ ๊ณตํ๋ ํ์ผ์ด ์๋น์ค ํ๋ซํผ์ ํ๋ก ํธ์๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋๋ค. ๊ณ ๊ฐ, ๋งค๋์ , ๊ด๋ฆฌ์๊ฐ ๊ฐ๊ฐ์ ์ญํ ์ ๋ง๋ ๊ธฐ๋ฅ์ ์ฌ์ฉํ ์ ์๋ ํตํฉ ํ๋ซํผ์ ๋๋ค.
- ๐ ํธ๋ฆฌํ ํ์ผ์ด ์๋น์ค: ์ฒญ์, ๋๋ด, ์์ด์ปจ ์ฒญ์ ๋ฑ ๋ค์ํ ์๋น์ค
- ๐ฅ ์ ๋ฌธ ๋งค๋์ ๋งค์นญ: ๊ฒ์ฆ๋ ๋งค๋์ ์์ ์์ ํ ๋งค์นญ
- ๐ณ ์์ ํ ๊ฒฐ์ ์์คํ : ๋ค์ํ ๊ฒฐ์ ์๋จ ์ง์
- ๐ฑ ๋ฐ์ํ ๋์์ธ: ๋ชจ๋ฐ์ผ ์ฐ์ ์ค๊ณ๋ก ๋ชจ๋ ๊ธฐ๊ธฐ์์ ์ต์ ํ
- ๋ค์ค ์ฌ์ฉ์ ์ญํ : ๊ณ ๊ฐ(CUSTOMER), ๋งค๋์ (MANAGER), ๊ด๋ฆฌ์(ADMIN)
- JWT ํ ํฐ ๊ธฐ๋ฐ ์ธ์ฆ: ์์ ํ ์ธ์ ๊ด๋ฆฌ
- OAuth ์์ ๋ก๊ทธ์ธ: ์นด์นด์ค, ๋ค์ด๋ฒ ๋ฑ ์ง์
- ๊ถํ๋ณ ๋ผ์ฐํธ ๋ณดํธ: ์ญํ ์ ๋ฐ๋ฅธ ํ์ด์ง ์ ๊ทผ ์ ์ด
- ์๋น์ค ์นดํ ๊ณ ๋ฆฌ ์ ํ: ์ฒญ์, ๋๋ด, ์์ด์ปจ ์ฒญ์ ๋ฑ
- ์์ธ ์ต์ ์ ํ: ์๋น์ค๋ณ ์ธ๋ถ ์ต์ ๋ฐ ์ถ๊ฐ ์๋น์ค
- ์ค์๊ฐ ๋งค๋์ ๋งค์นญ: ์์น ๊ธฐ๋ฐ ๋งค๋์ ์ถ์ฒ
- ๊ฒฐ์ ์์คํ : ์นด๋, ์นด์นด์คํ์ด, ๋ค์ด๋ฒํ์ด ๋ฑ
- ์๋น์ค ์ฒดํฌ์ธ: ํ์ฅ ๋์ฐฉ ๋ฐ ์๋น์ค ์์/์๋ฃ
- ๋งค์นญ ์์ฒญ ๊ด๋ฆฌ: ๊ณ ๊ฐ ์์ฒญ์ ๋ํ ์๋ต
- ์ ์ฐ ๊ด๋ฆฌ: ์๋น์ค ์๋ฃ ํ ์ ์ฐ ์ฒ๋ฆฌ
- ํ๋กํ ๊ด๋ฆฌ: ๊ฐ์ธ์ ๋ณด ๋ฐ ์๋น์ค ์ ๋ณด ๊ด๋ฆฌ
- ํต๊ณ ๋์๋ณด๋: ์ค์๊ฐ ์๋น์ค ํํฉ ๋ฐ ๋งค์ถ ํต๊ณ
- ๊ณ ๊ฐ ๊ด๋ฆฌ: ๊ณ ๊ฐ ๋ชฉ๋ก, ๊ฒฐ์ ๋ด์ญ, ๋ฌธ์ ๊ด๋ฆฌ
- ๋งค๋์ ๊ด๋ฆฌ: ๋งค๋์ ๋ชฉ๋ก, ์ ์ฐ ๊ด๋ฆฌ, ์น์ธ ์ฒ๋ฆฌ
- ์์ฝ ๊ด๋ฆฌ: ์ ์ฒด ์์ฝ ํํฉ ๋ฐ ๋งค์นญ ๊ด๋ฆฌ
- ๋ฆฌ๋ทฐ ๊ด๋ฆฌ: ๊ณ ๊ฐ ๋ฆฌ๋ทฐ ๊ด๋ฆฌ ๋ฐ ์๋ต
- ์ค์๊ฐ ์๋ฆผ: SSE(Server-Sent Events) ๊ธฐ๋ฐ ์ค์๊ฐ ์๋ฆผ
- ๋ฐ์ํ ๋์์ธ: ๋ชจ๋ฐ์ผ ์ฐ์ ์ค๊ณ
- ๋คํฌ๋ชจ๋ ์ง์: ํ ๋ง ํ ๊ธ ๊ธฐ๋ฅ
- ์ง๋ ์ฐ๋: Google Maps API ๊ธฐ๋ฐ ์์น ์๋น์ค
- React 19.1.0: ์ต์ React ๊ธฐ๋ฅ ํ์ฉ
- Vite 6.3.5: ๋น ๋ฅธ ๊ฐ๋ฐ ํ๊ฒฝ ๋ฐ ๋น๋ ๋๊ตฌ
- React Router DOM 7.6.0: ํด๋ผ์ด์ธํธ ์ฌ์ด๋ ๋ผ์ฐํ
- Tailwind CSS 4.1.8: ์ ํธ๋ฆฌํฐ ํผ์คํธ CSS ํ๋ ์์ํฌ
- Lucide React 0.511.0: ์์ด์ฝ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
- React DatePicker 8.4.0: ๋ ์ง ์ ํ ์ปดํฌ๋ํธ
- Zustand 5.0.5: ๊ฒฝ๋ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
- React Hooks: ํจ์ํ ์ปดํฌ๋ํธ ์ํ ๊ด๋ฆฌ
- Chart.js 4.5.0: ๋ฐ์ดํฐ ์๊ฐํ
- React Chart.js 2 5.3.0: React์ฉ Chart.js ๋ํผ
- @react-google-maps/api 2.20.6: Google Maps React ์ปดํฌ๋ํธ
- Axios 1.9.0: HTTP ํด๋ผ์ด์ธํธ
- clsx 2.1.1: ์กฐ๊ฑด๋ถ ํด๋์ค๋ช ์ ํธ๋ฆฌํฐ
- html2canvas 1.4.1: HTML์ ์ด๋ฏธ์ง๋ก ๋ณํ
- jspdf 3.0.1: PDF ์์ฑ
- TypeScript 5.8.3: ์ ์ ํ์ ๊ฒ์ฌ
- ESLint: ์ฝ๋ ํ์ง ๊ด๋ฆฌ
- Prettier 3.5.3: ์ฝ๋ ํฌ๋งทํ
- Node.js 18.0.0 ์ด์
- npm ๋๋ yarn
# ์ ์ฅ์ ํด๋ก
git clone https://github.com/Kernel360/KBE5_HomeAid_FE.git
# ํ๋ก์ ํธ ๋๋ ํ ๋ฆฌ ์ด๋
cd KBE5_HomeAid_FE
# ์์กด์ฑ ์ค์น
npm install
# ๋๋
yarn install
# ๊ฐ๋ฐ ์๋ฒ ์์
npm run dev
# ๋๋
yarn dev
# ํ๋ก๋์
๋น๋
npm run build
# ๋๋
yarn build
# ๋น๋ ๋ฏธ๋ฆฌ๋ณด๊ธฐ
npm run preview
# ๋๋
yarn preview
# ๋ฆฐํธ ๊ฒ์ฌ
npm run lint
# ๋๋
yarn lint
- ์๋น์ค ์์ฝ: ๋ค์ํ ํ์ผ์ด ์๋น์ค ์์ฝ
- ๊ฒฐ์ ๊ด๋ฆฌ: ์์ ํ ์จ๋ผ์ธ ๊ฒฐ์
- ์์ฝ ๊ด๋ฆฌ: ์์ฝ ๋ด์ญ ์กฐํ ๋ฐ ์ทจ์
- ๋ฆฌ๋ทฐ ์์ฑ: ์๋น์ค ํ๊ธฐ ๋ฐ ํ์
- ๋ฌธ์ ๊ด๋ฆฌ: 1:1 ๋ฌธ์ ์์ฑ ๋ฐ ์กฐํ
- ์ฃผ์ ๊ด๋ฆฌ: ์๋น์ค ์ฃผ์ ๋ฑ๋ก ๋ฐ ๊ด๋ฆฌ
- ๋งค์นญ ๊ด๋ฆฌ: ๊ณ ๊ฐ ์์ฒญ์ ๋ํ ์๋ต
- ์๋น์ค ์ฒดํฌ์ธ: ํ์ฅ ๋์ฐฉ ๋ฐ ์๋น์ค ์งํ
- ์ ์ฐ ๊ด๋ฆฌ: ์๋น์ค ์๋ฃ ํ ์ ์ฐ ์ฒ๋ฆฌ
- ํ๋กํ ๊ด๋ฆฌ: ๊ฐ์ธ์ ๋ณด ๋ฐ ์๋น์ค ์ ๋ณด ๊ด๋ฆฌ
- ๋ฌธ์ ๊ด๋ฆฌ: ๊ณ ๊ฐ ๋ฌธ์์ ๋ํ ์๋ต
- ๋์๋ณด๋: ์ค์๊ฐ ํต๊ณ ๋ฐ ํํฉ ๋ชจ๋ํฐ๋ง
- ๊ณ ๊ฐ ๊ด๋ฆฌ: ๊ณ ๊ฐ ๋ชฉ๋ก, ๊ฒฐ์ ๋ด์ญ ๊ด๋ฆฌ
- ๋งค๋์ ๊ด๋ฆฌ: ๋งค๋์ ์น์ธ, ์ ์ฐ ๊ด๋ฆฌ
- ์์ฝ ๊ด๋ฆฌ: ์ ์ฒด ์์ฝ ํํฉ ๋ฐ ๋งค์นญ ๊ด๋ฆฌ
- ํต๊ณ ๋ถ์: ๋งค์ถ, ์๋น์ค, ๊ณ ๊ฐ ํต๊ณ
- ๋ฆฌ๋ทฐ ๊ด๋ฆฌ: ๊ณ ๊ฐ ๋ฆฌ๋ทฐ ๊ด๋ฆฌ ๋ฐ ์๋ต
- ํํ์ด์ง: ์๋น์ค ์๊ฐ ๋ฐ ์ฃผ์ ๊ธฐ๋ฅ ์๋ด
- ์ด๋ฒคํธ ํ์ด์ง: ์งํ์ค์ธ ์ด๋ฒคํธ ๋ฐ ํ๋ก๋ชจ์
- ๊ณต์ง์ฌํญ: ์๋น์ค ๊ด๋ จ ๊ณต์ง ๋ฐ FAQ
- ๋ก๊ทธ์ธ: ์ผ๋ฐ ๋ก๊ทธ์ธ ๋ฐ ์์ ๋ก๊ทธ์ธ
- ํ์๊ฐ์ : ๊ณ ๊ฐ/๋งค๋์ ์ ํ ๋ฐ ๋จ๊ณ๋ณ ๊ฐ์
- OAuth ์ฝ๋ฐฑ: ์์ ๋ก๊ทธ์ธ ์ฒ๋ฆฌ
- ์๋น์ค ์ ํ: ์นดํ ๊ณ ๋ฆฌ๋ณ ์๋น์ค ์ ํ
- ์ต์ ์ ํ: ์๋น์ค๋ณ ์ธ๋ถ ์ต์ ์ ํ
- ์์ฝ ์ ๋ณด: ๋ ์ง, ์๊ฐ, ์ฃผ์ ์ ๋ ฅ
- ๊ฒฐ์ : ๋ค์ํ ๊ฒฐ์ ์๋จ ์ง์
- ํต๊ณ ๋์๋ณด๋: ์ค์๊ฐ ๋ฐ์ดํฐ ์๊ฐํ
- ๊ณ ๊ฐ ๊ด๋ฆฌ: ๊ณ ๊ฐ ๋ชฉ๋ก ๋ฐ ์์ธ ์ ๋ณด
- ๋งค๋์ ๊ด๋ฆฌ: ๋งค๋์ ์น์ธ ๋ฐ ์ ์ฐ
- ์์ฝ ๊ด๋ฆฌ: ์ ์ฒด ์์ฝ ํํฉ ๊ด๋ฆฌ
// src/api/config/api.js
import axios from 'axios';
const api = axios.create({
baseURL: process.env.VITE_API_BASE_URL,
timeout: 10000,
});
// ์์ฒญ ์ธํฐ์
ํฐ - JWT ํ ํฐ ์๋ ์ถ๊ฐ
api.interceptors.request.use((config) => {
const token = localStorage.getItem('accessToken');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
// ์๋ต ์ธํฐ์
ํฐ - ํ ํฐ ๋ง๋ฃ ์ฒ๋ฆฌ
api.interceptors.response.use(
(response) => response,
(error) => {
if (error.response?.status === 401) {
// ํ ํฐ ๋ง๋ฃ ์ ๋ก๊ทธ์ธ ํ์ด์ง๋ก ๋ฆฌ๋ค์ด๋ ํธ
window.location.href = '/auth/signin';
}
return Promise.reject(error);
}
);
- ์ธ์ฆ:
/auth/signin
,/auth/signup
,/auth/refresh
- ์๋น์ค:
/services
,/services/{id}/options
- ์์ฝ:
/reservations
,/reservations/{id}
- ๊ฒฐ์ :
/payments
,/payments/{id}
- ๋งค์นญ:
/matching
,/matching/{id}
- ๊ด๋ฆฌ์:
/admin/dashboard
,/admin/customers
,/admin/managers
// src/stores/authStore.js
import { create } from 'zustand';
export const useAuthStore = create((set, get) => ({
user: null,
accessToken: null,
refreshToken: null,
setUser: (user) => set({ user }),
setTokens: (accessToken, refreshToken) => set({ accessToken, refreshToken }),
logout: () => set({ user: null, accessToken: null, refreshToken: null }),
}));
- authStore: ์ฌ์ฉ์ ์ธ์ฆ ์ ๋ณด
- themeStore: ๋คํฌ๋ชจ๋/๋ผ์ดํธ๋ชจ๋ ์ค์
- reservationStore: ์์ฝ ๊ด๋ จ ์ํ
- matchingStore: ๋งค์นญ ๊ด๋ จ ์ํ
- alertStore: ์ค์๊ฐ ์๋ฆผ ์ํ
- Button: ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ๋ฒํผ ์ปดํฌ๋ํธ
- Modal: ๋ชจ๋ฌ ๋ค์ด์ผ๋ก๊ทธ ์ปดํฌ๋ํธ
- Header: ๋ค๋น๊ฒ์ด์ ํค๋
- Footer: ํ๋จ ๋ค๋น๊ฒ์ด์
- ThemeToggle: ํ ๋ง ์ ํ ํ ๊ธ
- ๊ด๋ฆฌ์: Dashboard, CustomerList, ManagerList ๋ฑ
- ์์ฝ: ServiceOption, ServiceRequest, Payment ๋ฑ
- ๋งค์นญ: MatchingList, MatchingDetail, ServiceCheckIn ๋ฑ
- ๋ฆฌ๋ทฐ: ReviewList, ReviewWrite, ReviewDetail ๋ฑ
- ESLint: ์ฝ๋ ํ์ง ๋ฐ ์ผ๊ด์ฑ ์ ์ง
- Prettier: ์ฝ๋ ํฌ๋งทํ ์๋ํ
- TypeScript: ์ ์ ํ์ ๊ฒ์ฌ
- features/: ๊ธฐ๋ฅ๋ณ ๋ชจ๋ํ
- components/: ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ์ปดํฌ๋ํธ
- pages/: ํ์ด์ง ์ปดํฌ๋ํธ
- services/: API ์๋น์ค
- utils/: ์ ํธ๋ฆฌํฐ ํจ์
- Zustand: ๊ฒฝ๋ ์ํ ๊ด๋ฆฌ
- React Hooks: ์ปดํฌ๋ํธ ์ํ
- Context API: ์ ์ญ ์ํ (ํ์์)
- ๊ณต๊ฐ ๋ผ์ฐํธ: ์ธ์ฆ ๋ถํ์
- ๋ณดํธ๋ ๋ผ์ฐํธ: ์ธ์ฆ ๋ฐ ๊ถํ ํ์
- ์ค์ฒฉ ๋ผ์ฐํธ: ๋ ์ด์์ ๊ณต์
# Vercel CLI ์ค์น
npm i -g vercel
# ๋ฐฐํฌ
vercel --prod
# .env.local
VITE_API_BASE_URL=https://api.example.com
VITE_GOOGLE_MAPS_API_KEY=your_google_maps_api_key
- ์ฝ๋ ์คํ๋ฆฌํ : ๋ผ์ฐํธ๋ณ ์ฒญํฌ ๋ถ๋ฆฌ
- ์ด๋ฏธ์ง ์ต์ ํ: WebP ํฌ๋งท ์ฌ์ฉ
- ๋ฒ๋ค ๋ถ์: ๋น๋ ํฌ๊ธฐ ์ต์ ํ
์์ฐ์ง (ํ์ฅ) | ๊น์ํ | ์์งํ | ๊ฐํฌ์ง |
---|---|---|---|
@SangWJDev | @soohoioa | @jhroom | @heeejinin |
- ํ๋ก์ ํธ ์ด์: GitHub Issues
- ๋ฌธ์์ฌํญ: ํ๋ก์ ํธ ๊ด๋ฆฌ์์๊ฒ ์ฐ๋ฝ
KBE5 HomeAid Frontend - ์ ๋ฌธ ๋งค๋์ ๊ฐ ์ ๊ณตํ๋ ํ์ผ์ด ์๋น์ค ํ๋ซํผ ๐ โจ