Skip to main content

Command Palette

Search for a command to run...

[트러블슈팅] Toastify CSS가 적용되지 않을 때 (feat. tailwind CSS)

Updated
3 min readView as Markdown
[트러블슈팅] Toastify CSS가 적용되지 않을 때 (feat. tailwind CSS)

이번에 Toastify를 처음 사용해봤는데 css가 적용이 안 된다🥹

utils/toastService.js

import { toast } from 'react-toastify'

const defaultOptions = {
  position: 'top-center',
  autoClose: 2000,
  hideProgressBar: false,
  closeOnClick: true,
  pauseOnHover: true,
  draggable: true,
  theme: 'colored',
}

const ToastService = {
  success: (message, options = {}) =>
    toast.success(message, {
      ...defaultOptions,
      className: 'bg-pink-100 text-main-pink font-semibold rounded shadow',
      progressClassName: 'bg-main-pink',
      icon: '🌸',
      ...options,
    }),

  error: (message, options = {}) =>
    toast.error(message, {
      ...defaultOptions,
      className: 'bg-red-100 text-red-700 font-semibold rounded shadow',
      progressClassName: 'bg-red-500',
      icon: '❌',
      ...options,
    }),

  info: (message, options = {}) =>
    toast.info(message, {
      ...defaultOptions,
      className: 'bg-blue-100 text-blue-700 font-semibold rounded shadow',
      progressClassName: 'bg-blue-500',
      icon: 'ℹ️',
      ...options,
    }),

  warning: (message, options = {}) =>
    toast.warn(message, {
      ...defaultOptions,
      className: 'bg-yellow-100 text-yellow-700 font-semibold rounded shadow',
      progressClassName: 'bg-yellow-500',
      icon: '⚠️',
      ...options,
    }),
}

export default ToastService

이렇게 커스텀을 해뒀다..‼️

하지만 css가 적용이 안 된다 🙂‍↔️ (부정)

어느부분이 문제라고 생각했냐?

  • 엄청난 구글링을 통해 다양한 해결책을 적용해보았다… 하지만 단 하나도 해결방법이 되어주진 못 했다..!!! 그러던 중에 근본적으로 tailwind로 스타일을 주고 있으니 스타일을 주는 방식이 문제가 있나..?! 라는 생각을 했다.
//기존에 css 주는 방식 
error: (message, options = {}) =>
    toast.error(message, {
      ...defaultOptions,
      className: 'bg-red-100 text-red-700 font-semibold rounded shadow',
      progressClassName: 'bg-red-500',
      icon: '❌',
      ...options,
}),

그래서 기존 className 방식에서 style 방식으로 수정해줬다.

error: (message, options = {}) =>
    toast.error(message, {
      ...defaultOptions,
      style: {
        backgroundColor: '#fee2e2',
        color: '#b91c1c',
        fontWeight: '600',
        borderRadius: '0.375rem',
        boxShadow: '0 1px 2px rgba(0,0,0,0.05)',
      },
      progressStyle: {
        background: '#ef4444',
      },
      icon: '❌',
      ...options,
    }),

적용이된다.. 충격!!!! 🤦🏻‍♀️

🧐 왜 이런일이 발생했을까?

  1. Tailwind의 클래스 제거 최적화

Tailwind CSS는 빌드할 때 사용되지 않은 CSS 클래스는 자동으로 제거한다.

이 기능을 PurgeCSS 또는 content 기반 트리 셰이킹이라고 함

// tailwind.config.js
content: ['./src/**/*.{js,jsx,ts,tsx}']

다들 분명 tailwind.config.js가 이렇게 되어 있을것임 ‼️

Tailwind는 이 경로 내에서 실제로 직접 적혀 있는 클래스명만 찾아서 빌드에 포함하는 특징이 있다.

  1. react-toastify는 동적으로 className을 적용함

    • toast.success('message', { className: 'bg-red-100 text-red-700' }) 처럼 동적으로 문자열을 전달하면 Tailwind는 이 className이 정적인 HTML/CSS/JSX 안에 없기 때문에 제거해버린다.
    toast.success('hello', {
      className: 'bg-red-100 text-red-700',
    })

는 Tailwind 입장에서 볼 때 "bg-red-100"이라는 클래스가 어디에도 직접 안 써 있으니 지워버린것이다…🥺

✅ 해결된 이유: style은 CSS를 "직접" 지정하니까!

  • style은 자바스크립트 객체로 실제 인라인 CSS를 직접 전달하기 때문에 Tailwind와는 상관없이 적용된다.

🌱 배운 점

  • Tailwind CSS는 사용되지 않은 클래스명을 자동으로 제거한다는 사실을 실제로 겪으며 이해할 수 있었다. 특히 react-toastify처럼 외부 라이브러리에서 동적으로 className을 넘기는 경우에 Tailwind의 트리 셰이킹 대상이 되어 클래스가 적용되지 않을 수 있다는 걸 알게 되었다.(Tailwind는 역시 어려워)

  • ToastContainer를 잘 넣고 ToastService도 분리해놨지만 스타일이 안 먹는 이유는 Tailwind의 빌드 방식 때문이었고 해결방법으로 style 속성으로 직접 CSS를 넣는 방식이 가장 확실하다는 것도 알게 되었다.(style최고)


💬 느낀 점

  • 글만 보면 굉장히 짧은 시간에 해결한 것처럼 보이지만, 실제로는 꽤 많은 시간을 구글링하고, Stack Overflow나 GitHub 이슈에서 제안된 다양한 방법들을 시도해봤다.

    하지만… !!! 그렇게 복잡한 해결책들 대부분은 문제를 해결해주지 못한 걸 확인하고 결국 핵심은 굉장히 기본적인 부분에 있으며 기본은 역시 중요하다는 걸 다시 한번 또 또 또 느꼈다.

  • 동적으로 className을 전달하는 방식이 Tailwind에서는 위험할 수 있다는 사실은 알고 있었지만 실제로 겪어보니 그 중요성을 더 크게 체감했다.

More from this blog

[React] 클라이언트에서 이미지를 압축해보자

우리는 서버 비용을 직접 부담하고 있기 때문에 항상 최적화와 비용 절감 방법을 고민하게 된다. 현재 자유게시판이 활성화가 많이 되지는 않았지만 사용자들이 업로드하는 이미지가 평균 5MB 이상일 경우를 대비해서 클라이언트에서 이미지 압축을 진행했다. 웹에서는 크게 두 가지 방법이 있었는데 Canvas API를 직접 사용하는 방법 browser-image-compression 라이브러리를 활용하는 방법 이 있다. 여러 장점을 고려해 brow...

Oct 8, 20252 min read
[React] 클라이언트에서 이미지를 압축해보자

[책 추천] 프론트엔드 개발자라면 반드시 알아야 할 '웹 접근성' 이야기

내가 생각하는 프론트엔드 개발자는 단순히 보이는 화면만 구현하는 것을 넘어서 누구나 접근할 수 있는 웹을 만드는 데 중요한 역할을 해야 한다고 생각한다. 실무에 바로 적용하는 웹 접근성 가이드북 이번에 이 책을 받고 프엔들이 읽기에 너무 좋다고 생각해서 블로그에 추천 글까지 적게 되었다 ! 목차 Chatper1. 쉽게 이해하는 접근성 Chapter2. 웹 접근성의 기초 Chapter3. HTML 태그, 의미 있게 사용하기 Chpater4...

Jul 27, 20255 min read
[책 추천] 프론트엔드 개발자라면 반드시 알아야 할 '웹 접근성' 이야기

[Next.js] 나만의 학습 블로그 만들기#3-다국어 지원 (Feat.next-i18next)

오늘은 다국어 지원 가능한 기능 구현 과정을 적어보려고 한다. 원래는 댓글기능보다 먼저 구현하려고 했는데 ,, 갑자기 댓글기능 알아보다가 재밌어서 먼저 끝내버렸다,,,🙄 시작하기 전에 정말 어려웠다 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ 어려움이 많아서 기능 적용하는 데 시간이 꽤 걸렸다 ,,, 다국어 지원 기능 나는 영어랑 일본어를 추가해줬다 ! (해외취업도 관심 있기 때문에 나중에 이력서 낼 때 도움이 되지 않을까? ..🤭) 다국어 구현 방법 구현 방...

Jul 15, 20254 min read
[Next.js] 나만의 학습 블로그 만들기#3-다국어 지원 (Feat.next-i18next)

[Next.js] 나만의 학습 블로그 만들기#4 - 댓글 기능(Feat. Giscus)

댓글기능이 있으면 무조건 재밌을 거 같아서 넣어보려고 한다🤭 아무래도 개발에 관련된 학습 블로그라서 개발자들이 많을 것으로 예상했다 ! 그래서 깃허브 이슈 기반 댓글 시스템을 기반으로 기능을 구현해보려고 한다. 👉🏻 도움이 많이 된 블로그 ! 방법 Giscus | (https://giscus.app) utterances | (https://utteranc.es) 알아봤을 때는 이렇게 두 개가 유명하다고 한다. 그럼 각각의 특징과 장...

Jul 14, 20253 min read
[Next.js] 나만의 학습 블로그 만들기#4 - 댓글 기능(Feat. Giscus)

[React] React + localStorage로 하루에 한 번만 보이는 팝업 만들기

이번 프로젝트에 설문조사 배너를 제작했는데… 흠… 뭔가 별로라는 의견이 많았다! (팀원들 의견) 🙄 디자인이 문제일까? 해서 래퍼런스를 많이 찾아봤는데 … ! 일반 웹사이트는 설문조사 배너 자체를 안 만들어요,,,🤭 충격 그 자체 ( 난 아직 멀었음 ) 그리고 알아보니깐.. 설문조사 배너는 사용자 경험을 해치기 쉬워 잘 쓰이지 않는다고 한다! 그래서 나는 모달 팝업 방식으로 전환하기로 결정했고 실무에서 자주 사용하는 패턴으로 구현했다. 방...

Jul 9, 20253 min read
[React] React + localStorage로 하루에 한 번만 보이는 팝업 만들기
S

subin-dev-blog

27 posts

끊임없이 배우기 위해 노력합니다. 🌱