Hydration 에러: styled-components와 framer-motion동시 사용시 props가 강제로 넘어가면서 생긴 복합적 문제 해결하기
Description: HeroBanner 구현 중 styled-components와 framer-motion 결합으로 발생한 Hydration 에러를 분석하고, Next.js의 서버 렌더링과 클라이언트 DOM, 가상 DOM 간의 문제를 학습하며 해결한 과정을 기록합니다
현재 노트: KR-210.00 a Hydration 에러: styled-components와 framer-motion동시 사용시 props가 강제로 넘어가면서 생긴 복합적 문제 해결하기
상위 분류: KR-210 렌더링 및 UI or UX
#React_Next #React #styled_comonents #framer_motion
Hydration 에러: styled-components와 framer-motion동시 사용시 props가 강제로 넘어가면서 생긴 복합적 문제 해결하기
배경
HeroBanner컴포넌트를 만드는 과정에서 따로 따로 사용시 문제가 없는 두 개의 라이브러리를 동시에 쓰면서 발생하는 복합적인 문제가 발생하였습니다. 이 과정에서 Hydration
개념 학습 및 Next의 서버렌더링에서 최종 클라이언트 DOM까지의 과정 학습. 그리고 가상 DOM에서의 렌더링 문제를 학습하여 최종적으로 문제를 해결하기까지의 과정을 작성합니다
완성 결과
에러로그
Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used
- A server/client branch
if (typeof window !== 'undefined')
. - Variable input such asDate.now()
orMath.random()
which changes each time it's called. - Date formatting in a user's locale which doesn't match the server. - External changing data without sending a snapshot of it along with the HTML. - Invalid HTML tag nesting. It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.
See more info here: https://nextjs.org/docs/messages/react-hydration-error
+ bgcolor="#FFD700"
- bgcolor={null}
+ Page 1 Content
처음 파악한 원인 currentIndex 값의 불일치로 인한 hydration error
- 클라이언트에서만 동작하는 로직:
- 타이머(
setInterval
)와 같은 로직은 클라이언트에서만 동작하며, 이는 서버에서는 실행되지 않습니다. - 브라우저가 Hydration을 완료하기 전에 상태 업데이트가 발생하면 불일치가 생깁니다.
내 해석 : 서버에서는 useEffect가 실행이안되서 항상 currentIndex가 0인데, 클라이언트에서는 5초마다 계속 바뀌닌까 생기는 에러
- 타이머(
해결 시도-> 중요한 것은 currentIndex
의 서버측과 클라이언트측의 불일치
서버와 클라이언트 간의 초기 상태 동기화가 필요
좀 더 탐색
이 경고는 React가 클라이언트에서 Hydration 과정 중에 서버에서 생성한 HTML과 일치하지 않는 DOM을 발견했을 때 발생하는 에러
내 해석: 서버에서 에러를 반환하는게 아니라, 서버는 html만들고 끝 신경 안씀. 즉 만약 currentIndex가 달리진다 하더라도, 크게 문제가 안됨.
use client
선언으로 ssr렌더링이 되지 않아서 이 원인으로 hydration 에러가 발생하는 것은 이상함
- 서버는 html반환
- 클라이언트 에서 hydration시작
- 클라이언트 에서 hydration 중
- hydration이 끝남
backgroundColor
가 styled-components에서 CSS 속성으로 렌더링되지만, React DOM은 이를 DOM 속성으로 전달하려고 시도.- 서버에서 렌더링된 HTML에는
backgroundColor
속성이 없거나null
로 렌더링됨. - 클라이언트에서는 React가
backgroundColor
를 렌더링하려다 서로 다른 결과로 인해 Hydration 에러 발생.
최종원인 html에 없는 backgroundColor라는 custom props를 강제로 넘기면서 발생
styled-components와 React DOM의 상호작용에서 props가 DOM 속성으로 전달되면서 문제가 발생
특히 bakgroundColor라는 없는 props를 DOM에 넘기려고하면서 생기는 문제였음을 파악
더 근본적인 원인 styled-componets와 framer-motion간의 복합한 문제
- styled-components는 기본적으로 props를 CSS 생성기로만 사용하고, DOM으로 전달하지 않습니다.
- 예:
styled.div
를 사용할 때,props.bgColor
는 CSS에서만 사용되고 React DOM으로는 전달되지 않음.
- 예:
- 하지만, framer-motion의
motion.div
는 props를 DOM 속성으로 전달하는 기본 동작을 가짐.- 예:
motion.div
는 전달받은 props를 애니메이션 제어나 DOM 속성으로 그대로 전달하려고 시도.
- 예:
styled(motion.div)
는 styled-components와 framer-motion의 동작이 결합되면서, styled-components에서만 사용돼야 할 props가 React DOM으로 전달되는 부작용이 발생.
내 해석: 보통 styled-componet의 props는 css내부처리로만 잘 사용되는데, framer-motion이랑 엮어서 사용하다보니 framer-motion의 경우 DOM에 props를 작성하게 되면서 생긴 문제같음. 왜냐하면 애니메이션이다보니 직접 DOM을 조작해야해서 기본적으로 DOM을 조작하기위해 props를 넘기는듯.
해결
에러 발생 시
구분 | 서버 HTML 렌더링 결과 | React 가상 DOM | 클라이언트 DOM |
---|---|---|---|
bgColor | null |
#FFD700 |
없음 (DOM 속성으로 포함되지 않음) |
style | background-color: #FFD700 (CSS로 처리됨) |
backgroundColor: #FFD700 (CSS로 처리됨) |
background-color: #FFD700 (CSS로 처리됨) |
해결 후
구분 | 서버 HTML 렌더링 결과 | React 가상 DOM | 클라이언트 DOM |
---|---|---|---|
$backgroundColor | 없음 (DOM 속성으로 전달되지 않음) | 없음 (React DOM에서 props로 처리되지 않음) | 없음 (DOM에 포함되지 않음) |
style | background-color: #FFD700 (CSS로 처리됨) |
backgroundColor: #FFD700 (CSS로 처리됨) |
background-color: #FFD700 (CSS로 처리됨) |
// 문제 해결전 props.bgColor사용
const Slide = styled(motion.div)`
...
background-color: ${(props) =>
props.bgColor || "#f5f5f5"};
font-size: 24px;
`;
// 문제 해결 후 props.$backgroundColor로 변경
const Slide = styled(motion.div)`
...f
background-color: ${(props) =>
props.$backgroundColor || "#f5f5f5"}; /* $로 프롭스를 CSS 처리 */
font-size: 24px;
`;
배운점
- Hydration 개념 및 SSR의 작동 원리 심화 이해
- SSR에서 서버가 렌더링한 HTML과 React의 가상 DOM을 동기화하는 과정에서 발생할 수 있는 Hydration 에러의 원인과 동작 원리를 구체적으로 이해함.
- 특히, 서버에서 HTML 반환 후 클라이언트에서 동적 상태가 추가되면서 발생하는 불일치 문제에 대한 디버깅 접근법을 체득.
- 라이브러리 간 상호작용에서 발생하는 복합적 문제 해결 경험
- styled-components와 framer-motion의 기본 동작 차이를 분석하여, props 전달 방식의 차이가 DOM 속성 충돌로 이어지는 원리를 파악.
- 로그 의존도가 낮은 문제 디버깅 경험
- 명확한 에러 로그가 없더라도 렌더링 과정 분석 및 개념 기반 접근으로 원인을 추론하고 해결책을 도출함.
- 이 과정에서 문제 분석과 시스템적인 사고 능력 강화.