export default function Page() {
return (
<h1>앱 라우터 공부 2일차 🤓</h1>
);
}
- React 18v부터 새롭게 추가된 새로운 유형의 컴포넌트.
- 오직 서버 측에서만 실행되는 컴포넌트. ➡️ 브라우저에서는 실행X
한 페이지에 포함되는 여러 컴포넌트들 중에 상호작용이 없어서 서버 측에서만 실행되면 되는 컴포넌트들을 서버 컴포넌트
로, 사용자와의 상호작용으로 Hydration이 필요한 컴포넌트들은 서버와 브라우저 모두에서 실행되어야 하기 때문에 기존의 클라이언트 컴포넌트
로 분류하면 된다.
서버 컴포넌트
는 서버 측에서 사전 렌더링을 진행할 때 딱 한 번만 실행되며, 클라이언트 컴포넌트
는 사전 렌더링과 Hydration 진행 시 모두 실행된다.
페이지의 대부분을 서버 컴포넌트
로 구성하고, 꼭 필요한 경우에만 클라이언트 컴포넌트
를 사용하는 것이다.
➕ 앱 라우터에서는 기본적으로 모든 컴포넌트가 서버 컴포넌트로 작동한다!
서버 컴포넌트를 클라이언트 컴포넌트로 만들기 위해서는,
파일의 최상단에 "use client"
를 작성해주면 된다.
우리 프로젝트에서는 검색바 컴포넌트가 사용자와의 상호작용이 필요한 컴포넌트이므로, 해당 키워드를 사용해 클라이언트 컴포넌트
로 만들어준다. 그럼 위와 같이 훅을 사용해서 상태를 관리할 수 있다.
1️⃣ 서버 컴포넌트에는 브라우저에서 실행될 코드가 포함되면 안된다.useState(), useEffect()와 같은 훅들은 클라이언트 컴포넌트에서만 사용 가능하다. 따라서 서버 컴포넌트에서는 사용 불가!
또한 브라우저에서 실행되는 기능을 담고 있는 라이브러리도 사용 불가!
2️⃣ 클라이언트 컴포넌트는 클라이언트에서만 실행되는 것은 아니다.서버 컴포넌트가 서버 측에서만 실행되는 컴포넌트니까, 클라이언트 컴포넌트도 클라이언트 측에서만 실행되는 컴포넌트❓ 이건 잘못된 정보다.
클라이언트 컴포넌트는 단지 사전 렌더링 과정에서 서버 컴포넌트와 차이가 있을 뿐! 서버와 클라이언트에서 모두 실행된다.
3️⃣ 클라이언트 컴포넌트에서 서버 컴포넌트를 import 할 수 없다.
2번에서 언급한 내용과 관련이 있다. 서버 컴포넌트 코드는 사전 렌더링 과정 중 서버 측에서 한 번만 실행되지만, 클라이언트 컴포넌트 코드는 사전 렌더링 과정 중 서버 측에서 한 번, Hydration 과정에서 한 번, 이렇게 총 두 번 실행된다.
Hydration 과정에서 실행될 때 클라이언트 컴포넌트 코드에 있는 서버 컴포넌트는 실행되지 않기 때문에 오류가 발생하게 되고, 따라서 클라이언트 컴포넌트에서 서버 컴포넌트를 import 할 수 없는 것이다.
하지만 Next.js는 이런 경우 "자동으로 서버 컴포넌트를 클라이언트 컴포넌트로 변경"해, 오류가 발생하는 것을 막는다❗️
그러나 이 방법보다는, 클라이언트 컴포넌트에 서버 컴포넌트를 children으로 넘겨주는 방식을 더 추천한다🫡 이 때는 서버 컴포넌트를 클라이언트 컴포넌트로 자동으로 변경하지 않기 때문 ~
4️⃣ 서버 컴포넌트에서 클라이언트 컴포넌트에게 직렬화되지 않는 Props는 전달할 수 없다.
하지만 Javascript의 함수는 직렬화가 불가능하다. 그래서 이러한 값들은 props로 전달할 수 없다!
더 구체적으로 알아보기 위해 사전 렌더링 과정을 파헤쳐보자. 사전 렌더링이 시작되면 모든 컴포넌트들이 동시에 실행되는 것이 아니라, 서버 컴포넌트들만 먼저 실행되게 된다.
서버 컴포넌트들의 실행이 끝나면 RSC Payload
라는 json과 비슷한 형태의 문자열이 생성되고, 이후에 클라이언트 컴포넌트들의 실행과 함께 HTML 페이지가 완성된다. 그리고 이 RSC Payload
에는 서버 컴포넌트의 모든 정보들이 포함되어 있다.
만약 이 때 서버 컴포넌트가 props 값으로 함수를 클라이언트 컴포넌트에게 전달하고 있다면, 전달하는 함수도 직렬화를 통해 RSC Payload
에 포함되어야 한다. 하지만 Javascript 함수는 직렬화가 불가능❗️
따라서 서버 컴포넌트에서 클라이언트 컴포넌트로 직렬화가 불가능한 값을 props로 전달하는 것은 불가능하다.