이전 블로깅에서 _app.tsx와 _document.tsx에 대해 알아보고 설정하는 내용을 썼다.
그런데 분명히 설정을 했는데도 불구하고, RecoilRoot를 설정해야 한다는 에러가 계속 발생했다.
처음에는 뭐가 문제인지 몰랐다. 리코일과 리액트쿼리 홈페이지, 그리고 깃허브에 들어가서 example 코드를 보고 뭐가 잘못됐는지 살펴봤는데... 잘못된 부분은 없어보였다. 아무리 코드를 고쳐도 해결되지 않았다.
root에 리코일과 리액트쿼리를 설정하라고 해서 가장 먼저 실행된다는 _app.tsx에 설정한 것인데..!
./pages/_app.tsx라는 경로가 잘못된 걸까 싶어서 넥스트 doc도 봤지만 문제없어보였다.
그러다 _app.tsx 자체가 인식되지 않는 것 같다는 생각이 들었다. 그래서 이번에는 react query를 사용해봤는데 마찬가지로QueryClientProvider를 설정하라는 에러가 발생하는 것을 볼 수 있었다.
그래서 또 다시 넥스트 doc을 봤다.
루트 레이아웃은 디렉터리의 최상위 수준에서 정의되며 app모든 경로에 적용됩니다. 이 레이아웃을 사용하면 서버에서 반환된 초기 HTML을 수정할 수 있습니다.
Migrating from the pages directory: The root layout replaces the _app.js and _document.js files.
_app.tsx, _document.tsx 대신 layout.tsx를 써야한다.
export const metadata: Metadata = {
title: "나들이",
description: "태그만 몇개 선택하면 여행계획 끝! 태그 기반 k-여행 추천 서비스",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="ko" className={gothic.className}>
<body>
<Recoil>
<ReactQuery>
<StyledComponentsRegistry>{children}</StyledComponentsRegistry>
</ReactQuery>
</Recoil>
</body>
</html>
);
}
이때 layout.tsx에서 바로 상태관리 provider를 등록하면 에러가 나온다. server 컴포넌트에서(메타태그를 사용하고있는) "use Client" 를 같이 쓸 수 없는 듯...
Recoil.tsx, ReactQuery.tsx 이렇게 각각 children을 받는 컴포넌트로 만들어서 일종의 슬롯을 만들어 처리해줘야한다.
next.js에서 기본적으로 모든 컴포넌트는 server 컴포넌트이다.
서버 전용에서 클라이언트 부분으로 경계를 넘나드는 컷오프 지점을 정의합니다. 파일에 "클라이언트 사용"이 정의되면 하위 컴포넌트를 포함하여 파일로 가져온 다른 모든 모듈은 클라이언트 번들의 일부로 간주됩니다.
- "use client" 지시문은 임포트하기 전에 파일 맨 위에 정의해야 합니다.
- 모든 파일에 "use client"를 정의할 필요는 없습니다. 클라이언트 모듈 경계는 "진입점"에서 한 번만 정의하면 되며, 이 경계로 가져온 모든 모듈은 클라이언트 컴포넌트로 간주됩니다.
상황 | server component | client component |
---|---|---|
fetch data | o | x |
서버 리소스에 접근(직접) | o | x |
민감한 정보를 서버에 보관(액세스 토큰, API 키 등) | o | x |
server/Reduce client-side에 높은 종속성을 가진 경우 | o | x |
상호작용 및 이벤트 리스너(onClick(),onChange()등) 추가 | x | o |
상태 혹은 Lifecycle 사용(useState(), useReducer(),useEffect(), 등) | x | o |
브라우저 API 사용 | x | o |
state, effect 또는 브라우저 API를 사용하는 hook 사용 | x | o |
React 클래스 구성 요소 사용 | x | o |
아래는 예시이다. client 컴포넌트에서 children으로 server 컴포넌트를 받도록 해 사용한다!
'use client'
import { useState } from 'react'
export default function ExampleClientComponent({
children,
}: {
children: React.ReactNode
}) {
const [count, setCount] = useState(0)
return (
<>
<button onClick={() => setCount(count + 1)}>{count}</button>
{children}
</>
)
}
감사합니다. 이런 정보를 나눠주셔서 좋아요.