← 전체 글로 돌아가기

Next.js

Next.js 서버 액션이 로컬에서는 되는데 서버에서 실패할 때

환경 변수, 파일 경로, 패키지 의존성 차이로 인한 빌드 또는 실행 오류를 진단하는 방법.

로컬 vs 프로덕션 환경 차이

개발자 경험의 가장 답답한 부분이 바로 "내 컴퓨터에서는 되는데"이다. 특히 Next.js 서버 액션은 로컬에서는 잘 작동하는데 배포 후 실패하는 경우가 많다.

주요 원인:

  • 환경 변수가 다름
  • 파일 경로가 상대경로로 지정됨
  • 로컬 개발 의존성과 프로덕션 의존성이 다름
  • TypeScript 컴파일 설정 차이
  • Node.js 버전 차이

빌드 로그 확인하기

배포 후 빌드 로그부터 본다. 보통 CI/CD 로그에 에러가 명확하게 나타난다.

# GitHub Actions의 경우
# Actions 탭 → 해당 워크플로우 → 로그 확인

# Vercel의 경우
# 대시보드 → 해당 프로젝트 → Deployments → 로그 확인

# 로컬에서 프로덕션 빌드 시뮬레이션
npm run build
npm run start

환경 변수 확인

프로덕션 환경에서만 필요한 환경 변수를 로컬에서 설정했는지 확인한다.

# .env.local (로컬만 사용)
DATABASE_URL=postgresql://localhost/mydb

# .env.production (프로덕션)
DATABASE_URL=postgresql://prod-server.example.com/mydb

# 빌드 시간에 필요한 변수
NEXT_PUBLIC_API_URL=https://api.example.com

프로덕션 환경에서 실제로 환경 변수가 설정되어 있는지 확인한다.

# Vercel 대시보드에서 확인
# Settings → Environment Variables

# 또는 SSH로 접속해서 확인
echo $DATABASE_URL
echo $NEXT_PUBLIC_API_URL

파일 경로 문제

상대경로를 쓰면 로컬과 빌드 환경에서 작동이 다를 수 있다.

// 위험: 상대경로 사용
const dbPath = './database.db';

// 올바름: 절대경로 사용
import path from 'path';
const dbPath = path.join(process.cwd(), 'database.db');

// 또는 환경 변수 사용
const dbPath = process.env.DB_PATH || path.join(process.cwd(), 'database.db');

의존성 문제

로컬에만 설치된 패키지나 dev 의존성이 프로덕션에서 필요할 수 있다.

# package.json 확인
npm list

# 또는 yarn으로 의존성 잠금
yarn lock

# 프로덕션 빌드 테스트
npm ci  # npm install 대신 사용 (정확한 버전만 설치)
npm run build

TypeScript 컴파일 오류

next build가 로컬에서는 성공하지만 CI에서 실패할 수 있다.

# 타입 체크 강화
npx tsc --noEmit

# 엄격한 모드로 빌드
npm run build -- --strict

서버 액션 특화 문제

서버 액션은 클라이언트에서 호출되기 때문에, API 엔드포인트처럼 명시적으로 테스트해야 한다.

// app/actions.ts (서버 액션)
'use server'
export async function fetchUserData(id: string) {
  // 이 함수는 서버에서만 실행되어야 함
  const user = await db.query(`SELECT * FROM users WHERE id = $1`, [id]);
  return user;
}

만약 이 함수에서 데이터베이스 연결이 실패한다면, 로컬 개발 환경의 DB와 프로덕션 DB가 다르거나 접근 권한이 없는 것일 수 있다.

# 프로덕션 DB에 접근 가능한지 테스트
npm run build
node -e "require('./.next/server/lib/db').testConnection()"

배포 전 체크리스트

  • 로컬에서 npm run build && npm run start로 프로덕션 빌드를 테스트했는가?
  • 모든 환경 변수가 프로덕션에 설정되어 있는가?
  • 파일 경로가 절대경로 또는 process.cwd()를 사용하는가?
  • TypeScript 에러가 없는가? (npx tsc --noEmit)
  • 로컬 의존성과 프로덕션 의존성이 동일한가? (lock 파일 커밋)
  • 서버 액션의 외부 리소스(DB, API) 접근이 프로덕션에서도 가능한가?
  • Node.js 버전이 로컬과 서버에서 동일한가?

이 항목들을 확인한 후 배포하면 "내 컴퓨터에서는 되는데" 상황을 대부분 피할 수 있다.