0. 프로젝트 소개
- 스포츠 용품을 판매하고 도전이라는 가치를 전달하는 온라인 커머스 플랫폼 나이키 모티브 코딩 프로젝트입니다. 나이키는 웹페이지에서 회원가입 시 얻을 수 있는 혜택을 강조하고 간편한 회원가입 절차를 통해 회원가입을 유도하고 있습니다. 이를 위해 배송이 중요한 사이트이나 회원가입시 주소를 입력받지 않고 결제 시 정확한 주소를 입력하게 합니다. 또한 주문 시에 회원인 경우 무료 배송임을 강조하여 회원이 얻을 수 있는 혜택을 강조합니다.
- 개발기간 : 2023.02.06 - 2023.02.17 (약 2주)
- frontend github : https://github.com/wecode-bootcamp-korea/42-1st-Naweki-frontend
- backend github : https://github.com/jayhanjaelee/42-1st-Naweki-backend/tree/docs/README.md
1. 전체 페이지 시연 영상
https://drive.google.com/file/d/1K7N8V5zpr32S3dHisy2GXMtWi-Bjva7e/view?usp=sharing
2. 맡은 부분과 실제 구현 모습
Nav
- 구현 기능 :
- 메뉴 상단에 회원일 시 '고객님 안녕하세요' 문구 노출되고, 비회원일 시 회원가입과 로그인으로 이동하도록 구현
- 메뉴 리스트에 mouse enter시 드롭다운 메뉴 노출되고 클릭 시 해당 메뉴로 이동 (new release 클릭 시 신상품 목록으로, men 클릭 시 남성 제품 목록으로 이동함)
- 드롭다운 메뉴까지 마우스가 움직여도 메뉴가 닫히지 않고, 드롭다운 메뉴의 뒷 배경은 어둡게 처리하여 드롭다운 메뉴를 강조함
- 검색창에 키워드 검색 시 해당하는 제품을 이미지와 함께 노출하여 사용자의 편의성을 높임
- 아이콘 클릭 시 각 메뉴로 이동하여 모든 페이지에서 페이지간 이동이 자유롭도록 구현
제품리스트 페이지
- 구현 기능 :
- 백엔드 서버에 저장된 상품 데이터 불러와서 출력
- 페이지 왼쪽 sidebar에서 lifestyle/jordan 등 해당 카테고리 클릭 시 해당하는 제품만 노출
- 왼쪽 sidebar에서 색깔과 성별의 경우 버튼을 통해 카테고리 접고 펴는 기능 구현
- 정렬기준 클릭 시 드롭다운 메뉴 보여줌
- 사용자가 한눈에 제품을 인식할 수 있도록 한 페이지에 제품 3개씩 보여주고 버튼 형식으로 페이지네이션 구현
결제 페이지
- 구현 기능 :
- 백엔드 서버에 저장된 장바구니 데이터 불러와서 출력
- input 창에 입력 후 버튼 클릭 시 입력된 데이터 불러오도록 구현
- 버튼 클릭 시 다음 절차 컴포넌트 보여주도록 구현
- 맨 마지막에 주문 완료 시 백엔드로 데이터 전송하도록 구현
3. 진행과정에서 blocker과 해결 방법
첫 번째 blocker : nav에서 메뉴 별 다른 드롭다운 메뉴 데이터 보여주기
blocker : new release에 해당하는 드롭다운 메뉴의 상수데이터와 men/women/kids에 해당하는 드롭다운 메뉴의 상수데이터가 달라 마우스가 움직이면 다른 데이터를 보여줘야 했습니다.
해결방법 : 처음에는 단순하게 mouse hover로 드롭다운 메뉴를 보여주도록 구현했습니다. 그러다보니, 마우스가 드롭다운 메뉴로 내려가면 드롭다운 창이 닫혀버렸습니다. 그래서 mouse enter라는 이벤트를 알게 되었고 이를 적용했습니다.
그리고 onMouseEnterList라는 함수를 만들 때 id를 parameter(매개변수)자리에 넣어줬으며, jsx <> 안에서 마우스 이벤트를 호출할 때 함수를 호출해주는 방식(() => onMouseEnterList(menu.id))으로 구현했습니다.
import React, { useState } from 'react';
import { Link } from 'react-router-dom';
import { MENU_DATA } from '../data/menuData';
import NewMenuBox from '../NewMenuBox/NewMenuBox';
import OtherMenuBox from '../OtherMenuBox/OtherMenuBox';
import './Menu.scss';
const Menu = () => {
const [isShown, setIsShown] = useState(false);
const [menuId, setMenuId] = useState(0);
const onMouseEnter = () => setIsShown(true);
const onMouseLeave = () => setIsShown(false);
// id를 parameter 자리에 넣어줍니다
const onMouseEnterList = id => setMenuId(id);
return (
<div className="menu">
<ul className="menuLists" onMouseEnter={onMouseEnter}>
{MENU_DATA.map(menu => {
return (
<Link className="toProductList" key={menu.id} to="/products">
<li
className="menuList"
// onmouseenter 시 함수를 호출해줍니다
onMouseEnter={() => onMouseEnterList(menu.id)}
id={menu.id}
>
{menu.name}
</li>
</Link>
);
})}
</ul>
{menuId === 1 ? (
<NewMenuBox
className="menubox"
isShown={isShown}
onMouseLeave={onMouseLeave}
onMouseEnter={onMouseEnter}
/>
) : (
(menuId === 2 || menuId === 3 || menuId === 4) && (
<OtherMenuBox
className="menubox"
isShown={isShown}
onMouseLeave={onMouseLeave}
onMouseEnter={onMouseEnter}
/>
)
)}
</div>
);
};
export default Menu;
두 번째 blocker : query parameter를 통해 필터링 기능 구현하기
blocker : 아직 동적 라우팅에 익숙치 않아서 쿼리 스트링을 사용하는 것 자체가 어려웠습니다. 그리고 나이키가 특히 카테고리를 다양하게 분류해서(style, gender, color, ...) 이 필터링 기능을 다 구현하는 것은 어렵다고 판단하여 style 카테고리에 대한 필터링만 진행하자고 결정했습니다. 우선 쿼리 스트링을 사용해야 하는 것을 알겠는데 이를 어떻게 적용해야 할지 잘몰랐습니다.
해결방법 : 구글링과 위코드 세션을 복습하며 다른 사람들의 코드를 따라쳐봤고, 이를 응용해 제가 필요한 부분을 구현했습니다. 해결 과정에서 console.log를 활용해 에러를 해결해나갔고 필터링 기능을 구현할 수 있었습니다.
import React, { useEffect, useState } from 'react';
import { useLocation, useSearchParams } from 'react-router-dom';
import Aside from './Aside/Aside';
import Banner from './Banner/Banner';
import Product from './Product/Product';
import { CATEGORY_DATA } from './Aside/data/categoryData';
import './ProductList.scss';
const ProductList = () => {
const [products, setProducts] = useState([]);
const [isFilterClicked, setIsFilterClicked] = useState(false);
// useLocation hook을 이용했습니다
const location = useLocation();
const category = location.search;
const [searchParams, setSearchParams] = useSearchParams();
const limit = searchParams.get('limit');
const page = searchParams.get('page');
useEffect(() => {
// 쿼리스트링으로 카테고리 필터링 기능을 구현했습니다
fetch(
`http://10.58.52.114:3000/products${category}?page=${page}&limit=${limit}`,
{
method: 'GET',
}
)
.then(res => {
return res.json();
})
.then(data => {
setProducts(data.data);
});
}, [page, limit, category]);
const onClickFilter = () => {
setIsFilterClicked(prev => !prev);
};
const movePage = pageNumber => {
searchParams.set('page', (pageNumber - 1) * 3);
setSearchParams(searchParams);
};
return (
<main className="productList">
<Banner onClickFilter={onClickFilter} />
<div className="contentWrapper">
<Aside
isFilterClicked={isFilterClicked}
products={products}
CATEGORY_DATA={CATEGORY_DATA}
/>
<div className="productWrapper">
<Product products={products} isFilterClicked={isFilterClicked} />
</div>
</div>
<div>
<button onClick={() => movePage(1)}>1</button>
<button onClick={() => movePage(2)}>2</button>
<button onClick={() => movePage(3)}>3</button>
</div>
</main>
);
};
export default ProductList;
4. 잘한 점과 아쉬운 점
잘한 점
- 꼼꼼한 기록과 스케줄 관리 :
- notion과 trello를 이용해 각자의 진행 상황을 꼼꼼히 기록하여 진행상황을 파악하기 수월했습니다. trello로 각 페이지 별 구체적인 진행상황을 확인했고, notion을 통해 daily meeting을 기록하고 공유해야 하는 내용을 정리했습니다.
- daily meeting 전 notion에 해당 미팅에서 공유해야 하는 내용을 미리 작성하고 미팅에 임해 프론트와 백이 소통하는 데 많은 도움이 됐습니다. 또한 프론트에서 구현하는 기능을 어떤 식으로 백엔드에 설명해야 할지도 배울 수 있었습니다.
- notion에서 프론트와 백엔드가 공유해야 하는 데이터를 따로 정리하여 상호간의 소통을 원활하게 했습니다.
아쉬운 점
- 보이는 기능을 구현하는 것에만 집중하여 페이지의 레이아웃에 대해 깊게 생각하지 못했습니다. 그러다 보니 처음부터 컴포넌트를 잘 분리하지 못했고, 프로젝트를 진행하면서 컴포넌트를 합쳤다 나눴다하면서 시간을 허비했습니다. 그래서 다음 프로젝트 때는 페이지 분석을 꼼꼼히 하여 어떤 기능을 왜 구현해야 하는지 세세히 작성할 계획입니다.
5. 다음 프로젝트에 임하는 자세
- 코더가 아닌 개발자가 되자 : 단순히 기능 하나를 더 구현하는 것보다 이 기능이 왜 필요하고 왜 내가 이 기능을 구현해야 하는지 생각하며 구현하겠습니다.
- 누가 봐도 이해할 수 있도록 말하고 기록하자 : 나의 진행상황은 어디쯤이고 어떤 기능을 어떻게 구현하고 있는지 말과 기록 모두 명확하게 표현할 것입니다. 첫 프로젝트이다보니 어떤 식으로 기능에 대해 설명하고 전달해야 하는지 소통방식이 미숙했습니다. 두 번째 프로젝트에서는 먼저 글을 통해 나의 생각과 진행과정을 자세히 정리하고, 정리한 내용을 바탕으로 남들이 쉽게 이해할 수 있는 언어로 소통하겠습니다.
'Learning Log > Project' 카테고리의 다른 글
[project] 나홀로집에 2차 프로젝트 회고 (0) | 2023.03.12 |
---|---|
[project] 나홀로집 프로젝트의 1차 스프린트 기간 회고 (0) | 2023.03.03 |
[project] nike motive coding (0) | 2023.02.10 |
[project] github repository 연결하기 (0) | 2023.01.14 |