Next.js 공식문서를 보면서 커머스 사이트(와이즐리) 구현하기 (3)

undefined·2022년 11월 29일
0
post-thumbnail

<소스 참고>
https://github.com/kimtaru/commerce_by_next13

레이아웃 구현 전

와이즐리의 레이아웃은 아래와 같습니다.

  1. Header
  2. Bottom Navigation
  3. Footer

Layout 만들기

layout 컴포넌트 생성

// components/layout/layout.js

import Footer from "./footer";
import Header from "./header";
import BottomNavigation from "./bottom-navigation";

export default function Layout({ children }) {
  return (
    <>
      <Header />
      <main>{children}</main>
      <Footer />
      <BottomNavigation />
    </>
  );
}

_app.js 적용


// pages/_app.js

import "../styles/globals.css";

function MyApp({ Component, pageProps }) {
  const getLayout = Component.getLayout || ((page) => page);
  return getLayout(<Component {...pageProps} />);
}

export default MyApp;

페이지 생성

헤더의 항목은 총 3개(추천/신제품/베스트)이므로 총 3개의 페이지를 구현했습니다. 그 중 '추천'은 메인화면이므로 pages/index.js에 구현하였습니다.

완성된 레이아웃

아래와 같이 레이아웃이 적용된 페이지가 완성되었습니다.

포스팅엔 소스를 덕지덕지 붙이고 싶지 않아서 많이 올리지 않았습니다. 깃헙을 참조해주시면 감사하겠습니다.
https://github.com/kimtaru/commerce_by_next13

Tailwind로 스타일링을 해보니

Tailwind로 CSS 작성을 하니 처음엔 다소 오래 걸렸습니다.
왜냐하면 Tailwind에서 제공하는 클래스명을 모르니 일일이 검색을 해야 하는 수고가 생겼습니다.

하지만 계속 사용하면서 자주 사용하는 스타일속성을 숙지해 나간다면
생산성 측면에서 매우 도움이 될 것 같다고 생각했습니다.
(친해질 시간이 필요합니다.)

그런데 일부 padding 이나 margin 혹은 top이나 bottom 같은 위치값이
규격화 되어 있고 % 단위를 지원하지 않아서 직접 스타일속성을 지정해야 할 일이 종종 생겼습니다.

특히 아래와 같은 컴포넌트는 동적으로 스타일 속성을 제어해줄 수 있어야 했고 두 개의 방법이 떠올랐습니다.

  1. useRef를 사용하여 클릭 이벤트로 스타일 속성 변경
  2. useState를 사용하여 변경 시 리렌더링

1번의 경우 소스가 불필요하게 길어졌습니다.

항목의 갯수만큼 ref를 생성해야 했고, 일일이 클릭 이벤트 함수를 구현해주어야 하기 때문에 소스가 불필요하게 길어집니다.

또한 2번의 경우 state를 통해 제어를 하니 항목 클릭 시 마다 새롭게 스타일이 적용되어 리렌더링 되었지만 새로고침을 하니 state의 값이 초기화 되어 현재의 path가 베스트 상품 페이지인데 추천 항목에 선택됨 스타일이 적용되는 현상이 발생했습니다.

어떻게 하면 새로고침을 해도 현재 위치값을 파악해 올바른 메뉴항목에 선택 스타일을 유지할 수 있을까요(persist)?


next/router

next에서 제공하는 라우터 훅을 통해 현재의 위치를 얻을 수 있습니다.


라우터의 정보를 얻고 싶을때 useRouter 훅을 사용할 수 있습니다.

공식문서는 정말 신기하게도 제가 고민하고 있는 부분을 정확하게 짚어내고 있습니다!

문서에서 제공하는 예시 소스에서는 router.asPath로 현재의 path를 String으로 얻은 다음 href와 비교하여 스타일을 동적으로 제어하고 있습니다.



따라서 아래의 코드와 같이 props의 값에 따라 동적으로 스타일링이 가능한 라이브러리 styled-components를 사용하여 스타일을 제어해줄 수 있었습니다.


/* 
	selected의 값에 따라 동적으로 스타일 반환함
**/

import styled from "styled-components";

const StyledLink = styled(Link)`
  cursor: pointer;
  --tw-text-opacity: 1;
  color: rgb(107 114 128 / var(--tw-text-opacity));
  line-height: 2.5rem;
  font-weight: 400;
  ${(props) =>
    props.selected &&
    ` color: rgb(30 64 175 / var(--tw-text-opacity));
      font-weight: 700;
      border-bottom-width: 2px;
      border-style: solid;
      --tw-border-opacity: 1;
      border-color: rgb(30 64 175 / var(--tw-border-opacity));
    `}
`;

	<StyledLink
		href="/"
		selected={router.asPath === "/"}
	>
        추천
    </StyledLink>

이로써 전체적인 레이아웃을 완성했습니다.

반드시 prefix를 설정하자

어플리케이션 전체의 스타일링을 Tailwind에게 모두 위임하지 않는 이상,
반드시 Tailwind Classname에 Prefix를 붙여서 사용하는 것을 권장드립니다.

저 같은 경우 빠른 페이지 구현을 위해 Ant Design을 추가로 사용할 계획이며 두 개의 프레임워크 사이 클래스명 충돌로 인한 이슈가 생길 수도 있다고 생각이 들었습니다.

Tailwind 사이트에 Conflict를 검색해보니 Prefix를 설정하는 방법이 나왔습니다.


저장하면 모든 tailwind의 클래스명에 접두사가 붙어서 제공되며
앞으로는 'tw-' 접두사를 붙여 사용하실 수 있습니다.

마치며

이제 각 페이지 및 컴포넌트와 그에 따른 기능구현에 들어가보도록 하겠습니다.

profile
여러 고민의 흔적

0개의 댓글