본문 바로가기
Web/Next.js

컴포넌트 속 컴포넌트 (import와 children의 차이)

by 가나닩 2024. 6. 6.

Next.js는 클라이언트 컴포넌트와 서버 컴포넌트를 둘다 사용할 수 있다. 컴포넌트를 분리 사용하다보면 import를 통해 불러와 필요한곳에 컴포넌트를 집어넣어 사용하게 되는데 서버 컴포넌트를 클라이언트 컴포넌트에서 가져와 실행하면 오류가 발생하는것을 알 수 있다.

 

 

1. 서버 컴포넌트와 클라이언트 컴포넌트

아래 링크에 자세한 설명이 작성되어있다.

 

Next.js의 use client와 use server

 

Next.js의 use client와 use server

Next.js는 React를 기반으로 한 프레임워크중 가장 대표적인 프레임워크이다. 클라이언트 사이드 렌더링과 서버 사이드 렌더링을 지원하여 양쪽의 특징을 선택적으로 사용할수 있다는것이 가장 큰

cstelladev.tistory.com

 

즉, 서버 컴포넌트는 서버에서 실행할 수 있는 코드(DB접근, 서버세션관리 등) 를 포함하고 있고 클라이언트 컴포넌트는 브라우저에서 실행할 수 있는 코드(useState등 상태관리, onClick같은 이벤트리스너 등)를 포함하고 있다.

 

 

2. 오류가 발생하는 이유 - import의 특징

위 설명처럼 각 컴포넌트는 실행 환경에 맞는 코드들을 포함하게 된다.

그런데 import는 컴포넌트의 소스 코드를 직접 포함한다. 다시말해 사용자 브라우저에서 서버 코드가 실행되도록 하는것이다.

// 에러 발생
"use client";

import TestServer from "./testServer";

export default function TestClient() {
    return (
        <div>
            <div>클라이언트 컴포넌트</div>
            <TestServer />
            <div>클라이언트 컴포넌트</div>
        </div>
    );
}

서버 컴포넌트를 import하여 사용하면 에러가 발생한다.

 

 

3. 사용하려면? - children의 특징

children이라는 prop으로 컴포넌트를 사용하면 보다 유연한 사용이 가능하다.

// layout.js
import TestClient from "./testClient"; // 클라이언트 컴포넌트를 import
import TestServer from "./testServer"; // 서버 컴포넌트를 import

export default function Layout() {
    return (
        <TestClient>
            <TestServer />
        </TestClient>
    );
}
//testClient.js
"use client";

export default function TestClient({ children }) {
    return (
        <div>
            <div>클라이언트 컴포넌트</div>
            {children}
            <div>클라이언트 컴포넌트</div>
        </div>
    );
}
//testServer.js
import { getServerSession } from "next-auth";
import { authOptions } from "nextauth 경로";

export default async function TestServer() {
    let session = await getServerSession(authOptions);

    return <div>{session.user.name}</div>;
}

 

클라이언트 컴포넌트에서 서버 컴포넌트를 사용했다.

 

children형식으로 컴포넌트를 사용할때는 props형태를 사용하게 된다. props로 전달되는 서버 컴포넌트는 쉽게말해 서버에서 실행 가능한 코드를 모두 제대로 실행한 결과값을 제공받는것이다.

 

 

4. children prop 사용 예시

children prop을 사용하면 유연한 컴포넌트 사용이 가능하므로 많은 부분에서 활용할 수 있다. 아래는 대표적인 예시이다.

import NavBar from "./navBar";
import ClientSessionProvider from "./clientSessionProvider";

export const metadata = {
    title: "title",
    description: "description",
};

export default function RootLayout({ children }) {
    return (
        <html lang="ko">
            <body>
                <ClientSessionProvider>
                    <NavBar />
                </ClientSessionProvider>
                {children}
            </body>
        </html>
    );
}
//clientSessionProvider.js
"use client";

import { SessionProvider } from "next-auth/react";

export default function ClientSessionProvider({ children }) {
    return <SessionProvider>{children}</SessionProvider>;
}

 

Next.js는 서버에서 동작할 수 있으므로 SEO에 유리하다. SEO에 유리한 웹페이지를 만들기 위해서는 검색엔진이 참조하는 metadata를 잘 관리할 필요가 있다. 그런데 모든 컴포넌트를 클라이언트 컴포넌트로 정의하면 메타데이터를 사용할 수 없다.

layout은 페이지의 최상단 컴포넌트이므로 metadata가 중요하 다. 여기서 SessionProvider같은 클라이언트 전용 컴포넌트를 사용하기 위해 layout자체를 클라이언트 컴포넌트로 정의해버리면 SEO의 이점을 포기해야한다.

이때 편법을 통해 클라이언트 전용 컴포넌트를 처리하는 js파일을 따로 만들고 children으로 해당 기능이 필요한 컴포넌트를 전달해줄 수 있다.

 

 

 

※ 상태관리, 이벤트리스너 등의 특수한 경우를 빼면 대부분은 서버에서 해결이 가능하다. session데이터 같은 경우에도 next-auth에서는 getServerSession을 제공하고 있으며 api요청 등도 클라이언트가 아닌 서버에서 처리할 수 있다. 서버사이드렌더링의 장점을 최대한 이용할 수 있어야한다.