Next.js
Next.js에서 에러 페이지를 볼 때 먼저 확인할 로그
Next.js 프로덕션 서비스에서 에러 페이지가 보일 때 실제 에러가 뭔지 찾기 위해 로그를 읽고 원인을 파악하는 방법을 정리했다.
실제 서비스 중인 Next.js 사이트에서 갑자기 에러 페이지가 보인다면, 사용자는 "뭐가 잘못된 거야?"라고 알려주지만, 개발자로서는 어디를 봐야 할지 모를 수 있다. 로그를 체계적으로 찾아보면 대부분의 문제는 빠르게 해결된다.
서버 로그 확인
Next.js 서버가 뭘 실행하고 있는지, 에러가 뭔지 봐야 한다:
# 로컬에서 프로덕션 빌드 후 실행
rm -rf .next
npm run build
NODE_ENV=production npm start
# 콘솔 출력을 주의 깊게 본다
# 에러가 있으면 스택 트레이스가 나타난다
Docker 컨테이너 환경
# 컨테이너의 로그 확인
docker logs <container_id>
# 로그를 계속 추적
docker logs -f <container_id>
# 로그를 파일로 저장
docker logs <container_id> > logs.txt
PM2로 실행 중인 경우
# 현재 실행 중인 프로세스 확인
pm2 list
# 로그 확인
pm2 logs
pm2 logs --lines 100 # 최근 100줄
pm2 logs --err # 에러 로그만
# 특정 앱의 로그
pm2 logs my-app
시스템 저널(journalctl)
# systemd로 관리되는 경우
sudo journalctl -u nextjs -n 100 # 최근 100줄
sudo journalctl -u nextjs -f # 실시간 추적
# 에러 레벨만
sudo journalctl -u nextjs -p err
에러 메시지 읽기
실제 에러가 나면 이렇게 보인다:
Error: Cannot find module 'sharp'
at Function.Module._resolveFilename (internal/modules/loader.js:1093:17)
at Function.Module._load (internal/modules/loader.js:949:21)
읽어야 할 부분:
- 에러의 첫 줄이 핵심 (여기서는
Cannot find module 'sharp') - 어느 파일에서 발생했는가?
- 스택 트레이스는 어디에서 시작했는가?
빌드 타임 에러 vs 런타임 에러
빌드 타임 에러 (배포 시)
npm run build
# 출력:
# TypeError: Cannot read property 'slice' of undefined
# at pages/api/users.js:25:15
# 이는 빌드 중 getStaticProps나 getServerSideProps에서 데이터를 못 가져왔다는 뜻
런타임 에러 (사용자가 페이지 접속 시)
# 서버 로그:
# Error: ReferenceError: window is not defined
# at pages/blog/[id].js:10:5
# 이는 서버에서 클라이언트 API(window, document)를 사용했다는 뜻
흔한 에러와 해결책
1. "Cannot find module"
# 원인: 필수 패키지가 설치되지 않음
# 해결:
npm install sharp # 또는 필요한 패키지
npm ci # 정확한 버전으로 다시 설치
rm -rf node_modules && npm install # 완전 재설치
2. "Port 3000 is already in use"
# 원인: 다른 프로세스가 포트를 사용 중
# 해결:
lsof -i :3000 # 포트 사용 프로세스 확인
kill -9 <PID> # 강제 종료
# 또는 다른 포트로
PORT=3001 npm start
3. "window is not defined"
// 문제 코드
export default function Page() {
const height = window.innerHeight; // 서버에서 실행되므로 에러
return <div>{height}</div>;
}
// 해결: useEffect 사용
import { useEffect, useState } from 'react';
export default function Page() {
const [height, setHeight] = useState(0);
useEffect(() => {
setHeight(window.innerHeight);
}, []);
return <div>{height}</div>;
}
4. "getServerSideProps 실패"
// 문제: API 호출 실패
export async function getServerSideProps() {
const data = await fetch('https://api.example.com/data');
return { props: { data } };
}
// 해결: 에러 처리
export async function getServerSideProps() {
try {
const res = await fetch('https://api.example.com/data');
if (!res.ok) throw new Error(`API returned ${res.status}`);
const data = await res.json();
return { props: { data } };
} catch (error) {
console.error('getServerSideProps error:', error);
return { notFound: true }; // 404 페이지 표시
}
}
에러 페이지 커스터마이징
기본 에러 페이지
// pages/500.js
export default function Error() {
return (
<div>
<h1>500 - 서버 에러가 발생했습니다</h1>
<p>관리자에게 문의해주세요.</p>
</div>
);
}
getStaticProps 실패 처리
// pages/products/[id].js
export async function getStaticProps({ params }) {
try {
const product = await fetchProduct(params.id);
if (!product) return { notFound: true };
return { props: { product }, revalidate: 60 };
} catch (error) {
console.error('getStaticProps error:', error);
// 빌드는 계속 진행하되, 해당 페이지는 나중에 생성
return { revalidate: 10 };
}
}
외부 서비스 로그
Vercel 배포
# Vercel 대시보드에서 로그 확인
# 1. Project → Deployments
# 2. 최근 배포 클릭
# 3. "Functions" 탭에서 서버 로그 확인
# 또는 CLI에서
vercel logs production
클라우드 로깅 서비스
# Google Cloud Logging
gcloud logging read "resource.type=cloud_run_revision" --limit 50 --format json
# AWS CloudWatch
aws logs tail /aws/lambda/nextjs-api --follow
에러 메시지 로깅 개선
// lib/errorLogger.js
export function logError(error, context = {}) {
const timestamp = new Date().toISOString();
const message = `[${timestamp}] ${error.message}`;
const stackTrace = error.stack;
console.error(message, stackTrace, context);
// 선택적: 외부 서비스로 전송 (Sentry, LogRocket 등)
// sentryClient.captureException(error, { extra: context });
}
// pages/api/data.js
try {
const data = await fetchData();
return res.json(data);
} catch (error) {
logError(error, { endpoint: '/api/data', method: req.method });
return res.status(500).json({ error: 'Internal Server Error' });
}
디버깅 팁
# 1. NODE_ENV 확인
echo $NODE_ENV
# 2. 빌드 아티팩트 확인
ls -la .next/
# 3. 환경 변수 확인
env | grep -E 'NODE|PORT|DATABASE'
# 4. 프로세스 상태 확인
ps aux | grep node
# 5. 디스크 공간 확인
df -h
Next.js 에러는 보통 명확한 에러 메시지를 주므로, 로그를 집중해서 읽으면 원인을 빠르게 찾을 수 있다. 배포 후 처음 몇 분은 로그를 주시하는 습관이 좋다.