Antd FOUC

이재호·2023년 4월 10일
0

Antd FOUC

프론트엔드를 개발할 때 디자인 라이브러리를 사용할 지 말지에 대한 고민에 빠지곤 한다. 어느정도 규모가 있는 기업이라면 내부에서 디자인 라이브러리를 직접 개발하겠지만 그렇지 않다면 늘 고민이 되는 부분이다.

예전에는 직접 모든 디자인을 Less활용해서 컴포넌트화 해서 사용해본 적이 있었는데, css에서 정말 정말 많은 공수가 들어간다.

이번에는 대세라고 하는 Antd 한 번 써보기로 결정했다. 과거에 회사 사이드 프로젝트에서 Antd 사용해본 적이 있었는데, 경험이 나쁘지 않았다.

Antd를 사용하고 배포 후 처음으로 맞이하게 된 문제는 바로 FOUC였다. 프레임워크는 SSR 적용된 Next를 사용했다. 따로 설정을 하지 않고 Antd를 js에서 사용하니 FOUC가 심하게 발생했다. 해결하기 위해서 이런 저런 정보를 찾아보았지만 결국 해답은 공홈에서 얻을 수 있었다.

디펜던시 설치

다음의 디펜던시가 필요했다.

npm install ts-node tslib --save-dev

tsconfig.node.json

{
  "compilerOptions": {
    "strictNullChecks": true,
    "module": "NodeNext",
    "jsx": "react",
    "esModuleInterop": true
  },
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"]
}

기존에 CNA하면 tsconfig.json은 들어있는데, prebuildpredev 에서 사용하기 위해 위와 같은 타입스크립트 설정파일을 따로 하나 더 만들어준다.

theme/index.tsx

Antd의 ConfigProvider 를 노드에 래핑해주는 함수를 하나 만들어준다. 이 함수는 테마를 커스터마이징 하기 위해서 사용된다.

import React from "react";
import { ConfigProvider } from "antd";

const backgroundColor = "#f8e0f1";
const borderColor = "#FFE5CA";
const secondaryBorderColor = "#FFE5CA";
const pointColor = "#E74646";

const withTheme = (node: JSX.Element) => (
	<>
		<ConfigProvider
			theme={{
				token: {
					colorPrimary: pointColor,
					colorBgBase: "white",
					fontFamily: "Noto Sans KR",
				},
			}}
		>
			<ConfigProvider
				theme={{
					token: {
						colorBorderSecondary: secondaryBorderColor,
						colorBorder: borderColor,
					},
				}}
			>
				{node}
			</ConfigProvider>
		</ConfigProvider>
	</>
);

export default withTheme;
export { backgroundColor, pointColor, borderColor, secondaryBorderColor };

scripts/genAntdCss.tsx

실행하면 output경로에 Antd css파일을 생성해주는 스크립트를 작성해준다. 위에서 작성한 withTheme을 같이 활용해서 추후에 테마를 커스터마이징하는데 도움될 수 있도록 해준다.

// scripts/genAntdCss.tsx
import { extractStyle } from "@ant-design/static-style-extract";
import withTheme from "../theme";

import fs from "fs";

const outputPath = "./public/antd.min.css";

const css = extractStyle(withTheme);

fs.writeFileSync(outputPath, css);

package.json

다음으로는 패키지.json에 predevprebuild 스크립트를 아래와 같이 작성해, build dev 스크립트 실행 시 antd css파일을 경로에 생성해줄 수 있도록 작성해준다.

// package.json
{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "predev": "ts-node --project ./tsconfig.node.json ./scripts/genAntdCss.tsx",
    "prebuild": "ts-node --project ./tsconfig.node.json ./scripts/genAntdCss.tsx"
  }
}

_app.tsx

_app.tsx 파일에도 컴포넌트를 withTheme 함수로 래핑해준다.

export default function App({ Component, pageProps }: AppProps) {
	return withTheme(
		<MainLayout>
			<Component {...pageProps} />
		</MainLayout>
	);
}

_document.tsx

document 에서 Head 내부에 빌드타임에 생성될 /antd.min.css 파일을 임포트 해준다.

export default function MyDocument() {
	return (
		<Html lang="en">
			<Head>
				<link href="/antd.min.css" rel="stylesheet" />
			</Head>
			<body>
				<Main />
				<NextScript />
			</body>
		</Html>
	);
}

위와 같이 작성하면 Head에서 antd CSS를 불러오기 때문에 FOUC가 많이 개선된다.

고찰

그럼에도 불구하고 특정한 환경에 따라서 완전한 FOUC의 개선은 어려워보인다. 완전한 사용자 경험의 개선을 위해서 다른 방법을 찾아보아야겠다.

profile
복세편살

0개의 댓글