라이브러리/MUI

[Next.js + MUI + Emotion] Received true for a non-boolean attribute $preview 오류 해결기

순코딩 2025. 4. 22. 13:34

🧩 문제 상황

Next.js, MUI, Emotion 조합으로 컴포넌트를 구현하던 중, 콘솔에 아래와 같은 에러 메시지가 떴습니다.

Error: Received `true` for a non-boolean attribute `$preview`.

If you want to write it to the DOM, pass a string instead: $preview="true" or $preview={value.toString()}.


처음엔 단순한 경고처럼 보였지만, 실제로는 styled 컴포넌트의 boolean 커스텀 prop이 그대로 HTML DOM으로 전달되며 발생한 오류였습니다.

 

🔎 문제 코드 분석

에러가 발생한 컴포넌트는 다음과 같습니다:

<Container $preview={preview}>
  {preview && <Text variant="body1">빈 공간 생성</Text>}
  <SpaceBox $height={blockData.height} $preview={preview} />
</Container>



그리고 styled로 감싼 컴포넌트는 다음과 같이 정의되어 있었죠:

type ContainerProps = {
  $preview: boolean;
};

const Container = styled(Stack)<ContainerProps>`
  border: ${({ $preview }) => ($preview ? "1px dashed gray" : "none")};
`;


여기서 문제는 $preview가 React 컴포넌트(Stack, Box)를 통해 HTML DOM까지 전달되면서 발생했습니다. React는 $preview 같은 이름을 HTML 요소 속성으로 인식하지 못해 오류를 발생시킵니다.

 

 

✅ 해결 방법: shouldForwardProp 설정하기

Emotion에서는 styled 함수에 shouldForwardProp 옵션을 지정해, 특정 props가 DOM에 전달되지 않도록 필터링할 수 있습니다.



💡 핵심 코드

import isPropValid from "@emotion/is-prop-valid";

// 공통 정의
const shouldForwardProp = (prop: PropertyKey) =>
  typeof prop === "string" && isPropValid(prop) && !prop.startsWith("$");

// 적용
const Container = styled(Stack, { shouldForwardProp })<ContainerProps>`
  border: ${({ $preview }) => ($preview ? "1px dashed gray" : "none")};
`;

const SpaceBox = styled(Box, { shouldForwardProp })<SpaceBoxProps>`
  background-color: ${({ $preview }) => ($preview ? "lightblue" : "transparent")};
`;

 

 

✅ 결과

$preview, $height 같은 커스텀 스타일 전용 props는 DOM에 전달되지 않음

React 경고/에러 사라짐

컴포넌트 내부에서는 여전히 props를 활용 가능

 

✨ 보너스: 왜 $preview처럼 $를 붙일까?

$ 접두사는 관례적으로 "이건 스타일에만 사용하는 prop입니다"라는 의미로 사용됩니다.

 shouldForwardProp과 함께 쓰면 가독성과 유지보수 측면에서도 명확한 분리가 가능하죠.

 

🔚 마무리 정리

문제
Emotion styled 컴포넌트에 boolean 커스텀 props 전달 시, DOM까지 전달되어 React 오류 발생

원인
$preview와 같은 props가 HTML DOM 요소까지 전달됨

해결
shouldForwardProp를 설정하여 DOM 전달 차단


커스텀 스타일용 props는 $ 접두사를 붙이고 필터링 규칙을 설정하자


📌 전체 적용 코드 예시

import { styled, Box, Stack, Typography } from "@mui/material";
import isPropValid from "@emotion/is-prop-valid";

const shouldForwardProp = (prop: PropertyKey) =>
  typeof prop === "string" && isPropValid(prop) && !prop.startsWith("$");

const Container = styled(Stack, { shouldForwardProp })<{ $preview: boolean }>`
  border: ${({ $preview }) => ($preview ? "1px dashed gray" : "none")};
`;

const SpaceBox = styled(Box, { shouldForwardProp })<{ $height: number; $preview: boolean }>`
  height: ${({ $height }) => $height}px;
  background-color: ${({ $preview }) => ($preview ? "lightblue" : "transparent")};
`;

const Text = styled(Typography)`
  position: absolute;
  color: gray;
`;


이 에러는 Emotion 기반 프로젝트에서 styled-components처럼 커스텀 스타일 props를 자주 쓰는 경우 흔히 마주치는 문제입니다.

shouldForwardProp만 잘 설정해도 안정성과 깔끔한 코드 품질을 유지할 수 있습니다.