✨ 기억보다 기록을/트러블슈팅

뱃지 컴포넌트 CSS 프리렌더링 문제

서카츄 2024. 11. 22. 00:13

뱃지 컴포넌트를 구현하면서 각각의 내용에 맞는 background 색상을 넣어 줬었는데

Best로 보이는 뱃지 색상이 안보이는 현상이 있었다. 

 

 

 

 

 

 

처음 무료배송 뱃지의 bg는 잘 나왔는데,

두번째 best는 개발자 도구를 켜서 확인해봐도 className에 잘 들어와 있었다.

 

`bg-orange` 색상은 커스텀 한 색상이었는데 혹시 빠졌나? 싶어 그대로 색상을 확인해보니 잘 나오고 있었다.

 

 

 

왜 이랬더라..? 하면서 곰곰히 생각해보니까

어??? 맞다 next 프리렌더링 과정에서 purple까지는 알고 불러왔는데, 프리렌더링 과정 시 bg-orange는 해당 색상이 미리 로딩되지 않아 없어서 그 색상이 안뜨는 것이었다.

강의 들었던 과정중에 이 내용이 있었는데 딱 그 내용이 떠오르면서 아 맞다 이거 아닌가? 싶더라

그리고 Tailwind CSS는 실제 렌더링 시 사용되는 클래스명만 빌드 파일에 포함시키기 때문에, 조건부 렌더링으로 인해 클래스명이 빌드에 포함되지 않으면 적용되지 않는 이슈가 있었다!

purge과정 → 정적으로 쓰이지 않는 클래스는 Tailwind가 최적화 하면서 날려버리는 현상

 

 

공식 문서

https://tailwindcss.com/docs/detecting-classes-in-source-files

 

Detecting classes in source files - Core concepts

Understanding and customizing how Tailwind scans your source files.

tailwindcss.com

공식문서에도 자세히 나와있지만...

결국 Tailwind는 실제 렌더링되는 코드 안(className이나 문자열)에 없는 클래스는 빌드할 때 제거한다고 명시하는 중

 

 

 

https://seokachu.tistory.com/283

 

20241118(월) ▶️ 굿즈샵페이지 Badge 공통 컴포넌트 만들기

Badge는 무료배송, 인기, best 등을 표시하기 위해서 사용했다!공통 컴포넌트로 유연성 있게 만들어 보았다. 뱃지 계산 로직//utils/calculateBadge.tsimport type { BadgeFields } from "@/types";export const calculateBadge

seokachu.tistory.com

 

기존에 작성했던 Badge 내용에서 수정해보도록 하자!!

 

 

 

 

 

문제가 발생하는 코드 흐름

  1. Badge 컴포넌트가 처음 렌더링될 때 averageRating은 초기값 0
  2. useEffect에서 getAverageRating을 비동기로 호출하여 실제 평점을 가져옴
  3. best 뱃지는 review_count >= 10 && rating >= 4 조건을 둘 다 만족해야 표시
const [averageRating, setAverageRating] = useState(0); // 초기값 0

// 초기 렌더링 시 여기서 rating이 0이므로 best 뱃지 조건을 만족할 수 없음
const badges = calculateBadge({ ...item, rating: averageRating });

 

비동기로 가져오면서 처음에는 초기렌더링이 0이라 조건을 가져올 수 없었다.

= 결국 Tailwind에서 조건부로 사용하다보니 빌드 최적화 과정에서 사용되지 않는다고 인식해서 사라진 것

더 풀어서 작성하자면, `badges`는 표시할 뱃지 종류 리스트인데

처음 렌더링될 때 averageRating이 0이니까 calculateBadge를 호출해도 badges 배열이 비어있다. (보여줄 뱃지가 없다)

 

 

 

두번째 문제

// badge color 설정
const getBadgeColor = (badge: string) => {
  switch (badge) {
    case BADGE_TYPES.FREE_DELIVERY:
      return `bg-purple`;
    case BADGE_TYPES.BEST:
      return `bg-custom-orange`;
    default:
      return `bg-gray-500`;
  }
};

 

badge color 설정 함수를 별도의 utils 폴더에 따로 분리해 관리 했었는데, Tailwind CSS 빌드 최적화 과정에서

이 파일을 추적하지 못해서 정상적으로 표시되지 않는다는 점

→ Tailwind CSS는 실제 렌더링 되는 JSX내에서 직접 사용하는 className 문자열은 무조건 인식한다는 것

→ 결국 컴포넌트 안에 있는 함수는 컴포넌트 렌더링 시 Tailwind가 쉽게 추적 가능

 

 

 

 

해결 방안

1. 평균 평점 데이터를 받아온 이후에만 뱃지를 렌더링하여, 초기 잘못된 렌더링으로 인한 TailwindCSS purge 문제를 방지함.

2. getBadgeColor 함수를 Badge 컴포넌트 내부로 이동하여, TailwindCSS가 빌드 타임에 해당 클래스명을 정상적으로 감지할 수 있도록 수정함.

 

 

 

 

1. 첫번째 문제 조건문 추가

if (badges.length === 0) return null;

 

조건문을 추가해서 badges 배열이 비어있으면, Badge 컴포넌트를 아예 렌더링 하지 않도록 했다.

 

여기서 Tawilwind CSS 빌드 과정과 연결하자면

처음 렌더링할 때 Badge 컴포넌트가 렌더링되면, 커스텀한 bg-orange가 없기 때문에 Tailwind에서 이 클래스 필요없네????

하고 날려버린다.

 

→ 처음에 렌더링 자체를 막아버렸기 떄문에 Tailwind는 아무것도 못보고 (못없앰!)

→ averageRating 데이터가 들어옴

→ badges가 생긴 이후에 DOM이 랜더링 됨 (span 태그)

→ bg-orange 클래스가 동작함.

→ Tailwind에서 문제 없이 그 클래스를 유지하게 됨

 

결론은 잘못된 초기 상태에서 불필요한 purge가 일어나는것을 막음.

 

 

 

 

 

2. getBadgeColor 함수 이동

import { BADGE_TYPES } from "@/utils/constants";
import { calculateBadge } from "@/utils/calculateBadge";
import type { BadgeFields } from "@/utils/calculateBadge";

export interface BadgeItemProps {
  item: BadgeFields;
  averageRating: number;
}

// badge color 설정
const getBadgeColor = (badge: string) => {
  switch (badge) {
    case BADGE_TYPES.FREE_DELIVERY:
      return `bg-purple`;
    case BADGE_TYPES.BEST:
      return `bg-custom-orange`;
    default:
      return `bg-gray-500`;
  }
};

const Badge = ({ item, averageRating }: BadgeItemProps) => {
  const badges = calculateBadge({ ...item, rating: averageRating });
  if (badges.length === 0) return null;

  return (
    <div className="flex items-center gap-1">
      {badges.map((badge) => (
        <span key={badge} className={`text-xs px-2 py-1 rounded-md text-white ${getBadgeColor(badge)}`}>
          {badge}
        </span>
      ))}
    </div>
  );
};

export default Badge;

 

그대로 코드를 옮겼기 때문에, 설명은 생략 (...)

 

 

 

 

이렇게 해서 Badge 컴포넌트 문제를 해결해 보았다.

처음에는 왜 작동 안되는지 이해가 안돼서 계속 이것저것 시도해봤는데 결국 렌더링 과정 문제였다 ㅠ ㅠ

Tailwind에 대해서 빌드 과정을 다시 배우는 계기가 되었고,

너무 많은 컴포넌트 분리도 흐름에 맞게 적당히 분리해야 한다는 것을 알게 된 계기가 되었다...🥲😊