[TIL #51] next 팀프로젝트 트러블 슈팅 footer

차슈·2024년 7월 10일
0

TIL

목록 보기
51/70
post-thumbnail

트러블 슈팅

문제

라우터가 없는 Next.js 환경에서 특정 경로(/meeting)에서는 푸터를 sticky로 설정하고, 나머지 경로에서는 fixed로 설정하고 싶어했다. 이를 위해 기존 Footer 컴포넌트를 수정하고, CVA를 사용하여 변형을 적용했다.

 <html lang="en">
      <body className={inter.className}>
        <Header />
        {children}
        <Footer />
      </body>
    </html>

position을 stickyfixed 번갈아서 넣고, 모든 페이지에서는 'fixed'를 넣고 '/meeting'만 sticky를 적용해야하는데

컴포넌트를 따로 분리해서 layout.tsx를 따로 만들었는데도 해결할 수 없었고,

컴포넌트마다 footer 적용을 해봤지만 코드의 효율성 문제로 쓰지 않았다.

근본적 문제:

모든 페이지에서 Footer를 fixed로 설정하고, /meeting 페이지에서는 sticky로 설정하는 요구사항을 충족해야했다. 기존 컴포넌트 구조에서는 이를 동적으로 처리하기 어려웠다.


해결:

CVA와 Next.js의 usePathname 훅을 사용하여 경로에 따라 position 속성을 동적으로 변경했다.
CVA를 사용해 fixedsticky 변형을 정의.
usePathname 훅을 사용해 현재 경로를 확인하고, 경로에 따라 position 속성을 설정.

해결코드

변경된 Footer 컴포넌트에서는 경로에 따라 position 속성을 동적으로 설정했다.

'use client';
import { cva, VariantProps } from 'class-variance-authority';
import { usePathname } from 'next/navigation';
import { ComponentProps, PropsWithChildren } from 'react';

const footerVariants = cva(' bg-header-color text-white text-center py-4 bottom-0 left-0 w-full z-10', {
  variants: {
    position: {
      fixed: 'fixed',
      sticky: 'sticky'
    }
  }
});

type FooterVariant = VariantProps<typeof footerVariants>;
type FooterProps = FooterVariant & ComponentProps<'footer'>;

export default function Footer({ position, ...props }: PropsWithChildren<FooterProps>) {
  const pathname = usePathname();
  const isMeetingPath = pathname.startsWith('/meeting');
  const Position = isMeetingPath && position === undefined ? null : 'fixed';
  return (
    <footer className={footerVariants({ position: Position })} {...props}>
      {' '}
      &copy; 2024 독수리오남매. All rights reserved.
    </footer>
  );
}

결과

특정 경로에서는 sticky 푸터를, 나머지 경로에서는 fixed 푸터를 동적으로 적용할 수 있게 되었다.


CVA

class-variance-authority 라이브러리의 약자로 일관성 있는 UI를 정의하고 사용할 수 있도록 도와주는 툴로써 컴포넌트 사용할때 유용하다.
즉, 공통 스타일링

설치

yarn add class-variance-authority

예시

import { cva } from "class-variance-authority";
 
const button = cva("button", {
  variants: {
    intent: {
      primary: "button--primary",
      secondary: "button--secondary",
    },
    size: {
      small: "button--small",
      medium: "button--medium",
    },
  },
  compoundVariants: [
    { intent: "primary", size: "medium", class: "button--primary-small" },
  ],
  defaultVariants: {
    intent: "primary",
    size: "medium",
  },
});
 
button();
// => "button button--primary button--medium"
 
button({ intent: "secondary", size: "small" });
// => "button button--secondary button--small"

intentsize의 값에 따라 다른 디자인을 보여줄 수 있도록 구성되어 있다.
cva 첫번째 인자에는 모든 경우 공통으로 들어갈 css를 입력하게 된다.
만약 없다면 '' 비워두어도 된다.
두번째 인자에서부터 조건에 따른 객체를 넣어주면 된다.

0개의 댓글