diff --git a/React/package-lock.json b/React/package-lock.json
new file mode 100644
index 00000000..396cb730
--- /dev/null
+++ b/React/package-lock.json
@@ -0,0 +1,6 @@
+{
+ "name": "React",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {}
+}
diff --git a/React/panda-market/package-lock.json b/React/panda-market/package-lock.json
index 62ea306a..60b87fe5 100644
--- a/React/panda-market/package-lock.json
+++ b/React/panda-market/package-lock.json
@@ -19,7 +19,9 @@
},
"devDependencies": {
"ajv": "^7.2.4",
+ "axios": "^1.7.9",
"classnames": "^2.5.1",
+ "lodash.debounce": "^4.0.8",
"react-router-dom": "^6.28.1"
}
},
@@ -5151,6 +5153,34 @@
"node": ">=4"
}
},
+ "node_modules/axios": {
+ "version": "1.7.9",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz",
+ "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "follow-redirects": "^1.15.6",
+ "form-data": "^4.0.0",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
+ "node_modules/axios/node_modules/form-data": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
+ "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "es-set-tostringtag": "^2.1.0",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/axobject-query": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
@@ -14048,6 +14078,13 @@
"node": ">= 0.10"
}
},
+ "node_modules/proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/psl": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz",
diff --git a/React/panda-market/package.json b/React/panda-market/package.json
index 081c1958..295a893c 100644
--- a/React/panda-market/package.json
+++ b/React/panda-market/package.json
@@ -38,7 +38,9 @@
},
"devDependencies": {
"ajv": "^7.2.4",
+ "axios": "^1.7.9",
"classnames": "^2.5.1",
+ "lodash.debounce": "^4.0.8",
"react-router-dom": "^6.28.1"
}
}
diff --git a/React/panda-market/src/App.jsx b/React/panda-market/src/App.jsx
new file mode 100644
index 00000000..f8a23804
--- /dev/null
+++ b/React/panda-market/src/App.jsx
@@ -0,0 +1,26 @@
+import { Outlet, useLocation } from "react-router-dom";
+import Header from "./components/Layout/Header";
+import Footer from "./components/Layout/Footer";
+import styles from "./styles/App.module.css";
+import "./styles/App.font.css";
+import "./styles/App.color.css";
+
+function App() {
+ const location = useLocation();
+
+ return (
+ <>
+ {!["/signin", "/signup"].includes(location.pathname) && (
+
+ )}
+
+
+
+ {["/"].includes(location.pathname) && (
+
+ )}
+ >
+ );
+}
+
+export default App;
diff --git a/React/panda-market/src/Main.js b/React/panda-market/src/Main.js
index 00d60b89..14225fa1 100644
--- a/React/panda-market/src/Main.js
+++ b/React/panda-market/src/Main.js
@@ -1,9 +1,11 @@
import { BrowserRouter, Routes, Route } from "react-router-dom";
-import App from "./components/App";
-import HomePage from "./pages/HomePage";
-import ItemPage from "./pages/ItemPage";
-import ItemListPage from "./pages/ItemListPage";
-import RegisterItemPage from "./pages/RegisterItemPage";
+import App from "./App";
+import HomePage from "./pages/HomePage/HomePage";
+import LoginPage from "./pages/LoginPage/LoginPage";
+import CommunityPage from "./pages/CommunityPage/CommunityPage";
+import MarketPage from "./pages/MarketPage/MarketPage";
+import ItemPage from "./pages/ItemPage/ItemPage";
+import RegisterItemPage from "./pages/RegisterItemPage/RegisterItemPage";
function Main() {
return (
@@ -11,8 +13,10 @@ function Main() {
}>
} />
+ } />
+ } />
- } />
+ } />
} />
} />
diff --git a/React/panda-market/src/api.js b/React/panda-market/src/api.js
deleted file mode 100644
index 1394ab07..00000000
--- a/React/panda-market/src/api.js
+++ /dev/null
@@ -1,11 +0,0 @@
-const BASE_URL = "https://panda-market-api.vercel.app";
-
-export async function getItems({ page = "", pageSize = "", order = "" }) {
- const query = `page=${page}&pageSize=${pageSize}&orderBy=${order}`;
- const response = await fetch(`${BASE_URL}/products?${query}`);
- if (!response.ok) {
- throw new Error("데이터를 불러오는데 실패했습니다");
- }
- const body = await response.json();
- return body;
-}
diff --git a/React/panda-market/src/apis/itemApi.js b/React/panda-market/src/apis/itemApi.js
new file mode 100644
index 00000000..51823bb7
--- /dev/null
+++ b/React/panda-market/src/apis/itemApi.js
@@ -0,0 +1,16 @@
+import axios from "axios";
+
+const instance = axios.create({
+ baseURL: "https://panda-market-api.vercel.app",
+});
+
+export async function getItems({ page = "", pageSize = "", order = "" }) {
+ const query = `page=${page}&pageSize=${pageSize}&orderBy=${order}`;
+ try {
+ const res = await instance.get(`/products?${query}`);
+ return res.data;
+ } catch (error) {
+ console.error(error);
+ throw error;
+ }
+}
diff --git a/React/panda-market/src/assets/icon/ic_arrow_down.svg b/React/panda-market/src/assets/icon/ic_arrow_down.svg
new file mode 100644
index 00000000..b423610b
--- /dev/null
+++ b/React/panda-market/src/assets/icon/ic_arrow_down.svg
@@ -0,0 +1,3 @@
+
diff --git a/React/panda-market/src/assets/icon/ic_delete.svg b/React/panda-market/src/assets/icon/ic_delete.svg
new file mode 100644
index 00000000..32ce78c3
--- /dev/null
+++ b/React/panda-market/src/assets/icon/ic_delete.svg
@@ -0,0 +1,4 @@
+
diff --git a/React/panda-market/src/assets/icon/ic_plus.svg b/React/panda-market/src/assets/icon/ic_plus.svg
new file mode 100644
index 00000000..5bb9abf5
--- /dev/null
+++ b/React/panda-market/src/assets/icon/ic_plus.svg
@@ -0,0 +1,4 @@
+
diff --git a/React/panda-market/src/assets/icon/ic_sort.svg b/React/panda-market/src/assets/icon/ic_sort.svg
new file mode 100644
index 00000000..657b44f9
--- /dev/null
+++ b/React/panda-market/src/assets/icon/ic_sort.svg
@@ -0,0 +1,6 @@
+
diff --git a/React/panda-market/src/components/AllItems.css b/React/panda-market/src/components/AllItems.css
deleted file mode 100644
index 6ecdf934..00000000
--- a/React/panda-market/src/components/AllItems.css
+++ /dev/null
@@ -1,90 +0,0 @@
-.top {
- display: flex;
- justify-content: space-between;
- align-items: center;
-}
-
-.title {
- font-weight: 700;
- font-size: 2rem;
- color: var(--gray900);
-}
-
-.menu {
- display: flex;
- gap: 1rem;
-}
-
-form {
- position: relative;
-}
-
-.searchBar {
- width: 32.5rem;
- height: 4.2rem;
- border: none;
- background-color: var(--gray100);
- padding: 0 5rem;
- border-radius: 1.2rem;
- font-size: 1.6rem;
-}
-
-.searchBar::placeholder {
- font-weight: 400;
- font-size: 1.6rem;
- color: var(--gray400);
-}
-
-.searchIcon {
- position: absolute;
- top: 1.4rem;
- left: 2rem;
-}
-
-.registerButton {
- padding: 1.2rem 2.3rem;
- border-radius: 0.8rem;
- font-weight: 600;
- font-size: 1.6rem;
-}
-
-.orderSelect {
- width: 13rem;
- padding: 1.2rem 2rem;
- border-radius: 1.2rem;
- border-color: var(--gray200);
- font-weight: 400;
- font-size: 1.6rem;
- color: var(--gray800);
-}
-
-.pageButtons {
- padding-left: 0;
- padding-top: 2rem;
- margin: 2rem 0;
- display: flex;
- justify-content: center;
- align-items: center;
- gap: 1rem;
- list-style: none;
-}
-
-.pageButton,
-.pageButton:hover,
-.pageButton:focus {
- width: 4rem;
- height: 4rem;
- border-radius: 4rem;
- font-weight: 600;
- font-size: 1.6rem;
- color: var(--gray500);
- background-color: #ffffff;
- border: 0.1rem solid var(--gray200);
-}
-
-/* Mobile */
-@media (min-width: 375px) and (max-width: 767px) {
- .menu {
- flex-wrap: wrap;
- }
-}
diff --git a/React/panda-market/src/components/AllItems.js b/React/panda-market/src/components/AllItems.js
deleted file mode 100644
index a2179dbb..00000000
--- a/React/panda-market/src/components/AllItems.js
+++ /dev/null
@@ -1,116 +0,0 @@
-import { Link } from "react-router-dom";
-import ItemList from "../components/ItemList";
-import "./AllItems.css";
-import SearchIcon from "../assets/icon/ic_search.svg";
-import BackIcon from "../assets/icon/ic_back.svg";
-import NextIcon from "../assets/icon/ic_next.svg";
-import { useEffect, useState } from "react";
-import { getItems } from "../api";
-
-function AllItems() {
- const [order, setOrder] = useState("recent");
- const [page, setPage] = useState(1);
- const [pageSize, setPageSize] = useState(10);
- const [pageBound, setPageBound] = useState(0);
- const [items, setItems] = useState([]);
- const pageArr = [1, 2, 3, 4, 5];
-
- // 아이템 불러오기
- const handleLoad = async (query) => {
- const { list } = await getItems(query);
- setItems(list);
- };
-
- useEffect(() => {
- handleLoad({ page, pageSize, order });
- }, [page, pageSize, order]);
-
- // 아이템 정렬
- const handleOrderChange = (event) => {
- setOrder(event.target.value);
- setPage(1);
- setPageBound(0);
- };
-
- // 페이지네이션
- const changePage = (e) => {
- setPage(e.target.value);
- };
-
- const plusPageBound = () => {
- setPageBound(pageBound + 1);
- setPage(1 + 5 * (pageBound + 1));
- };
-
- const minusPageBound = () => {
- pageBound < 1 ? setPageBound(0) : setPageBound(pageBound - 1);
- pageBound < 1
- ? setPage(1 + 5 * pageBound)
- : setPage(1 + 5 * (pageBound - 1));
- };
-
- // 반응형
- useEffect(() => {
- function handleResize() {
- const newPageSize = getPageSize(window.innerWidth);
- if (newPageSize !== pageSize) {
- setPageSize(newPageSize);
- }
- }
- window.addEventListener("resize", handleResize);
- return () => window.removeEventListener("resize", handleResize);
- }, [pageSize]);
-
- function getPageSize(width) {
- if (width > 1200) return 10; // PC
- else if (width > 768) return 6; // Tablet
- else return 4; // Mobile
- }
-
- return (
- <>
-
-
전체 상품
-
-
-
-
-
-
-
-
-
-
-
- {pageArr.map((num) => (
-
- ))}
-
-
- >
- );
-}
-
-export default AllItems;
diff --git a/React/panda-market/src/components/App.js b/React/panda-market/src/components/App.js
deleted file mode 100644
index 05c04ff7..00000000
--- a/React/panda-market/src/components/App.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import { Outlet } from "react-router-dom";
-import Nav from "./Nav";
-import Footer from "./Footer";
-import styles from "./App.module.css";
-import "./App.font.css";
-import "./App.color.css";
-
-function App() {
- return (
- <>
-
-
-
-
-
- >
- );
-}
-
-export default App;
diff --git a/React/panda-market/src/components/BestItems.css b/React/panda-market/src/components/BestItems.css
deleted file mode 100644
index 6af53e31..00000000
--- a/React/panda-market/src/components/BestItems.css
+++ /dev/null
@@ -1,11 +0,0 @@
-.top {
- display: flex;
- justify-content: space-between;
- align-items: center;
-}
-
-.title {
- font-weight: 700;
- font-size: 2rem;
- color: var(--gray900);
-}
diff --git a/React/panda-market/src/components/BestItems.js b/React/panda-market/src/components/BestItems.js
deleted file mode 100644
index 5e51895c..00000000
--- a/React/panda-market/src/components/BestItems.js
+++ /dev/null
@@ -1,46 +0,0 @@
-import ItemList from "../components/ItemList";
-import "./BestItems.css";
-import { useEffect, useState } from "react";
-import { getItems } from "../api";
-
-function BestItems() {
- const [items, setItems] = useState([]);
- const [pageSize, setPageSize] = useState(4);
-
- // 아이템 불러오기
- const handleLoad = async (query) => {
- const { list } = await getItems(query);
- setItems(list);
- };
-
- useEffect(() => {
- handleLoad({ page: 1, pageSize, order: "favorite" });
- }, [pageSize]);
-
- // 반응형
- useEffect(() => {
- function handleResize() {
- const newPageSize = getPageSize(window.innerWidth);
- if (newPageSize !== pageSize) {
- setPageSize(newPageSize);
- }
- }
- window.addEventListener("resize", handleResize);
- return () => window.removeEventListener("resize", handleResize);
- }, [pageSize]);
-
- function getPageSize(width) {
- if (width > 1200) return 4; // PC
- else if (width > 768) return 2; // Tablet
- else return 1; // Mobile
- }
-
- return (
- <>
- 베스트 상품
-
- >
- );
-}
-
-export default BestItems;
diff --git a/React/panda-market/src/components/Container.js b/React/panda-market/src/components/Container.js
deleted file mode 100644
index 1d7c581d..00000000
--- a/React/panda-market/src/components/Container.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import styles from "./Container.module.css";
-
-function Container({ children }) {
- return {children}
;
-}
-
-export default Container;
diff --git a/React/panda-market/src/components/ItemCard.js b/React/panda-market/src/components/ItemCard.js
deleted file mode 100644
index 57dec21c..00000000
--- a/React/panda-market/src/components/ItemCard.js
+++ /dev/null
@@ -1,28 +0,0 @@
-import heartIcon from "../assets/icon/ic_heart.svg";
-import "./ItemCard.css";
-
-function ItemCard({ item, best }) {
- const { images, name, price, favoriteCount } = item;
-
- const imgClassNames = `${best ? "bestImg" : ""} itemImg`;
-
- return (
- <>
-
-

-
-
-
- - {name}
- - {price}원
- -
-
- {favoriteCount}
-
-
-
- >
- );
-}
-
-export default ItemCard;
diff --git a/React/panda-market/src/components/ItemList.js b/React/panda-market/src/components/ItemList.js
deleted file mode 100644
index 806bc83d..00000000
--- a/React/panda-market/src/components/ItemList.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import "./ItemList.css";
-import ItemCard from "./ItemCard";
-import Container from "./Container";
-
-function ItemList({ items, best }) {
- const ClassNames = `${best ? "bestList" : ""} itemList`;
-
- return (
-
-
- {items.map((item) => (
- -
-
-
- ))}
-
-
- );
-}
-export default ItemList;
diff --git a/React/panda-market/src/components/Footer.js b/React/panda-market/src/components/Layout/Footer.jsx
similarity index 80%
rename from React/panda-market/src/components/Footer.js
rename to React/panda-market/src/components/Layout/Footer.jsx
index d578c1e4..f51736c0 100644
--- a/React/panda-market/src/components/Footer.js
+++ b/React/panda-market/src/components/Layout/Footer.jsx
@@ -1,10 +1,10 @@
// import facebookIcon from "../assets/facebook.svg";
-import styles from "./Footer.module.css";
-import facebookIcon from "../assets/icon/ic_facebook.svg";
-import twitterIcon from "../assets/icon/ic_twitter.svg";
-import youtubeIcon from "../assets/icon/ic_youtube.svg";
-import instagramIcon from "../assets/icon/ic_instagram.svg";
import { Link } from "react-router-dom";
+import facebookIcon from "../../assets/icon/ic_facebook.svg";
+import twitterIcon from "../../assets/icon/ic_twitter.svg";
+import youtubeIcon from "../../assets/icon/ic_youtube.svg";
+import instagramIcon from "../../assets/icon/ic_instagram.svg";
+import styles from "./Footer.module.css";
function Footer() {
return (
diff --git a/React/panda-market/src/components/Footer.module.css b/React/panda-market/src/components/Layout/Footer.module.css
similarity index 100%
rename from React/panda-market/src/components/Footer.module.css
rename to React/panda-market/src/components/Layout/Footer.module.css
diff --git a/React/panda-market/src/components/Layout/Header.jsx b/React/panda-market/src/components/Layout/Header.jsx
new file mode 100644
index 00000000..097d44e6
--- /dev/null
+++ b/React/panda-market/src/components/Layout/Header.jsx
@@ -0,0 +1,67 @@
+import { Link, NavLink, useLocation } from "react-router-dom";
+import useWindowSize from "../..//hooks/useWindowSize";
+import logoImg from "../../assets/logo/panda-market-logo.svg";
+import logoWordImg from "../../assets/logo/panda-market-logo-only-word.svg";
+import UserIcon from "../../assets/user/default-profile.png";
+import styles from "./Header.module.css";
+
+function Header() {
+ const { width } = useWindowSize();
+ const location = useLocation();
+
+ function communityLinkStyle({ isActive }) {
+ return {
+ color: isActive ? "var(--blue)" : "",
+ };
+ }
+
+ function marketLinkStyle({ isActive }) {
+ const isMarketRelatedPage = ["/items", "/additem"].includes(
+ location.pathname
+ );
+
+ return {
+ color: isActive || isMarketRelatedPage ? "var(--blue)" : "",
+ };
+ }
+
+ return (
+
+
+
+ {width >= 768 ? (
+

+ ) : (
+

+ )}
+
+ {!["/"].includes(location.pathname) && (
+
+ -
+
+ 자유게시판
+
+
+ -
+
+ 중고마켓
+
+
+
+ )}
+
+ {!["/"].includes(location.pathname) && (
+

+ )}
+ {["/"].includes(location.pathname) && (
+
+
+
+ )}
+
+ );
+}
+
+export default Header;
diff --git a/React/panda-market/src/components/Nav.module.css b/React/panda-market/src/components/Layout/Header.module.css
similarity index 77%
rename from React/panda-market/src/components/Nav.module.css
rename to React/panda-market/src/components/Layout/Header.module.css
index f6ead5c8..466650ba 100644
--- a/React/panda-market/src/components/Nav.module.css
+++ b/React/panda-market/src/components/Layout/Header.module.css
@@ -1,4 +1,4 @@
-.nav {
+.header {
width: 100%;
height: 7rem;
display: flex;
@@ -36,18 +36,26 @@ ul a:active {
.user {
width: 4rem;
+ cursor: pointer;
+}
+
+.loginButton {
+ font-size: 1.6rem;
+ font-weight: 600;
+ border-radius: 0.8rem;
+ padding: 1.2rem 2.3rem;
}
/* Tablet */
-@media (min-width: 768px) and (max-width: 1199px) {
- .nav {
+@media (max-width: 1199px) {
+ .header {
padding: 0.9rem 2.4rem;
}
}
/* Mobile */
-@media (min-width: 375px) and (max-width: 767px) {
- .nav {
+@media (max-width: 767px) {
+ .header {
padding: 0.9rem 1.6rem;
}
ul.menu {
diff --git a/React/panda-market/src/components/Nav.js b/React/panda-market/src/components/Nav.js
deleted file mode 100644
index 743e0250..00000000
--- a/React/panda-market/src/components/Nav.js
+++ /dev/null
@@ -1,37 +0,0 @@
-import { Link, NavLink } from "react-router-dom";
-import logoImg from "../assets/logo/panda-market-logo.svg";
-import UserIcon from "../assets/user/default-profile.png";
-import styles from "./Nav.module.css";
-
-function getLinkStyle({ isActive }) {
- return {
- color: isActive ? "var(--blue)" : "",
- };
-}
-
-function Nav() {
- return (
-
-
-
-

-
-
- -
-
- 자유게시판
-
-
- -
-
- 중고마켓
-
-
-
-
-

-
- );
-}
-
-export default Nav;
diff --git a/React/panda-market/src/hooks/useWindowSize.js b/React/panda-market/src/hooks/useWindowSize.js
new file mode 100644
index 00000000..e6d59042
--- /dev/null
+++ b/React/panda-market/src/hooks/useWindowSize.js
@@ -0,0 +1,27 @@
+import { useState, useEffect } from "react";
+import debounce from "lodash.debounce";
+
+function useWindowSize() {
+ const [windowSize, setWindowSize] = useState({
+ width: window.innerWidth,
+ height: window.innerHeight,
+ });
+
+ useEffect(() => {
+ const handleResize = debounce(() => {
+ setWindowSize({
+ width: window.innerWidth,
+ height: window.innerHeight,
+ });
+ }, 300);
+
+ window.addEventListener("resize", handleResize);
+ return () => {
+ window.removeEventListener("resize", handleResize);
+ };
+ }, []);
+
+ return windowSize;
+}
+
+export default useWindowSize;
diff --git a/React/panda-market/src/pages/CommunityPage/CommunityPage.jsx b/React/panda-market/src/pages/CommunityPage/CommunityPage.jsx
new file mode 100644
index 00000000..09faf486
--- /dev/null
+++ b/React/panda-market/src/pages/CommunityPage/CommunityPage.jsx
@@ -0,0 +1,7 @@
+import styles from "./CommunityPage.module.css";
+
+function CommunityPage() {
+ return <>>;
+}
+
+export default CommunityPage;
diff --git a/React/panda-market/src/pages/HomePage.module.css b/React/panda-market/src/pages/CommunityPage/CommunityPage.module.css
similarity index 100%
rename from React/panda-market/src/pages/HomePage.module.css
rename to React/panda-market/src/pages/CommunityPage/CommunityPage.module.css
diff --git a/React/panda-market/src/pages/HomePage.js b/React/panda-market/src/pages/HomePage/HomePage.jsx
similarity index 100%
rename from React/panda-market/src/pages/HomePage.js
rename to React/panda-market/src/pages/HomePage/HomePage.jsx
diff --git a/React/panda-market/src/pages/ItemPage.module.css b/React/panda-market/src/pages/HomePage/HomePage.module.css
similarity index 100%
rename from React/panda-market/src/pages/ItemPage.module.css
rename to React/panda-market/src/pages/HomePage/HomePage.module.css
diff --git a/React/panda-market/src/pages/ItemListPage.js b/React/panda-market/src/pages/ItemListPage.js
deleted file mode 100644
index 0422ea6a..00000000
--- a/React/panda-market/src/pages/ItemListPage.js
+++ /dev/null
@@ -1,19 +0,0 @@
-import Container from "../components/Container";
-import styles from "./ItemListPage.module.css";
-import AllItems from "../components/AllItems";
-import BestItems from "../components/BestItems";
-
-function ItemListPage() {
- return (
-
-
-
-
-
-
- );
-}
-
-export default ItemListPage;
diff --git a/React/panda-market/src/pages/ItemListPage.module.css b/React/panda-market/src/pages/ItemListPage.module.css
deleted file mode 100644
index 6903e36a..00000000
--- a/React/panda-market/src/pages/ItemListPage.module.css
+++ /dev/null
@@ -1,17 +0,0 @@
-.container {
- padding: 3rem 0;
-}
-
-/* Tablet */
-@media (min-width: 768px) and (max-width: 1199px) {
- .container {
- padding: 3rem 2.4rem;
- }
-}
-
-/* Mobile */
-@media (min-width: 375px) and (max-width: 767px) {
- .container {
- padding: 3rem 1.2rem;
- }
-}
diff --git a/React/panda-market/src/pages/ItemPage.js b/React/panda-market/src/pages/ItemPage/ItemPage.jsx
similarity index 100%
rename from React/panda-market/src/pages/ItemPage.js
rename to React/panda-market/src/pages/ItemPage/ItemPage.jsx
diff --git a/React/panda-market/src/pages/RegisterItemPage.module.css b/React/panda-market/src/pages/ItemPage/ItemPage.module.css
similarity index 100%
rename from React/panda-market/src/pages/RegisterItemPage.module.css
rename to React/panda-market/src/pages/ItemPage/ItemPage.module.css
diff --git a/React/panda-market/src/pages/LoginPage/LoginPage.jsx b/React/panda-market/src/pages/LoginPage/LoginPage.jsx
new file mode 100644
index 00000000..8073831a
--- /dev/null
+++ b/React/panda-market/src/pages/LoginPage/LoginPage.jsx
@@ -0,0 +1,7 @@
+import styles from "./LoginPage.module.css";
+
+function LoginPage() {
+ return <>>;
+}
+
+export default LoginPage;
diff --git a/React/panda-market/src/pages/LoginPage/LoginPage.module.css b/React/panda-market/src/pages/LoginPage/LoginPage.module.css
new file mode 100644
index 00000000..e69de29b
diff --git a/React/panda-market/src/pages/MarketPage/MarketPage.jsx b/React/panda-market/src/pages/MarketPage/MarketPage.jsx
new file mode 100644
index 00000000..dfa2afa2
--- /dev/null
+++ b/React/panda-market/src/pages/MarketPage/MarketPage.jsx
@@ -0,0 +1,14 @@
+import AllItemsSection from "./components/AllItemsSection";
+import BestItemsSection from "./components/BestItemsSection";
+import styles from "./MarketPage.module.css";
+
+function ItemListPage() {
+ return (
+
+ );
+}
+
+export default ItemListPage;
diff --git a/React/panda-market/src/components/Container.module.css b/React/panda-market/src/pages/MarketPage/MarketPage.module.css
similarity index 100%
rename from React/panda-market/src/components/Container.module.css
rename to React/panda-market/src/pages/MarketPage/MarketPage.module.css
diff --git a/React/panda-market/src/pages/MarketPage/components/AllItemsSection.jsx b/React/panda-market/src/pages/MarketPage/components/AllItemsSection.jsx
new file mode 100644
index 00000000..7627444d
--- /dev/null
+++ b/React/panda-market/src/pages/MarketPage/components/AllItemsSection.jsx
@@ -0,0 +1,179 @@
+import { Link } from "react-router-dom";
+import { useEffect, useState } from "react";
+import { getItems } from "../../../apis/itemApi";
+import useWindowSize from "../../../hooks/useWindowSize";
+import ItemCard from "./ItemCard";
+import SearchIcon from "../../../assets/icon/ic_search.svg";
+import DownIcon from "../../../assets/icon/ic_arrow_down.svg";
+import DropdownIcon from "../../../assets/icon/ic_sort.svg";
+import BackIcon from "../../../assets/icon/ic_back.svg";
+import NextIcon from "../../../assets/icon/ic_next.svg";
+import styles from "./AllItemsSection.module.css";
+
+function AllItems() {
+ const [order, setOrder] = useState("recent");
+ const [page, setPage] = useState(1);
+ const [pageSize, setPageSize] = useState(10);
+ const [isOpen, setIsOpen] = useState(false);
+ const [totalItemCount, setTotalItemCount] = useState(0);
+ const [pageBound, setPageBound] = useState(0);
+ const [items, setItems] = useState([]);
+ const MaxPageBound = Math.floor(totalItemCount / pageSize / 5);
+ const pageArr = [1, 2, 3, 4, 5];
+ const { width } = useWindowSize();
+
+ // 아이템 불러오기
+ const handleLoad = async (query) => {
+ try {
+ const { list, totalCount } = await getItems(query);
+ setItems(list);
+ setTotalItemCount(totalCount);
+ } catch (error) {
+ return;
+ }
+ };
+
+ useEffect(() => {
+ handleLoad({ page, pageSize, order });
+ }, [page, pageSize, order]);
+
+ // 아이템 정렬
+ const handleOrderChange = (event) => {
+ event.stopPropagation();
+ let selectedOrder = event.target.textContent;
+ if (selectedOrder === "최신순") {
+ setOrder("recent");
+ } else if (selectedOrder === "좋아요순") {
+ setOrder("favorite");
+ }
+ setPage(1);
+ setPageBound(0);
+ setIsOpen(false);
+ };
+
+ // 페이지네이션
+ const changePage = (e) => {
+ setPage(Number(e.target.value));
+ };
+
+ const plusPageBound = () => {
+ setPageBound(pageBound + 1);
+ setPage(1 + 5 * (pageBound + 1));
+ };
+
+ const minusPageBound = () => {
+ pageBound < 1 ? setPageBound(0) : setPageBound(pageBound - 1);
+ pageBound < 1
+ ? setPage(1 + 5 * pageBound)
+ : setPage(1 + 5 * (pageBound - 1));
+ };
+
+ // 반응형
+ useEffect(() => {
+ let newPageSize;
+
+ if (width > 1200) {
+ newPageSize = 10; // PC
+ } else if (width > 768) {
+ newPageSize = 6; // Tablet
+ } else {
+ newPageSize = 4; // Mobile
+ }
+
+ if (newPageSize !== pageSize) {
+ setPageSize(newPageSize);
+ }
+ }, [width, pageSize]);
+
+ return (
+
+
+
전체 상품
+
+
+
+
+
+ {/* 아이템 정렬 드롭다운*/}
+
+
+
+ {/* 아이템 목록 */}
+
+ {items.map((item) => (
+ -
+
+
+ ))}
+
+ {/* 페이지네이션 */}
+
+
+ {pageArr.map((num) => (
+
+ ))}
+
+
+
+ );
+}
+
+export default AllItems;
diff --git a/React/panda-market/src/pages/MarketPage/components/AllItemsSection.module.css b/React/panda-market/src/pages/MarketPage/components/AllItemsSection.module.css
new file mode 100644
index 00000000..e458c892
--- /dev/null
+++ b/React/panda-market/src/pages/MarketPage/components/AllItemsSection.module.css
@@ -0,0 +1,173 @@
+.container {
+ padding: 3rem 0;
+}
+
+.top {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.title {
+ font-weight: 700;
+ font-size: 2rem;
+ color: var(--gray900);
+}
+
+.menu {
+ display: flex;
+ gap: 1rem;
+}
+
+form {
+ position: relative;
+}
+
+.searchBar {
+ width: 32.5rem;
+ height: 4.2rem;
+ border: none;
+ background-color: var(--gray100);
+ padding: 0 5rem;
+ border-radius: 1.2rem;
+ font-size: 1.6rem;
+}
+
+.searchBar::placeholder {
+ font-weight: 400;
+ font-size: 1.6rem;
+ color: var(--gray400);
+}
+
+.searchIcon {
+ position: absolute;
+ top: 1.4rem;
+ left: 2rem;
+}
+
+.registerButton {
+ padding: 1.2rem 2.3rem;
+ height: 4.2rem;
+ border-radius: 0.8rem;
+ font-weight: 600;
+ font-size: 1.6rem;
+}
+
+.orderSelect,
+.orderSelect:hover,
+.orderSelect:focus {
+ display: flex;
+ gap: 1.2rem;
+ padding-left: 1.2rem;
+ font-weight: 400;
+ font-size: 1.6rem;
+ color: var(--gray800);
+ position: relative;
+ height: 4.2rem;
+ width: 13rem;
+ background-color: #ffffff;
+ border-radius: 1.2rem;
+ border: 0.1rem solid var(--gray200);
+}
+
+.orderSelectList {
+ display: flex;
+ flex-direction: column;
+ position: absolute;
+ top: 5rem;
+ right: 0;
+ width: 13rem;
+ background-color: #ffffff;
+ border-radius: 1.2rem;
+ border: 0.1rem solid var(--gray200);
+}
+
+.orderSelectOption {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 4.2rem;
+}
+
+.orderSelectOption:first-child {
+ border-bottom: 0.1rem solid var(--gray200);
+}
+
+.itemList {
+ display: grid;
+ grid-template-columns: repeat(5, 1fr);
+ gap: 2rem;
+ padding-left: 0;
+ padding-top: 2rem;
+ margin: 0;
+ list-style: none;
+}
+
+.pageButtons {
+ padding-left: 0;
+ padding-top: 2rem;
+ margin: 2rem 0;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ gap: 1rem;
+ list-style: none;
+}
+
+.pageButton,
+.pageButton:hover,
+.pageButton:focus {
+ width: 4rem;
+ height: 4rem;
+ border-radius: 4rem;
+ font-weight: 600;
+ font-size: 1.6rem;
+ color: var(--gray500);
+ background-color: #ffffff;
+ border: 0.1rem solid var(--gray200);
+}
+
+.pageButton:disabled {
+ background-color: var(--gray200);
+}
+
+.activePage,
+.activePage:hover,
+.activePage:focus {
+ background-color: var(--blue);
+ color: #ffffff;
+}
+
+/* Tablet */
+@media (max-width: 1199px) {
+ .container {
+ padding: 3rem 2.4rem;
+ }
+
+ .itemList {
+ grid-template-columns: repeat(3, 1fr);
+ }
+}
+
+/* Mobile */
+@media (max-width: 767px) {
+ .container {
+ padding: 3rem 1.2rem;
+ }
+
+ .menu {
+ flex-wrap: wrap;
+ }
+
+ .itemList {
+ grid-template-columns: repeat(2, 1fr);
+ gap: 1.5rem;
+ }
+
+ .orderSelect,
+ .orderSelect:hover,
+ .orderSelect:focus {
+ width: 4.2rem;
+ height: 4.2rem;
+ }
+}
diff --git a/React/panda-market/src/pages/MarketPage/components/BestItemsSection.jsx b/React/panda-market/src/pages/MarketPage/components/BestItemsSection.jsx
new file mode 100644
index 00000000..0f91f0b4
--- /dev/null
+++ b/React/panda-market/src/pages/MarketPage/components/BestItemsSection.jsx
@@ -0,0 +1,53 @@
+import { useEffect, useState } from "react";
+import { getItems } from "../../../apis/itemApi";
+import useWindowSize from "../../../hooks/useWindowSize";
+import ItemCard from "./ItemCard";
+import styles from "./BestItemsSection.module.css";
+
+function BestItems() {
+ const [items, setItems] = useState([]);
+ const [pageSize, setPageSize] = useState(4);
+ const { width } = useWindowSize();
+
+ // 아이템 불러오기
+ const handleLoad = async (query) => {
+ const { list } = await getItems(query);
+ setItems(list);
+ };
+
+ useEffect(() => {
+ handleLoad({ page: 1, pageSize, order: "favorite" });
+ }, [pageSize]);
+
+ // 반응형
+ useEffect(() => {
+ let newPageSize;
+
+ if (width > 1200) {
+ newPageSize = 4; // PC
+ } else if (width > 768) {
+ newPageSize = 2; // Tablet
+ } else {
+ newPageSize = 1; // Mobile
+ }
+
+ if (newPageSize !== pageSize) {
+ setPageSize(newPageSize);
+ }
+ }, [width, pageSize]);
+
+ return (
+
+
베스트 상품
+
+ {items.map((item) => (
+ -
+
+
+ ))}
+
+
+ );
+}
+
+export default BestItems;
diff --git a/React/panda-market/src/components/ItemList.css b/React/panda-market/src/pages/MarketPage/components/BestItemsSection.module.css
similarity index 54%
rename from React/panda-market/src/components/ItemList.css
rename to React/panda-market/src/pages/MarketPage/components/BestItemsSection.module.css
index 7e1ee2df..7a4bf2bc 100644
--- a/React/panda-market/src/components/ItemList.css
+++ b/React/panda-market/src/pages/MarketPage/components/BestItemsSection.module.css
@@ -1,6 +1,16 @@
+.container {
+ padding: 3rem 0;
+}
+
+.title {
+ font-weight: 700;
+ font-size: 2rem;
+ color: var(--gray900);
+}
+
.itemList {
display: grid;
- grid-template-columns: repeat(5, 1fr);
+ grid-template-columns: repeat(4, 1fr);
gap: 2rem;
padding-left: 0;
padding-top: 2rem;
@@ -8,29 +18,24 @@
list-style: none;
}
-.bestList {
- grid-template-columns: repeat(4, 1fr);
-}
-
/* Tablet */
-@media (min-width: 768px) and (max-width: 1199px) {
- .itemList {
- grid-template-columns: repeat(3, 1fr);
+@media (max-width: 1199px) {
+ .container {
+ padding: 3rem 2.4rem;
}
- .bestList {
+ .itemList {
grid-template-columns: repeat(2, 1fr);
}
}
/* Mobile */
-@media (min-width: 375px) and (max-width: 767px) {
- .itemList {
- grid-template-columns: repeat(2, 1fr);
- gap: 1.5rem;
+@media (max-width: 767px) {
+ .container {
+ padding: 3rem 1.2rem;
}
- .bestList {
+ .itemList {
grid-template-columns: repeat(1, 1fr);
gap: 0.5rem;
}
diff --git a/React/panda-market/src/pages/MarketPage/components/ItemCard.jsx b/React/panda-market/src/pages/MarketPage/components/ItemCard.jsx
new file mode 100644
index 00000000..99eb3a00
--- /dev/null
+++ b/React/panda-market/src/pages/MarketPage/components/ItemCard.jsx
@@ -0,0 +1,26 @@
+import heartIcon from "../../../assets/icon/ic_heart.svg";
+import styles from "./ItemCard.module.css";
+
+function ItemCard({ item }) {
+ const { images, name, price, favoriteCount } = item;
+
+ return (
+ <>
+
+

+
+
+
+ - {name}
+ - {price}원
+ -
+
+ {favoriteCount}
+
+
+
+ >
+ );
+}
+
+export default ItemCard;
diff --git a/React/panda-market/src/components/ItemCard.css b/React/panda-market/src/pages/MarketPage/components/ItemCard.module.css
similarity index 54%
rename from React/panda-market/src/components/ItemCard.css
rename to React/panda-market/src/pages/MarketPage/components/ItemCard.module.css
index 7950c3be..e2c663fb 100644
--- a/React/panda-market/src/components/ItemCard.css
+++ b/React/panda-market/src/pages/MarketPage/components/ItemCard.module.css
@@ -1,19 +1,11 @@
-.imgContainer {
-}
-
.itemImg {
- width: 22.1rem;
- height: 22.1rem;
+ width: 100%;
border-radius: 1.6rem;
+ aspect-ratio: 1 / 1;
object-fit: cover;
margin-bottom: 2rem;
}
-.bestImg {
- width: 28.2rem;
- height: 28.2rem;
-}
-
.itemInfo {
display: flex;
flex-direction: column;
@@ -43,24 +35,3 @@
font-size: 1.2rem;
color: var(--gray600);
}
-
-/* Tablet */
-@media (min-width: 768px) and (max-width: 1199px) {
- .bestImg {
- width: 34.3rem;
- height: 34.3rem;
- }
-}
-
-/* Mobile */
-@media (min-width: 375px) and (max-width: 767px) {
- .itemImg {
- width: 16.8rem;
- height: 16.8rem;
- }
-
- .bestImg {
- width: 34.3rem;
- height: 34.3rem;
- }
-}
diff --git a/React/panda-market/src/pages/RegisterItemPage.js b/React/panda-market/src/pages/RegisterItemPage.js
deleted file mode 100644
index 6a3ff9d3..00000000
--- a/React/panda-market/src/pages/RegisterItemPage.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import styles from "./RegisterItemPage.module.css";
-
-function RegisterItemPage() {
- return <>>;
-}
-
-export default RegisterItemPage;
diff --git a/React/panda-market/src/pages/RegisterItemPage/RegisterItemPage.jsx b/React/panda-market/src/pages/RegisterItemPage/RegisterItemPage.jsx
new file mode 100644
index 00000000..f6d07952
--- /dev/null
+++ b/React/panda-market/src/pages/RegisterItemPage/RegisterItemPage.jsx
@@ -0,0 +1,195 @@
+import { useState, useEffect, useRef } from "react";
+import PrusIcon from "../../assets/icon/ic_plus.svg";
+import DeleteIcon from "../../assets/icon/ic_delete.svg";
+import styles from "./RegisterItemPage.module.css";
+
+function RegisterItemPage() {
+ const [registerAvailable, setRegisterAvailable] = useState(false);
+ const [formData, setFormData] = useState({
+ name: "",
+ description: "",
+ price: "",
+ tag: "",
+ });
+ const [tagValues, setTagValues] = useState([]);
+ const [itemImg, setItemImg] = useState(null);
+ const [fileError, setFileError] = useState("");
+ const fileInputRef = useRef(null);
+
+ const handleRegister = async (event) => {
+ event.preventDefault();
+ };
+
+ const handleFileButtonClick = () => {
+ if (!fileInputRef.current) return;
+ fileInputRef.current.click();
+ };
+
+ const handleFileChange = (event) => {
+ const files = event.target.files;
+
+ if (!files) {
+ return;
+ }
+
+ if (files.length > 1) {
+ setFileError("*이미지 등록은 최대 1개까지 가능합니다.");
+ return;
+ }
+
+ setFileError("");
+ setItemImg(URL.createObjectURL(files[0]));
+ };
+
+ const handleDeleteFile = () => {
+ setItemImg(null);
+ setFileError("");
+ fileInputRef.current.value = "";
+ };
+
+ const handleChange = (event) => {
+ const { id, value } = event.target;
+ setFormData((prev) => ({
+ ...prev,
+ [id]: value,
+ }));
+ };
+
+ const handleAddTag = (event) => {
+ if (event.key === "Enter" && formData.tag !== "") {
+ setTagValues((prev) => [...prev, formData.tag]);
+ setFormData((prev) => ({
+ ...prev,
+ tag: "",
+ }));
+ }
+ };
+
+ const handleDeleteTag = (index) => {
+ setTagValues((prev) => prev.filter((_, i) => i !== index));
+ };
+
+ useEffect(() => {
+ const { name, description, price } = formData;
+ if (name && description && price && tagValues.length !== 0) {
+ setRegisterAvailable(true);
+ } else {
+ setRegisterAvailable(false);
+ }
+ }, [formData, tagValues]);
+
+ return (
+
+ );
+}
+
+export default RegisterItemPage;
diff --git a/React/panda-market/src/pages/RegisterItemPage/RegisterItemPage.module.css b/React/panda-market/src/pages/RegisterItemPage/RegisterItemPage.module.css
new file mode 100644
index 00000000..cbc37edf
--- /dev/null
+++ b/React/panda-market/src/pages/RegisterItemPage/RegisterItemPage.module.css
@@ -0,0 +1,213 @@
+.container {
+ display: flex;
+ flex-direction: column;
+ gap: 2.4rem;
+ max-width: 120rem;
+ margin: 0 auto;
+ padding: 2.4rem 0;
+ width: 100%;
+}
+
+.topSection {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+h1.title {
+ margin: 0;
+ font-weight: 700;
+ font-size: 2rem;
+ color: var(--gray800);
+}
+
+.registerButton {
+ width: 7.4rem;
+ height: 4.2rem;
+ border-radius: 0.8rem;
+ font-weight: 600;
+ font-size: 1.6rem;
+}
+
+.itemFormSection {
+ display: flex;
+ flex-direction: column;
+ gap: 3.2rem;
+}
+
+.infoInputSection {
+ display: flex;
+ flex-direction: column;
+ gap: 1.6rem;
+}
+
+h2.title {
+ margin: 0;
+ font-weight: 700;
+ font-size: 1.8rem;
+ color: var(--gray800);
+}
+
+.imgSectionContainer {
+ display: flex;
+ gap: 2.4rem;
+}
+
+.imgAddButton,
+.imgAddButton:hover,
+.imgAddButton:focus,
+.imgAddButton:disabled {
+ width: 28.2rem;
+ height: 28.2rem;
+ border-radius: 1.2rem;
+ background-color: var(--gray100);
+}
+
+.imgAddButtonContent {
+ display: flex;
+ flex-direction: column;
+ gap: 1.2rem;
+}
+
+.imgAddButtonText {
+ font-weight: 400;
+ font-size: 1.6rem;
+ color: var(--gray400);
+}
+
+.imgPreview {
+ position: relative;
+ width: 28.2rem;
+ height: 28.2rem;
+}
+
+.imgPreview > img {
+ width: 100%;
+ border-radius: 1.2rem;
+ aspect-ratio: 1 / 1;
+ object-fit: cover;
+}
+
+.imgPreview > button {
+ all: unset;
+ cursor: pointer;
+ position: absolute;
+ top: 1.2rem;
+ right: 1.2rem;
+}
+
+.errorMessage {
+ font-weight: 400;
+ font-size: 1.6rem;
+ color: var(--red);
+}
+
+input,
+input:focus {
+ height: 5.6rem;
+ padding: 1.6rem 2.4rem;
+ border-radius: 1.2rem;
+ border: none;
+ background-color: var(--gray100);
+ font-weight: 400;
+ font-size: 1.6rem;
+ line-height: 2.6rem;
+ outline: none;
+}
+
+textarea,
+textarea:focus {
+ height: 28.2rem;
+ padding: 1.6rem 2.4rem;
+ border-radius: 1.2rem;
+ border: none;
+ background-color: var(--gray100);
+ font-weight: 400;
+ font-size: 1.6rem;
+ line-height: 2.6rem;
+ resize: none;
+ outline: none;
+}
+
+input::placeholder,
+textarea::placeholder {
+ font-weight: 400;
+ font-size: 1.6rem;
+ color: var(--gray400);
+}
+
+.tags {
+ display: flex;
+ gap: 1.2rem;
+ overflow-x: auto;
+ white-space: nowrap;
+}
+
+.tags::-webkit-scrollbar {
+ display: none;
+}
+
+.tag {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.8rem;
+ padding: 0.6rem 1.2rem;
+ border-radius: 2.6rem;
+ background-color: var(--gray100);
+ font-weight: 400;
+ font-size: 1.6rem;
+ color: var(--gray800);
+}
+
+.deleteButton {
+ padding: 0.5rem;
+ border-radius: 100%;
+ background-color: var(--gray400);
+}
+
+.tag > button {
+ all: unset;
+ cursor: pointer;
+}
+
+/* Tablet */
+@media (max-width: 1199px) {
+ .container {
+ padding: 1.6rem 2.4rem;
+ }
+
+ .imgSectionContainer {
+ gap: 1rem;
+ }
+
+ .imgAddButton {
+ width: 16.8rem;
+ height: 16.8rem;
+ }
+
+ .imgPreview {
+ width: 16.8rem;
+ height: 16.8rem;
+ }
+}
+
+/* Mobile */
+@media (max-width: 767px) {
+ .container {
+ padding: 2.4rem 1.5rem;
+ }
+
+ .imgSectionContainer {
+ gap: 1rem;
+ }
+
+ .imgAddButton {
+ width: 16.8rem;
+ height: 16.8rem;
+ }
+
+ .imgPreview {
+ width: 16.8rem;
+ height: 16.8rem;
+ }
+}
diff --git a/React/panda-market/src/components/App.color.css b/React/panda-market/src/styles/App.color.css
similarity index 100%
rename from React/panda-market/src/components/App.color.css
rename to React/panda-market/src/styles/App.color.css
diff --git a/React/panda-market/src/components/App.font.css b/React/panda-market/src/styles/App.font.css
similarity index 71%
rename from React/panda-market/src/components/App.font.css
rename to React/panda-market/src/styles/App.font.css
index c61f27df..f16ee090 100644
--- a/React/panda-market/src/components/App.font.css
+++ b/React/panda-market/src/styles/App.font.css
@@ -6,3 +6,11 @@ html {
word-break: keep-all;
font-size: 62.5%; /* 16px * 62.5% = 10px = 1rem */
}
+
+input {
+ font-family: Pretendard, sans-serif;
+}
+
+textarea {
+ font-family: Pretendard, sans-serif;
+}
diff --git a/React/panda-market/src/components/App.module.css b/React/panda-market/src/styles/App.module.css
similarity index 100%
rename from React/panda-market/src/components/App.module.css
rename to React/panda-market/src/styles/App.module.css