[CatCatStore] PurpleStore를 모티브로 한 개인 프로젝트

송나은·2021년 7월 25일
0

Project

목록 보기
6/6

Overview

레이아웃은 퍼플스토어 웹페이지를 참고하여 웹뷰로 제작하였습니다.

  • 기술스택: Redux, Next.js Javascript ES6+, Styled-Components
  • 작업기간: 2021.06.12 ~ 2021.6.16
  • 디렉토리 구조
├─common
├─components
├─pages
├─public
│ ├─data
│ └─image
├─redux
│ ├─actions
│ ├─reducers
│ └─store
└─styles

CatCatStore Repository 바로가기

페이지 구성

상품리스트

  • 상단에 고정 된 헤더에는 장바구니 수량이 표시됩니다. (목데이터 default값: 5개)
  • 상품리스트 상단에 조회하고 있는 상품의 수량을 표시합니다.
  • get 요청으로 product 상품을 불러옵니다. 상품을 불러오는 동안 loader 컴포넌트로 로딩중임을 표시합니다.
  • get 요청 실패 시 콘솔에 에러 메세지가 나타납니다.

장바구니 모달창

  • 원하는 상품의 장바구니 버튼 클릭 시 장바구니 담기 모달창이 열리면서 장바구니에 상품이 추가됩니다.
  • 모달창 진입 시 장바구니 총 금액에 맞는 섹션에 그래프가 그려지면서 할인율이 표시됩니다.
  • 모달창이 open 되어있는 동안 스크롤이 발생하지 않습니다.
  • "계속담기" 클릭 시, 모달창의 배경 클릭 시 상품리스트로 돌아가고, "장바구니 확인" 클릭 시 장바구니로 이동합니다.

장바구니

  • 장바구니 페이지 진입 시 전체 상품이 선택되고, 선택삭제 버튼을 클릭하면 장바구니의 모든 상품이 삭제됩니다.
  • 상품 추가/삭제/수량 변경 시 장바구니 수량이 및 가격이 바로 반영되어 나타납니다. (=> update 기능 수정중)
  • 배송비가 30,000원 이하일 경우, 무료배송에 대한 안내와 배송비 3,000원이 표시됩니다.
  • 장바구니에 상품이 있을 경우 하단 버튼에 장바구니 수량과 "구매하기" 버튼이 렌더됩니다.
  • 장바구니가 비었을 경우 empty 이미지와 "캣캣스토어 둘러보기" 버튼이 렌더되고, 클릭 시 상품 리스트 페이지로 이동합니다.

✍ 기록

Next.js

SSR vs CSR

SSR은 클라이언트가 접속했을 때 브라우저에서 js 코드를 다운받아 해석할때까지 기다리지 않고, 서버에 보여질 HTML을 미리 준비해 응답해주는 방식이다.

장점: 렌더링 속도 향상. SEO

CSR은 js파일을 브라우저에서 해석해 렌더링하는 방식이다.

장점: 부드러운 UX. 필요한 데이터만 요청해서 서버 부하가 줄어든다.

next

  • pages 폴더에 있는 파일의 이름이 곳 라우터 경로이다.
  • next에서 제공하는 image 컴포넌트 사용 시 next.config.js에 domain 경로를 지정해줘야 한다.

    Unhandled Runtime Error
    Error: Invalid src prop (http://) on next/image, hostname "assets.example.com" is not configured unter images in your next.config.js

// next.config.js

module.exports = {
  images: {
    domains: ['assets.example.com'],
  },
}
  • styled-components 사용 시 babel-plugin-styled-components 설치와 _document 설정이 필요하다.
// .babelrc
{
  "presets": ["next/babel"], // 하나의 목적을 위한 여러개의 플러그인 집합
  "plugins": ["styled-components"] // babel-plugin-styled-components 추가하여 서버와 클라이언트 결괏값 일치.
}

Redux

Flux pattern

액션 -> ( 미들웨어 ) -> 리듀서 -> 스토어 -> 뷰(리액트) -> 액션

  1. 액션: type 속성값을 가진 자바스크립트 객체. dispatch 메서드에 넣어 호출하면 리덕스는 상태값을 변경한다
  2. 미들웨어: 리듀서가 액션을 처리하기 전에 실행되는 함수. ex) 디버깅, 에러처리, 로컬 스토리지에 값 저장 등
  3. 리듀서: 액션이 발생했을 때 새로운 상탯값을 만드는 함수.
  4. 스토어: 리덕스의 상탯값을 가지는 객체. 액션의 발생은 스토어의 dispatch 메서드로 시작된다.

리덕스 특징

  • 같은 상탯값을 다수의 컴포넌트에서 필요로 할 때 사용하기 좋다.
  • 상탯값은 불변객체이며, 하나의 객체(스토어)에 저장한다.

next-redux-wrapper

Next.js는 유저가 요청할때마다 redux store를 새로 생성한다.

Next.js가 제공하는 getInitialProps, getServerSideProps등에서 리덕스 스토어에 접근하려면 serverside일때 redux store와 client side일때 redux store를 합쳐 주어야 한다.

👉 redux store를 wrapper로 감싸주고 최상위 컴포넌트를 wrapper.withRedux로 감싸준다.

const configureStore = () => {
  const store = createStore(reducer);
  return store;
};

const wrapper = createWrapper(configureStore);

const MyApp = () => {
  // ...
}

export default wrapper.withRedux(MyApp);

Basic Auth

api 서버에서 데이터을 요구할때 http Authorization 헤더에 user id 와 , password 을 base64 로 인코딩한 문자열을 추가하여 인증하는 형식

headers: {
  "Content-Type": CONTENTTYPE,
    Authorization: Basic base64
}

Base 64

8비트 이진 데이터(예를 들어 실행 파일이나, ZIP 파일 등)를 문자 코드에 영향을 받지 않는 공통 ASCII 영역의 문자들로만 이루어진 일련의 문자열로 바꾸는 인코딩 방식

base64encode 바로가기

Infinite Scroll

const infiniteScroll = () => {
  const scrollHeight = document.documentElement.scrollHeight;
  const scrollTop = document.documentElement.scrollTop;
  const clinetHeight = document.documentElement.clientHeight;

  if (scrollTop + clinetHeight > scrollHeight - 100 && products.next !== null)
    setPage(page => page + 1);
  };

useEventListener("scroll", infiniteScroll, []);

Debounce

dep가 변화하면, ms후에 callback 함수를 실행한다.

export const useDebounce = (callback, ms, deps = []) => {
  useEffect(() => {
    const id = setTimeout(callback, ms);
    return () => clearTimeout(id);
  }, deps);
};

Throttle

설정한 시간(delay)에 한번씩 이벤트를 발생시킨다.

Custom Hooks

export const useEventListener = (type, listener, deps = []) => {
  return useEffect(() => {
    window.addEventListener(type, listener);
    return () => window.removeEventListener(type, listener);
  }, deps);
};

export const useScroll = (type, deps = []) => {
  useEffect(() => {
    document.body.style.overflow = type;
  }, deps);
};

useRef

리액트에 있는 모든 컴포넌트는 reference element를 가지고 있어서 어떤 component에 ref={변수명}을 넣어주면, 해당 component를 참조하게 된다.

  • DOM에 접근할 때 사용한다.
  • ref의 current 속성으로 타겟을 지정할 수 있다.

    (주의) component가 렌더링 되지 않은 상태에서 current에 접근하면 undefined가 나타난다.

  • 컴포넌트 안에서 조회 및 수정 가능한 변수를 관리할 수 있다.

    변수가 업데이트 된다고 해서 컴포넌트가 리렌더링이 되지 않는다.

데이터 시각화

CSS_Transition

속성을 서서히 변화시키는 속성
transition: property timing-function duration delay | initial | inherit

  • property
  • timing-function 진행속도
  • duration 총 시간
  • delay 시작 연기

linear-gradient()

직선형 그라데이션을 설정할 수 있는 속성

const Graph = styled.div`
  position: relative;
  width: ${props => props.price}%; 
  height: 100%;
  margin-bottom: 0.3rem;
  border-radius: 0.4375rem;
  background-image: linear-gradient(
    to right,
    rgb(242 242 242),
    rgb(127 131 135)
  );
  transition: 0.5s;
`;

em vs rem

미디어 쿼리와 함께 사용하며 뷰포트의 크기에 따라 길이를 가변적으로 핸들링 할 수 있다.

em은 단위가 적용된 요소의 글자 크기에 비례한다.

rem은 html 태그(최상위 요소)의 글자 크기에 비례한다. (=root em)

브라우저 기본 설정 기준에서 16px을 가지고 시작하는데 62.5%를 곱해주면 10px로 맞추고 rem을 10배수로 쓸 수 있다.

Reference

profile
그때그때 공부한 내용과 생각을 기록하는 블로그입니다.

0개의 댓글