🧩 문제 상황
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만 잘 설정해도 안정성과 깔끔한 코드 품질을 유지할 수 있습니다.
'라이브러리 > MUI' 카테고리의 다른 글
[MUI] <Switch/> 컴포넌트 스타일링(너비, 높이, ...) 커스터마이징 예시 코드 (0) | 2025.04.25 |
---|---|
[MUI] 스타일 프롭스 추가 | shouldForwardProp 사용방법 (0) | 2025.04.22 |
[MUI] 컴포넌트에 스타일 프롭스 추가하는 방법 (0) | 2025.04.22 |
[MUI] 캘린더 달력 한국 시간으로 변경하기 (0) | 2025.04.17 |
[MUI] <SwipeableTemporaryDrawer/> 전역 상태로 상태 관리 방법 feat.예시코드 (0) | 2025.04.15 |