Next.js/렌더링/Lesson 04
Server Component — DB 직접 접근, 0KB 클라이언트 번들
40분·theory
이 챕터
1/5
TypeScript
Server Component — DB 직접 접근, 0KB 클라이언트 번들
💡 왜 배워야 할까요? — '서버에서 끝내고 HTML 만 보낸다' 가 기본값
🎯
Server Component 의 함수 자체는 **클라이언트 번들에 포함되지 않습니다** — 렌더링된 HTML 만 전송. 페이지 가중치가 극단적으로 줄어듭니다.
💼
DB·파일 시스템·환경변수에 직접 접근할 수 있습니다. 브라우저로 절대 새어나가지 않으니 API 키·시크릿을 안전하게 사용 가능.
⚡
fetch 가 같은 렌더링 안에서 자동 dedupe·캐시됩니다 — 같은 URL 호출이 여러 번 있어도 실제 네트워크 요청은 한 번.
🔗
Pages Router 의 `getServerSideProps`·`getStaticProps`·`SWR` 같은 데이터 패칭 추상화가 전부 사라집니다. 그냥 `await fetch()`.
📈
단점: `useState`·`onClick`·`useEffect` 같은 브라우저 hook 사용 불가. 그건 Client Component 영역.
🏢 실무에서는
codemaster40 의 `src/app/study/[category]/page.tsx` 도 Server Component 일 가능성이 높습니다. 학습 데이터 JSON 을 서버에서 읽어 HTML 로 그대로 렌더링하므로 초기 로딩이 빠르고, 클라이언트로 가는 JS 는 상호작용 부분(`useState` 가 있는 컴포넌트) 만입니다.
Server vs Client — 경계와 규칙
1. 기본값은 Server Component
파일 맨 위에 'use client' 가 없으면 자동으로 Server Component.
2. Server Component 의 능력
3. fetch 자동 dedupe + 캐시
같은 렌더링 안에서 같은 URL 을 여러 컴포넌트가 호출해도, 실제 fetch 는 한 번:
캐시 정책:
4. Server → Client 경계
- ▸Server 가 Client 를 import 해서 끼우는 건 OK.
- ▸Client 가 Server 를 import 해서 끼우는 건 ❌ (브라우저에서 DB 못 부르니까).
- ▸단, Server Component 를
children으로 받아서 Client Component 안에 끼우는 건 OK (composition).
💡 💡 Server Component 실전 5
1. async 컴포넌트는 Server 만 가능
Client 에 async 붙이면 빌드 에러. 데이터 패칭은 Server 에서, 결과를 props 로 Client 에 내려줘라.
2. 'use client' 는 전염되지 않는다
Server 가 Client 를 import 해도 부모는 여전히 Server. 경계가 명확.
3. Client → Server import 는 불가
Client Component 가 Server Component 를 import 해서 직접 끼우면 빌드 에러. 대신 children 으로 받아서 끼워라:
4. fetch 캐시 모드 4가지
5. 환경변수 — Server 는 다 보임, Client 는 NEXT_PUBLIC_ 만
Server Component 에 시크릿 박아도 브라우저로 안 새어나감.
⚡ 직접 실행해보기 — Server/Client 경계 시뮬레이션
각 컴포넌트가 어디서 실행될지, fetch 가 어디서 일어날지 시뮬레이션해봅니다.
✏️ JS 코드
📟 콘솔 출력
▶ 실행 버튼을 눌러보세요
⚠️ 브라우저 샌드박스에서 실행 — console.log()만 지원, alert/fetch 불가
확인 퀴즈
App Router 에서 Client Component 가 Server Component 를 직접 `import` 해서 JSX 로 끼우면?
먼저 읽으면 좋은 개념: 파일 컨벤션 — loading / error / not-found
다음 추천: 데이터 페칭 — fetch 캐시 정책 4가지