Next.js 에 styled components를 적용하는 것 자체는 그렇게 어렵지 않았지만 어느정도 알고 있어야할 사전 지식이 있다.
아래 문서는 Next.js에서 제공하는 공식문서 중 css-in-js를 설정하는 방법들에 대해 다룬다.
https://nextjs.org/docs/app/building-your-application/styling/css-in-js#styled-components
문서 처음부터 아래와 같이 경고를 해주고 있다.
요약하자면, NextJS 13버전 이후로 react18의 서버컴포넌트와 같은 서버사이드렌더링 기법들이 많이 추가되었는데 그중에서 css-in-js는 서버 환경에서 동작하지 않는다는 말이다.
그렇다고 css-in-js를 사용하지 못하는 것은 아니다. 서버 컴포넌트에서 사용하지 못하는 것일 뿐 스타일을 사용하는 컴포넌트를 클라이언트 컴포넌트로 사용하면 사용할 수 있다.
다만, 이 방식으로 모든 컴포넌트를 클라이언트 컴포넌트로 만들어버리는 것은 서버사이드 렌더링의 장점들을 잃어버리는 것이므로 현재는 스타일 로직과 api등의 정보를 받아오는 데이터 로직을 분리하는 방식으로 해결할 수 있다.
( 현재도 css-in-js 를 ssr환경에서 사용할 수 있게 하는 노력은 현재진행형인듯 하다.)
각설하고, 간단하게 프로젝트를 만들고 next.js에 styled components를 적용시켜 보자.
npx create-next-app --typescript
위 명령어로 간단하게 next.js 프로젝트를 하나 만들어주자.
그리고 app 폴더 내에 registry.tsx라는 파일을 하나 만들고 와래와 같은 코드를 작성해준다.
// app/registry.tsx
"use client";
import React, { useState } from "react";
import { useServerInsertedHTML } from "next/navigation";
import { ServerStyleSheet, StyleSheetManager } from "styled-components";
export default function StyledComponentsRegistry({
children,
}: {
children: React.ReactNode;
}) {
// Only create stylesheet once with lazy initial state
// x-ref: https://reactjs.org/docs/hooks-reference.html#lazy-initial-state
const [styledComponentsStyleSheet] = useState(() => new ServerStyleSheet());
useServerInsertedHTML(() => {
const styles = styledComponentsStyleSheet.getStyleElement();
styledComponentsStyleSheet.instance.clearTag();
return <>{styles}</>;
});
if (typeof window !== "undefined") return <>{children}</>;
return (
<StyleSheetManager sheet={styledComponentsStyleSheet.instance}>
{children}
</StyleSheetManager>
);
}
이후 RootLayout 폴더에 아래와 같이 StyledComponentsRegistry 컴포넌트를 감싸주면 Next.js에서 styledComponents를 사용할 준비가 완료된다.
// app/layout.tsx
import StyledComponentsRegistry from "./registry";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
const componentType = typeof window === "undefined" ? "server" : "client";
console.log("layout", componentType);
return (
<html>
<body>
<StyledComponentsRegistry>{children}</StyledComponentsRegistry>
</body>
</html>
);
}
이제 아래와 같이 실제로 styled-components를 사용하면 잘 동작되는것을 알 수 있다.
// app/page.tsx
"use client";
import Image from "next/image";
import styles from "./page.module.css";
import styled from "styled-components";
export default function Home() {
const componentType = typeof window === "undefined" ? "server" : "client";
console.log("page", componentType);
return <Wrapper>asdfasdf</Wrapper>;
}
const Wrapper = styled.div`
color: blue;
`;
글의 초반부에 말했던 것처럼 현재 styled-componets는 서버에서 지원이 안되기 때문에 꼭!! "use clinet"를 붙여서 클라이언트 컴포넌트임을 명시해야 한다.
서버사이드 렌더링의 이점?
const componentType = typeof window === "undefined" ? "server" : "client";
console.log("page", componentType);
위 코드로 현재 코드가 작성되는 컴포넌트의 타입을 정할 수 있다.
"use client"로 작성한 page.tsx의 경우 아래와 같이 콘솔창에 찍힌다.
그리고 layout component는 서버에서만 콘솔이 찍히는것을 확인할 수 있다.
이런점을 이용해서 현재 서버사이드의 이점과 css-in-js를 사용하려면 로직을 잘 분리하는 것이 최선인 듯 하다..
'FrontEnd > React' 카테고리의 다른 글
[NextJs14] 글꼴 설정방법 ( google font ) (2) | 2024.03.04 |
---|---|
[React] TanStack(React-Query) DeepDive 해보기 (1) | 2024.02.23 |
[JEST,Recoil] jest에서 recoil사용하기 (0) | 2024.02.01 |
[storybook] viewport 설정 (1) | 2023.12.21 |
[REACT] storybook reset.css 적용 (0) | 2023.12.20 |