✏️기록하는 즐거움
article thumbnail
반응형

너무 늦어버린 3회차 회고,,ㅎㅎㅎ

깃헙 참고하면서 기억 더듬기!

 

✍️ 3주차 과제 내용

3주차에는 꽤 많은 내용의 과제를 진행했다.

  • 2주차 과제 리팩토링
  • Home 페이지 기능 구현하기
  • ProductDetail 페이지 기능 구현하기

 

♻️2주차 리팩토링 내용

⚠️ 수정할 내용 🪄 해결 방법
'DetailMenuButton' 컴포넌트명은
버튼 하나로 착각 할 수 있다.
DetailMenuButton => DetailMenuTabs로
컴포넌트명 변경
버튼 text 등의 요소는 pages 단위까지
끌어 올려주는 것이 좋다.
버튼의 text를 props로 받아 사용
styled-components를 사용한 컴포넌트를 만들 때
네이밍이 어렵다.
styled-components의 중첩 기능 활용

✅해결 1. DetailMenuButton => DetailMenuTabs로 컴포넌트명 변경

DetailMenuButton 컴포넌트에는 <button>이 두 개 들어가 있었다.
단수형 컴포넌트명은 적절하지 않으므로 복수형으로 수정하였다.

✅해결 2. 버튼의 text를 props로 받아 사용

text를 수정할 일이 생길 경우 pages 쪽에서 수정할 수 있어서 컴포넌트를 찾을 수고를 덜었다.

또, 버튼이 추가로 생기거나 했을 때, pages에서 바로 텍스트를 담은 배열을 전달할 수도 있을 것 같다.

// 기존 DetailMenuTabs 컴포넌트 코드

const DetailMenuTabs = () => {
  return (
    <StyledDetailMenuTabs>
      <MenuButton position={"left"}>상품 설명</MenuButton>
      <MenuButton position={"right"}>상품 후기</MenuButton>
    </StyledDetailMenuTabs>
  );
};
// 수정된 코드
const DetailMenuTabs = ({ firstTabName, secondTabName }) => {
  return (
    <StyledDetailMenuTabs>
      <button name="button">{firstTabName}</button>
      <button name="button">{secondTabName}</button>
    </StyledDetailMenuTabs>
  );
};

✅해결 3. styled-components의 중첩 기능 활용

만약 ProductInfo가 있다고 하면 이 안에서 상품명, 상품 이미지, 상품 가격 등의 요소들이 있을 것이다.

처음에는 이 요소들을 모두 styled-components로 만들고 있었는데, 점점 네이밍을 하기가 힘들어졌다.

이때는 styled-components의 중첩 기능을 활용하자!

 

styled-components: Basics

Get Started with styled-components basics.

styled-components.com

styled-components는 scss와 유사하게 사용할 수 있기 때문에 중첩도 가능하다!

중첩을 사용하면 네이밍 걱정 끝✨

 

✅ Home 페이지 기능 구현

  • 테마별 상품 리스트 보여주기
  • 상품을 클릭했을 때 상세 페이지로 이동하기

테마별 상품 리스트 보여주기

1) mock data 세팅

현재 서버에서 데이터를 받아서 사용하는 것이 아니기 때문에 mock data를 넣어서 진행하였다.

mock data
mock: 거짓된, 가짜의
실제 API에서 받아온 데이터가 아닌 필요에 의해서 샘플로 만든 데이터

 

mock data의 형식은 JSON으로 key: value의 객체 형태이다.

주로 data/ 혹은 sample/ 폴더에 파일을 만들어 놓는다.
// src\data\MockData.js
export const mockTheme1Products = [
  {
    id: 1,
    name: "비숑 블랙 머그잔",
    description:
      "쌀쌀한 날씨에 따뜻한 우유, 커피 한잔하기 좋은 블랙 & 화이트 비숑 머그잔입니다.",
    thumbnail:
      "IMG URL",
  },
  {
    id: 2,
    name: "가열 보온 티코스터 온열 원터치 컵 받침대",
    description:
      "언제나 따뜻하게 최대 :2시간 동안 최대 60도의 온도로 따듯한 차를 즐길 수 있습니다.",
    thumbnail:
      "IMG URL",
  },
  ]

데이터가 들어있는 객체 배열과 map() 메서드를 사용하여 기존의 코드에서 중복을 줄일 수 있다.

원래는 fetch를 사용하여 데이터를 받아오는 것이 후에 코드를 수정하는데 편하지만, 간단하게 진행하기 위해 데이터를 바로 가져왔다.

fetch
Fetch API가 제공하는 메서드로, 서버에 네트워크 요청을 보내고 새로운 정보를 비동기적으로 가져올 때 사용된다.

 

2) useEffect를 사용하여 데이터 보여주기

현재 데이터 파일을 프론트에서 가지고 있기 때문에 데이터를 유저에게 바로 보여주어도 되지만,

실제 서버 API를 통해 데이터를 불러오는 환경에서는 데이터를 불러오는 데 시간이 걸린다.

따라서 이 때 useEffect를 사용하여 비동기로 데이터를 가져오고, 데이터를 불러오기까지 유저에게는 로딩 화면 등을 제공한다.

const Home = () => {
  const [products, setProducts] = useState();

  const onClickThemeButton = (themeId) => {
    if (themeId === 1) {
      setProducts(mockTheme1Products);
    } else {
      setProducts(mockTheme2Products);
    }
  };

  useEffect(() => {
    // 1초 후, 상품 초기화
    setTimeout(() => {
      setProducts(mockTheme1Products);
    }, 1000);
  }, []);

  return (
    ...
    <ProductSection>
      {products ? (
        // 상품 리스트를 보여준다.
        <div>상품 리스트</div>
      ) : (
        <div>테마를 선택해주세요</div>
      )}
    </ProductSection>
  );
};

 

 

상품을 클릭했을 때 상세 페이지로 이동하기

페이지 이동은 react-router-dom의 useNavigate를 사용한다.

import { useNavigate } from "react-router-dom";

const Home = () => {
	const navigate = useNavigate();
    
    return (
    	<ProductCard onClick={() => navigate(`product/${product.id}`)} />
    );
}
useNavigate
useNavigate는 특정 이벤트가 발생했을 때, url을 조작할 수 있는 interface를 제공한다.
주로 navigate 라는 상수에 할당하여 사용한다.

navigate의 첫 번째 인자로는 이동할 주소, 두 번째 인자에는 { replace, state } 를 사용한다.

이동할 ProductDetail 페이지에서 어떤 상품을 클릭했는지 알 수 있도록 url에 파라미터를 사용한다.

만약 id가 3인 상품을 클릭했다면 이동한 url에는 /product/3 이 포함되어 있다.

 

✅ ProductDetail 페이지 기능 구현

  • Home 페이지에서 클릭한 상품의 정보를 나타낸다.
  • 상품의 상세 정보, 리뷰를 나타낸다.

 

클릭한 상품 정보 보여주기

// App.js
<Routes>
    <Route path="/" element={<Home />} />
    <Route path="/product/:productId" element={<ProductDetail />} />
    <Route path="/basket" element={<Basket />} />
</Routes>
import { useParams } from "react-router-dom";

const ProductDetail = () => {
  let { productId } = useParams();
  const [product, setProduct] = useState();
  
  useEffect(() => {
    const result = getProductDetail(productId);
    setProduct(result);
  }, [productId]);

useParams hook을 사용하면 url에 파라미터 값을 가져올 수 있다.

클릭한 상품의 id를 가지고 데이터에 서 같은 id를 가진 상품의 정보를 가져와 사용한다.

useParams
Route path의 매개변수에 해당하는 값을 가져올 수 있다.

 

상품의 상세 정보, 리뷰 나타내기

홈 페이지에서 구현했던 것처럼, 상품 탭에도 클릭한 탭에 따라서 상품 설명과 후기가 보이게 구현한다.

// pages/ProductDetail
const ProductDetail = () => {
  const [tabMenu, setTabMenu] = useState(0);
  
  const handleClickTabs = (tabId) => {
    if (tabId === 0) {
      setTabMenu(0);
    } else {
      setTabMenu(1);
    }
  };
  
  return (
      <DetailMenuTabs
        firstTabName={"상품 설명"}
        secondTabName={"상품 후기"}
        tabMenu={tabMenu}
        onClick={handleClickTabs}
      />
      <ProductDetailView
        detailImg={product.detailImg}
        name={product.name}
        tabMenu={tabMenu}
      />
  );
// comopnents/DetailMenuTabs
const DetailMenuTabs = ({ firstTabName, secondTabName, tabMenu, onClick }) => {
  return (
    <StyledDetailMenuTabs>
      <TabButton
        name="button"
        active={tabMenu === 0}
        onClick={() => onClick(0)}
      >
        {firstTabName}
      </TabButton>
      <TabButton
        name="button"
        active={tabMenu === 1}
        onClick={() => onClick(1)}
      >
        {secondTabName}
      </TabButton>
    </StyledDetailMenuTabs>
  );
};
// components/ProductDetailView
<StyledProductDetailView>
  {tabMenu === 0 ? (
    <img src={detailImg} alt={name + " 상품 설명"} />
  ) : (
    <div>상품 후기 화면입니다.</div>
  )}
</StyledProductDetailView>

 

🧹 정리

작업이 많아질수록 커밋 메시지의 길이가 불필요하게 길어지는 것을 확인할 수 있었다.

커밋 메시지가 너무 길어지지 않도록 수정한 부분의 핵심을 파악하는 것이 중요함을 알았다.

 

커밋 메시지를 잘 요약하려면 어떻게 해야할까?

방법을 찾아보다가 어떻게 보다는 무엇과 왜 라는 작성 규칙을 발견했다.

또한 다양한 저장소의 커밋 히스토리를 보면서 작성 방법을 익히는 것도 하나의 방법이라고 생각한다.

 

추가적으로 컴포넌트의 props 이름을 설정하기 어렵다면!
HTML element의 속성이나 CSS 가상 클래스를 참고하는 것이 좋다.

예를 들어 버튼이 클릭되었을 때에 따른 동작을 추가하고 싶다면 버튼의 클릭 여부 props 이름은 뭐로 할 수 있을까?

isClicked, clicked, isActive, active, ... 등 많은 이름을 생각할 수 있다.

제일 가독성이 좋은건 active 이다. 기본적인 CSS 가상 클래스에서 element가 활성화 되었을 때 active를 사용하기 때문이다.

물론 props의 이름은 자유롭게 사용해도 좋지만 코드의 가독성이 올라간다는 것은 좋은 점이니까!👍

 

 

 

✔️ 3주차 작업 내용 알아보기 (Github Projects)

 

Comento-Shopping Project Session03 • mihyunLee

Date: 2023.01.06-2023.01.10

github.com

 

 

반응형
profile

✏️기록하는 즐거움

@nor_coding

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!