Mantine이란?
Mantine은 React에서 사용할 수 있는 UI Component 라이브러리이다. 2023년 7월 기준 v6까지 출시되었으며, 지속적으로 업데이트되고 있다. Chakra UI와 컨셉이 굉장히 유사한데, 깔끔하고 직관적인 디자인에 풍부한 컴포넌트, 다양하고 유용한 훅 제공 등, 단순 UI 컴포넌트뿐 아니라 종합 라이브러리 역할도 겸하는 것 같다.
여러 프레임워크/라이브러리들을 지원하고 있고, 최근 많이 사용되는 Next.js 환경에서 Mantine을 사용하면서 겪은 Layout Shift 이슈를 해결한 경험을 공유하고자 한다.
Next.js SSR 환경에서 발생하는 Layout Shift
Mantine은 내부적으로 Emotion을 이용해 스타일링이 되어 있다. 따라서 MantineProvider를 가져오기만 하면 Emotion cache를 자동으로 생성한다. 그런데 이게 SSR 환경에서는 기본설정으로 잘 동작하지 않는다. 이건 Emotion 자체의 이슈이기 때문에 Emotion을 사용하여 스타일링하는 Mantine이나 MUI 등 여러 라이브러리들이 공통으로 겪는 문제이다.
왜 그런 현상이 발생하는지는 검색해보니 참고할만 한 글이 있어서 링크해본다. 해당 내용도 발췌해봤다.
- Emotion의 여러 인스턴스가 한 번에 로드됩니다. 이는 여러 인스턴스가 모두 동일한 버전의 Emotion인 경우에도 문제를 일으킬 수 있습니다.
- 컴포넌트 라이브러리는 스타일이 삽입되는 순서를 완전히 제어할 수 없는 경우가 많습니다.
- Emotion의 SSR지원은 리액트 17과 리액트 18에서 다르게 작동합니다. 이는 리액트 18의 스트리밍 SSR과의 호환성을 위해 필요했습니다.
어찌되었건 이 문제로 인해 초기 로딩에서 Layout Shift가 발생한다. CSS가 제대로 로드되지 않은 상태에서 먼저 깨진 레이아웃이 보이고, 그 다음에 스타일이 로드되면서 자리를 찾아간다. 이것 자체가 사이트 성능에도 부정적인 영향을 끼치고, UX에도 마찬가지로 좋지 않다.
다행히도 Mantine에서 가이드를 제공해주고 있어서 그걸 참고하면 된다.
적용해보기
링크는 아래 참고 자료 란에 있다. 참고해서 바로 적용해보자.
// pages/_document.tsx
const stylesServer = createStylesServer(emotionCache());
class _Document extends Document {
static async getInitialProps(ctx: DocumentContext) {
const initialProps = await Document.getInitialProps(ctx);
return {
...initialProps,
styles: (
<>
{initialProps.styles}
<ServerStyles
html={initialProps.html}
server={stylesServer}
key="styles"
/>
</>
),
};
}
render() {
return (
<Html lang="ko">
<Head>
...
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
// pages/_app.tsx
import { emotionCache } from "../src/emotionCache";
...
<MantineProvider
...
emotionCache={emotionCache()}
>
// src/emotionCache.ts
import { createEmotionCache, EmotionCache } from "@mantine/core";
let cache: EmotionCache | undefined;
export const emotionCache = () => {
if (!cache) {
cache = createEmotionCache({
key: "example-cache-key",
prepend: false,
});
}
return cache;
};
이렇게 적용하면 Emotion cache를 SSR 환경에서 정상적으로 이용할 수 있다.
참고 자료
'Frontend' 카테고리의 다른 글
Next.js에서 recoil-persist 사용하기 (0) | 2023.07.11 |
---|---|
Cloudflare Pages는 게임 체인져가 될 수 있을까? (0) | 2022.06.18 |
[해결] 2022-04-03 CRA로 Chakra UI 매뉴얼 세팅했을 때 오류 발생하는 이슈 (0) | 2022.04.03 |
Chakra UI 간단 사용기 (0) | 2022.03.09 |