이번에도 next.js 공식 문서를 공부하다가 데리고 왔다.
서버, 클라이언트 컴포넌트에 대해 조금 더 심층 공부해볼 예정 !

지금까지 프론트 공부하면서 매 시간마다 본
⬇️ 얘는 SEO 관련 세미나 준비 때 봤던 거 같고
- Server Side Rendering (SSR) vs Client Side Rendering (CSR)
⬇️ 얘는 오늘 next.js 공식문서에서 처음 봤다
- Server Component vs Client Component
둘이 똑같은 건 줄 알았는데 조금은 차이점이 있다고 한다?
(참고1 : https://f-lab.kr/insight/react-server-components-vs-ssr?gad_source=1&gclid=Cj0KCQjwsaqzBhDdARIsAK2gqnemvky3_9cOzvW3gRByc0bTPskIFKZnUPazRkcX6YrI5_zmkk-HOpgaAqLIEALw_wcB)

(참고2 :https://amaran-th.github.io/React/[Next.js]%20Server%20Component/)

SEO 관련 세미나에서 SSR은 다뤘기 때문에 이번에는 컴포넌트에 대해 다뤄볼 예정이다!
시작 -
Next.js 13부터 App Router가 등장하면서 pages/ 라우터보다 강력한 기능이 생겼는데 여기서 핵심적인 개념이 바로 Server Client, Client Component이다!
우선 Next.js의 기본은 Server Component이다.
즉, 아무 설정을 안 하면 다 서버에서 렌더링 됨!
useState), 이벤트(onClick)가 없음 // 기본값: Server Component
import { getPost } from '@/lib/data'
export default async function Page() {
const post = await getPost(1)
return <h1>{post.title}</h1>
}
=> DB나 API를 호출해도 API 키가 외부로 새지 않고, 불필요한 자바스크립트도 브라우저로 가지 않아 성능이 훨씬 좋음 !
서버 컴포넌트 안에서는 이벤트 핸들러를 직접 쓸 수 없기 때문에
브라우저에서 동작해야 하는 부분만 따로 분리해서 use client를 선언해준다!
'use client'
import { useState } from 'react'
export default function LikeButton() {
const [count, setCount] = useState(0)
return <button onClick={() => setCount(count + 1)}>❤️ {count}</button>
}
=> 브라우저 JS 번들에 포함되고 유저가 클릭하면 실시간으로 상태가 바뀌는 부분이다 !
실제 프로젝트에서는 무조건!! 둘을 섞어서 쓸 수밖에 없는 일이 생긴다.
ex. 서버에서 글 데이터 불러오기 + 클라이언트에서 좋아요 버튼만 반응형으로 생성
// app/post/[id]/page.tsx (Server Component)
import LikeButton from '@/app/ui/LikeButton'
import { getPost } from '@/lib/data'
export default async function Page({ params }) {
const post = await getPost(params.id)
return (
<article>
<h1>{post.title}</h1>
<p>{post.content}</p>
<LikeButton likes={post.likes} />
</article>
)
}
=> LikeButton은 데이터를 받아 브라우저 쪽에서만 상태를 관리
use client 남용 금지use client를 적는 순간, 그 파일 이하로 import된 모든 코드가 브라우저 번들에 포함된다.
즉,
layout.tsx에 use client를 넣으면 -> 네비게이션, 푸터, 페이지 전부 클라로 넘어감 좋은 예시
// app/layout.tsx (Server)
import Logo from './Logo'
import Search from './Search'
export default function Layout({ children }) {
return (
<nav>
<Logo />
<Search />
</nav>
)
}
// app/Search.tsx (Client)
'use client'
export default function Search() { /* input, useState 등 */ }
-> 이렇게 Search만 Client로 작성하는 것이 좋다. (Logo는 client 사용할 필요가 없으니까!)
나쁜 예시
// layout.tsx
'use client'
-> 이렇게 되면 전체가 클라이언트로 변해서 번들 사이즈가 어어엄청나게 커지게 된다.
: 데이터를 서버에서 미리 준비해두고, 클라이언트는 필요한 상태만 넘기는 구조로 만들자!
DB -> Server Component -> Client Component
예를 들어 API 키가 필요한 데이터 호출은 서버에서 해야만 안전하다.
// lib/data.ts
import 'server-only'
export async function getSecretData() {
const res = await fetch('https://api.com', {
headers: { authorization: process.env.API_KEY },
})
return res.json()
}
import 'server-only'를 추가해두면 클라이언트에서 잘못 import 할 경우 빌드 에러로 막아줄 수 있다!
⭐⭐⭐ 모든 걸 클라로 돌리는 게 아니라 정적/데이터는 서버, 상호작용은 클라로 진행하면 된다 ⭐⭐⭐
공부를 하다가 알게 된 건데 원래 리액트는 애플리케이션을 렌더링 하는 주체가 client였다고 한다. 그런데 갑자기? 
next13부터는 app 디렉토리가 도입됨에 따라 Server / Client component 개념이 추가되었다고 한다.
그러니까 pages -> app으로 바뀜으로써 (근데 이것도 너무 큰 변화 아닌가? 사실 알못이어서 체감은 잘 못하겠다) 또 공부해야 될 게 생긴 거 아니야 .. ?
next에 대해 이야기(악플)했던 리드님의 세미나가 불현듯 뇌리를 스쳤다.
나 프론트.. 하는 게 맞는 걸까? 이대로 영원히 도태되는 것 아닐까..? 라는 걱정이 앞섰다.
현업에 계신 프론트 개발자분들은 정말 대단하다! 트렌디한 삶을 살아야 해 . .
걱정과 함께 마칩니다.
Next.js 문서 공부하고 영주님 블로그까지 보니 학습률이 2배 완성 -⭐
공식 문서는 살짝쿵 이해하기 어려웠는데 영주님 블로그보니 완전 바로 이해됐슴다 !