Next.js
React Server Component 버그는 서버에서만 터진다
로컬 개발 환경에서는 보이지 않는 에러가 배포 후 나타날 때 확인할 것들.
React Server Component(RSC)는 강력하지만 까다롭다. 개발 중에는 완벽해도 배포되면 터진다. 특히 서버에서만 실행되는 코드의 에러는 로컬에서 보기 어렵다.
먼저 제외할 원인들
클라이언트 사이드 문제가 아닌지 먼저 확인한다.
- 브라우저 개발자 도구 콘솔에 에러가 있는가?
- 네트워크 탭에서 모든 요청이 200 OK인가?
- 캐시 문제는 아닌가? (하드 새로고침 시도)
이 셋이 정상이면, 서버에서의 문제다.
서버 빌드 로그 확인
npm run build
빌드 단계가 성공했는가? RSC는 빌드 타임에 서버 코드를 분석한다. 만약 경고(warning)가 있으면 무시하기 쉽지만, 런타임에 에러가 될 수 있다.
특히 이런 메시지를 찾자:
Failed to serialize data in Async RSC
Dynamic import() is not allowed in RSC
Module not found in server context
Server Component vs Client Component
RSC 안에서 클라이언트 API를 쓰려고 하면 에러난다.
// ❌ 에러: Server Component에서 브라우저 API 사용
export default function Page() {
const theme = localStorage.getItem('theme'); // 불가능
return <div>{theme}</div>;
}
// ✅ 올바름: 'use client' 선언 후 클라이언트 API 사용
'use client';
export default function Page() {
const theme = localStorage.getItem('theme');
return <div>{theme}</div>;
}
만약 API 호출, 환경변수 접근, DB 쿼리가 필요하면 서버 컴포넌트에서 한다. 하지만 상태(useState), 이벤트, 브라우저 API가 필요하면 클라이언트 컴포넌트로 바꾼다.
상태 이름과 렌더링 조건
서버에서는 상태가 없다. 매 요청마다 새로 렌더링한다.
// ❌ 에러: Server Component에서 useState 사용
export default function Counter() {
const [count, setCount] = useState(0); // 불가능
return <div>{count}</div>;
}
// ✅ 올바름: 클라이언트 컴포넌트로 분리
'use client';
import { useState } from 'react';
export default function Counter() {
const [count, setCount] = useState(0);
return <div>{count}</div>;
}
만약 조건부 렌더링이 필요하면, 조건을 서버에서 판단하고 결과를 내려준다.
// Server Component: 로그인 상태 판단
export default async function Page() {
const user = await getUser(); // DB 쿼리
if (!user) {
return <Login />;
}
return <Dashboard user={user} />;
}
에러 로그 위치
배포 환경에서 Server Component 에러는 어디에 나타나는가?
- 빌드 로그:
npm run build중 발생하면 배포가 실패한다. - 서버 콘솔: 런타임 에러는
docker logs또는 배포 플랫폼의 로그에 나타난다. - 브라우저 콘솔: 아무것도 안 나타난다. (서버에서 발생한 에러는 클라이언트에서 보이지 않음)
배포 환경의 로그를 보는 게 가장 중요하다.
# Dokploy/Docker 환경
docker logs <container-name> --tail=100
# Vercel
vercel logs
비정상일 때 확인할 것
// 서버에서만 접근 가능한 것들
- DB 쿼리
- 파일 시스템 접근
- 환경변수 (NEXT_PUBLIC_ 제외)
- 비밀 키 (API 키, DB 암호)
- 외부 API 호출 (서버 사이드만)
이 항목들이 클라이언트 컴포넌트에서 사용되고 있지는 않는가?
배포 환경 특성 이해
로컬 개발 환경(npm run dev)에서는 Server Component 에러를 놓칠 수 있다. 하지만 프로덕션 빌드(npm run build)는 더 엄격하다.
# 로컬에서 프로덕션 빌드 테스트
npm run build
npm run start
이렇게 하면 배포 환경과 같은 조건에서 테스트할 수 있다.
예상되는 정상 상태
- 모든 Server Component 에러가 빌드 단계에서 캐치된다.
- 클라이언트가 보는 화면에는 에러가 없고, 서버 로그도 깔끔하다.
- API 응답이 모두 원하는 데이터를 포함한다.
마지막 점검
- 빌드 로그 확인: 경고나 에러가 없는가?
- 서버 로그 확인: 런타임 에러가 없는가?
- 'use client' 선언: 필요한 곳에는 있는가?
- 서버 전용 코드: DB, 환경변수, 파일 접근이 클라이언트로 누출되진 않았는가?
- 로컬 프로덕션 빌드 테스트:
npm run build && npm run start로 확인
Server Component 버그는 찾기 어렵지만, 로그를 읽고 체계적으로 접근하면 대부분 간단하다.