테마 전환

Astro 빌드 실패? 5분 안에 확인할 7가지 일반적인 원인

Easton editorial illustration: performance inspection lens

터미널이 빨간 오류 메시지로 가득 찹니다. 로컬 개발 환경에서는 npm run dev가 빠르게 실행되고 컴포넌트 렌더링과 라우팅에도 아무 문제가 없었는데, astro build를 실행하는 순간 빌드가 터집니다.

Astro 빌드 실패는 프론트엔드 개발자가 겪는 가장 골치 아픈 문제 중 하나입니다. 로컬 환경과 프로덕션 빌드의 차이 때문에 원인을 파악하기 어렵고, 오류 메시지는 수십 줄에 이르는 기술 용어로 가득해 어디서부터 살펴봐야 할지 막막합니다.

이 글에서는 Astro를 사용하며 겪은 시행착오를 바탕으로 문제를 5분 안에 빠르게 찾는 방법, 가장 흔한 7가지 빌드 실패 상황과 해결책, Vercel·Cloudflare·GitHub Pages별 주의점, 실패를 줄이는 예방적 모범 사례를 정리했습니다. 실제로 빌드 실패의 90%는 이 7가지 원인 안에서 찾을 수 있습니다.

빠른 참조: 오류 메시지 표

오류가 발생했을 때 바로 대조할 수 있도록 먼저 빠른 참조표를 살펴보겠습니다.

오류 메시지가능한 원인빠른 해결책
SyntaxError: Unexpected token 'with'Node.js 버전이 너무 낮음Node 18.17.1+ 또는 20.3.0+로 업그레이드
Cannot find module / ERR_MODULE_NOT_FOUND의존성 설치 문제node_modules 삭제 후 재설치
frontmatter does not match schemaContent Collections 검증 실패Markdown 파일의 frontmatter 형식 확인
document is not defined / window is not defined서드파티 패키지가 SSR과 호환되지 않음client:only 또는 동적 import 사용
The build was canceled통합 충돌 또는 의존성 문제통합을 하나씩 주석 처리해 확인
로컬에서는 정상인데 온라인에서 실패환경 변수 또는 Node 버전 차이배포 플랫폼 설정 확인
GitHub Pages 페이지 404base 경로가 설정되지 않음astro.config.mjs의 base 필드 설정

1. 빠른 진단 프레임워크: 5분 안에 문제 찾기

오류 메시지를 이해하는 3가지 핵심

오류 메시지만 보면 당황하기 쉽지만, 실제로 답은 그 안에 들어 있습니다. 다음 3가지 핵심을 기준으로 빠르게 읽어 보세요.

1. 오류 유형 식별

오류의 첫 줄이나 핵심 단어를 확인합니다.

  • SyntaxError: 코드 문법 문제
  • ModuleNotFoundError 또는 Cannot find module: 의존성을 찾을 수 없음
  • ValidationError: 데이터 검증 실패(일반적으로 Content Collections의 frontmatter 문제)
  • ENOENT: 파일 또는 디렉터리가 없음
  • is not defined(document/window): 서버 렌더링 중 브라우저 API에 접근함

예를 들어 SyntaxError: Unexpected token 'with'가 보인다면 Node.js 버전이 너무 낮을 가능성이 큽니다.

2. 오류 위치 찾기

아래와 같은 정보를 찾아 내려갑니다.

at /path/to/your/file.astro:23:5

이 표시는 어느 파일의 23번째 줄에서 문제가 발생했는지 알려 줍니다. 중간에 길게 나오는 node_modules 경로에 휩쓸리지 말고, 직접 작성한 코드의 경로를 찾는 것이 중요합니다.

문제가 직접 작성한 코드가 아니라 어떤 의존성 패키지에서 발생할 때도 있습니다. 이 경우 오류 스택의 위쪽에 있는 Error: xxx caused by 같은 단서를 확인합니다.

3. 오류 문맥 이해

오류가 어느 단계에서 발생했는지 확인합니다.

  • Building for production... → 빌드 단계 오류
  • Rendering... → 페이지 렌더링 단계 오류
  • vite v5.0.0 building for production... → Vite 빌드 계층 오류

빌드 단계 오류는 주로 설정이나 의존성 문제이고, 렌더링 단계 오류는 코드 로직 문제인 경우가 많습니다.

5단계 빠른 진단법

오류 메시지를 읽는 방법을 알았다면 다음 5단계를 차례로 실행합니다. 대부분의 문제는 이 과정에서 찾을 수 있습니다.

Step 1: Node.js 버전 확인

node -v

Astro에는 Node.js 18.17.1+ 또는 20.3.0+가 필요합니다. 이보다 낮은 버전이라면 업그레이드하세요. 배포 플랫폼이 오래된 Node 버전을 기본으로 사용해 이 단계에서 막히는 경우가 많습니다.

로컬에서 nvm을 사용한다면 다음과 같이 전환할 수 있습니다.

nvm use 20

Step 2: 의존성이 올바르게 설치되었는지 확인

npm list  # 또는 pnpm list

UNMET DEPENDENCYmissing 같은 메시지가 있는지 확인합니다. 이런 메시지가 있다면 의존성이 완전하게 설치되지 않은 것입니다.

또한 package.jsonpackage-lock.json의 수정 시간을 비교하세요. lock 파일이 오래되었다면 의존성 상태가 서로 맞지 않을 수 있습니다.

Step 3: 캐시를 지우고 다시 빌드

단순하지만 매우 효과적인 방법입니다. 이상한 오류가 생겼을 때 가장 먼저 캐시부터 지워 보세요.

# 모든 빌드 결과물과 의존성 삭제
rm -rf node_modules .astro dist
# 다시 설치
npm install
# 빌드 재시도
npm run build

적어도 30%의 문제는 이렇게 해결됩니다. 캐시 오염과 의존성 버전 불일치는 생각보다 흔합니다.

Step 4: 최근 변경한 파일 확인

마지막으로 빌드가 성공한 이후 무엇을 바꿨는지 떠올려 보세요. 새 컴포넌트를 추가했나요? 설정을 바꾸거나 새 의존성을 설치했나요?

Git으로 최근 변경 사항을 확인합니다.

git diff HEAD

문제는 최근 한두 번의 커밋에 있는 경우가 많습니다. 새로 바꾼 코드를 잠시 주석 처리한 뒤 빌드가 성공하는지 확인하면 원인을 빠르게 좁힐 수 있습니다.

Step 5: 로컬 환경과 CI 환경의 차이 비교

로컬 빌드는 성공하지만 CI/CD 또는 배포 플랫폼에서 실패한다면 환경 차이가 원인입니다. 다음 항목을 중점적으로 확인합니다.

  • Node 버전: 로컬과 온라인 환경이 같은가요?
  • 패키지 관리자: npm, pnpm, yarn 중 무엇을 쓰며 버전도 같은가요?
  • 환경 변수: 온라인 환경에 필요한 변수가 모두 설정되어 있나요?
  • 의존성 버전: lock 파일을 커밋했으며 온라인 설치 버전이 로컬과 같은가요?

예전에 로컬에서는 Node 20을 사용했지만 Vercel은 기본 Node 18을 사용했던 적이 있습니다. Node 20에서만 지원하는 API를 쓴 탓에 온라인에서 오류가 발생했고, Vercel 프로젝트 설정에서 Node 버전을 지정한 뒤 해결했습니다.

2. 가장 흔한 빌드 실패 원인 7가지

원인 1: 호환되지 않는 Node.js 버전

대표 오류 메시지:

SyntaxError: Unexpected token 'with'

또는

error: Cannot use import statement outside a module

근본 원인:

Astro에는 Node.js 18.17.1 이상 또는 20.3.0+가 필요합니다. 많은 빌드 실패는 너무 낮은 버전에서 시작됩니다.

주로 다음 두 상황에서 발생합니다.

  1. 로컬 Node는 업그레이드했지만 배포 플랫폼은 여전히 이전 버전을 사용합니다.
  2. 팀원마다 서로 다른 Node 버전을 사용합니다.

해결책:

로컬 환경:

nvm으로 Node 버전을 관리한다면 쉽게 바꿀 수 있습니다.

nvm install 20
nvm use 20

배포 플랫폼 설정:

플랫폼에 따라 설정 방법이 다릅니다.

Vercel:
프로젝트 설정 → General → Node.js Version에서 20.x를 선택합니다.

Cloudflare Pages:
프로젝트 루트에 .nvmrc 파일을 만듭니다.

20

Netlify:
루트에 netlify.toml을 만듭니다.

[build.environment]
  NODE_VERSION = "20"

예방 조치:

package.json에 다음 설정을 추가해 필요한 Node 버전을 명시합니다.

{
  "engines": {
    "node": ">=18.17.1"
  }
}

그러면 누군가 낮은 Node 버전으로 npm install을 실행할 때 경고가 표시됩니다.

원인 2: 의존성 패키지 충돌 또는 버전 잠금 문제

대표 오류 메시지:

Error: Cannot find module 'astro'
ERR_MODULE_NOT_FOUND

또는 다음처럼 더 모호한 메시지가 나올 수 있습니다.

X [ERROR] The build was canceled

흔한 상황:

저도 이런 문제를 여러 번 겪었는데, 보통 다음 중 하나였습니다.

  1. 패키지 관리자 호환성 문제

Astro 4.11.2 이후 Bun과 pnpm 지원이 조정되면서 일부 프로젝트에서 갑자기 의존성을 설치하지 못하는 일이 있었습니다. 저도 4.11.1에서 4.11.2로 올린 뒤 pnpm 오류를 겪었고, 이후 Astro 팀이 문제를 수정했습니다.

  1. lock 파일과 node_modules가 동기화되지 않음

package.json을 바꿨지만 lock 파일을 업데이트하지 않았거나, Git에서 다른 사람의 lock 파일을 받은 뒤 로컬 의존성을 다시 설치하지 않았을 수 있습니다.

  1. 일부 서드파티 패키지 자체의 문제

Astro 환경에서 오류를 일으키기 쉬운 패키지도 있습니다.

  • astro-compress: 빌드 실패를 일으킨다는 보고가 많습니다.
  • @supercharge/strings: is not a function 오류가 보고된 적이 있습니다.
  • nodejs-mysql: 호환성이 더 좋은 mysql2로 바꾸는 편이 좋습니다.

해결책:

표준 3단계 조치:

# 1. 모든 의존성과 캐시 삭제
rm -rf node_modules .astro dist package-lock.json
# pnpm을 사용한다면:
rm -rf node_modules .astro dist pnpm-lock.yaml

# 2. 패키지 관리자 캐시 정리
npm cache clean --force
# 또는 pnpm store prune

# 3. 다시 설치
npm install
# CI에서는 의존성과 lock 파일을 일치시키기 위해 다음 명령 사용:
npm ci

그래도 해결되지 않으면 설정 파일 확인:

pnpm 사용자는 .npmrc를 조정해야 할 수 있습니다.

shamefully-hoist=true
public-hoist-pattern[]=*astro*

최소화 진단법:

특정 의존성이 원인으로 의심된다면 다음 순서로 확인합니다.

  1. 새 Astro 프로젝트를 만듭니다.
npm create astro@latest minimal-test -- --template minimal
  1. 문제가 의심되는 의존성만 추가해 재현되는지 확인합니다.

  2. 재현된다면 GitHub Issues에서 같은 문제가 보고되었는지 검색합니다.

저도 이 방법으로 astro-compress가 원인임을 찾았고, 결국 다른 이미지 최적화 방식을 선택했습니다.

원인 3: Content Collections 형식 검증 실패

대표 오류 메시지:

Error: blog → post.md frontmatter does not match collection schema.
"date" must be a valid date

또는

MarkdownContentSchemaValidationError: Content entry frontmatter does not match schema
"title" is required

근본 원인:

Astro 2.0은 Zod로 Markdown 파일의 frontmatter를 검증하는 Content Collections 기능을 도입했습니다. 데이터 타입의 안전성을 보장하는 강력한 기능이지만, Markdown frontmatter 형식이 규칙에 맞지 않으면 빌드 오류가 발생합니다.

저도 처음 사용할 때 어려움을 겪었습니다. 예전 블로그 글은 frontmatter 형식이 제각각이어서 날짜를 2024-01-01로 쓴 글도, 2024/01/01로 쓴 글도 있었고 일부 필드는 아예 빠져 있었습니다. Content Collections를 활성화하자 이 글들이 모두 오류를 냈습니다.

자주 발생하는 오류 유형:

  1. 필수 필드 누락

Schema에서 title을 필수로 정의했지만 일부 Markdown 파일에 title이 없는 경우입니다.

---
# title을 쓰지 않음
date: 2024-01-01
---
  1. 필드 타입 오류

가장 흔한 것은 날짜 형식 문제입니다.

---
title: "My Post"
date: 2024/01/01  # 2024-01-01이어야 함
---

배열을 문자열로 쓴 경우도 있습니다.

---
tags: javascript  # [javascript] 또는 ["javascript"]여야 함
---
  1. 필드 이름 오타

Schema에는 description으로 정의되어 있는데 desc라고 쓰면 Astro가 인식하지 못합니다.

해결책:

Step 1: schema 정의 확인

src/content/config.ts를 열어 schema 정의를 확인합니다.

import { z, defineCollection } from 'astro:content';

const blog = defineCollection({
  schema: z.object({
    title: z.string(),
    date: z.date(),
    tags: z.array(z.string()).optional(),
  }),
});

export const collections = { blog };

Step 2: 오류 메시지와 대조해 frontmatter 수정

오류 메시지는 문제가 있는 파일과 필드를 알려 줍니다. 예를 들면 다음과 같습니다.

blog → my-post.md frontmatter does not match collection schema.
"date" must be a valid date

이 경우 src/content/blog/my-post.md의 날짜 형식을 고칩니다.

---
title: "내 글"
date: 2024-01-01  # 형식이 YYYY-MM-DD인지 확인
tags: ["astro", "blog"]
---

Step 3: .passthrough()로 형식이 제각각인 예전 글 처리

오래된 글이 많아 하나씩 수정하기 어렵다면 .passthrough()로 검증을 완화할 수 있습니다.

const blog = defineCollection({
  schema: z.object({
    title: z.string(),
    date: z.coerce.date(),  // coerce로 자동 변환
    tags: z.array(z.string()).optional().default([]),
  }).passthrough(),  // schema에 없는 추가 필드 허용
});

.passthrough()는 schema에 정의되지 않은 필드가 있어도 오류를 내지 않고 통과시킨다는 뜻입니다.

Step 4: dev server 재시작

schema를 수정한 뒤에는 반드시 dev server를 다시 시작해야 적용됩니다.

# 먼저 중지(Ctrl+C)
# 다시 시작
npm run dev

또는 dev server가 실행 중일 때 s + enter를 눌러 콘텐츠 계층을 동기화합니다.

원인 4: 잘못된 환경 변수 설정

대표 상황:

로컬의 npm run devnpm run build는 모두 정상인데 Vercel이나 Cloudflare에 배포하면 다음 문제가 발생합니다.

  • 페이지가 완전하게 표시되지 않음
  • 댓글 시스템이나 API 호출 같은 일부 기능이 작동하지 않음
  • 빌드는 성공하지만 런타임 오류 발생

흔한 문제:

  1. 배포 플랫폼에 환경 변수가 설정되지 않음

로컬에는 .env 파일이 있지만 .gitignore에서 제외되어 있습니다. 민감한 정보는 커밋하면 안 되므로 이것은 올바른 설정입니다. 다만 배포 플랫폼은 이 환경 변수의 값을 알 수 없으므로 빌드나 실행 중 문제가 발생합니다.

  1. PUBLIC_ 접두사 사용 오류

Astro의 환경 변수에는 특별한 규칙이 있습니다.

  • 클라이언트에서 접근할 변수는 반드시 PUBLIC_으로 시작해야 합니다.
  • 서버 전용 변수에는 접두사가 필요하지 않습니다.

클라이언트 코드에서 PUBLIC_ 접두사가 없는 변수를 사용하면 빌드 시 값이 undefined가 됩니다.

예를 들면 다음과 같습니다.

// .env
API_KEY=abc123
PUBLIC_SITE_URL=https://example.com

// 클라이언트 코드
const apiKey = import.meta.env.API_KEY;  // ❌ undefined
const siteUrl = import.meta.env.PUBLIC_SITE_URL;  // ✅ 정상

해결책:

배포 플랫폼별 설정 방법:

Vercel:

  1. 프로젝트 → Settings → Environment Variables로 이동합니다.
  2. 변수를 추가하고 적용할 환경(Production/Preview/Development)을 선택합니다.
  3. 다시 배포합니다.

Cloudflare Pages:

  1. 프로젝트 → Settings → Environment variables로 이동합니다.
  2. Production과 Preview 환경에 각각 설정합니다.
  3. 다시 빌드합니다.

Netlify:

  1. Site settings → Environment variables로 이동합니다.
  2. 변수를 추가합니다.
  3. 새 배포를 실행합니다.

환경 변수의 올바른 사용법:

// astro.config.mjs
export default defineConfig({
  // 여기서는 모든 환경 변수를 사용할 수 있음
  site: import.meta.env.PUBLIC_SITE_URL,
});

// src/pages/index.astro
---
// 서버 코드에서는 모든 변수를 사용할 수 있음
const apiKey = import.meta.env.API_KEY;
const response = await fetch(`https://api.example.com?key=${apiKey}`);
---

<script>
  // 클라이언트 코드에서는 PUBLIC_으로 시작하는 변수만 사용 가능
  const siteUrl = import.meta.env.PUBLIC_SITE_URL;
  console.log(siteUrl);  // 정상 출력

  const apiKey = import.meta.env.API_KEY;
  console.log(apiKey);  // undefined
</script>

보안 주의 사항:

API 키나 데이터베이스 비밀번호 같은 민감한 정보를 PUBLIC_으로 시작하는 변수에 넣지 마세요. 이 값은 번들된 JS 파일에 인라인으로 포함되므로 누구나 볼 수 있습니다.

클라이언트에서 API를 호출해야 한다면 API 키를 직접 노출하지 말고 자체 백엔드 인터페이스를 통해 중계하는 편이 좋습니다.

원인 5: 설정 파일 오류

대표 오류 메시지:

명확한 오류 메시지가 없이 빌드가 멈추거나 무한 루프에 빠지거나 알 수 없는 Vite 오류가 발생하기도 합니다.

자주 문제가 되는 지점:

  1. 잘못된 base 경로 설정(GitHub Pages 배포)

GitHub Pages URL 형식은 https://username.github.io/repo-name/입니다. astro.config.mjsbase를 설정하지 않으면 모든 리소스 경로에서 404가 발생합니다.

잘못된 설정:

export default defineConfig({
  site: 'https://username.github.io/my-blog/',
  // base 설정 누락
});

올바른 설정:

export default defineConfig({
  site: 'https://username.github.io',
  base: '/my-blog',  // 저장소 이름을 base 경로로 사용
});
  1. 통합(integrations) 충돌

Svelte 통합과 content/config.ts가 충돌해 The build was canceled 오류가 발생했다는 보고가 있습니다.

저도 여러 이미지 최적화 플러그인을 동시에 사용했을 때 서로 충돌하는 문제를 겪었고, 그중 하나를 제거해 해결했습니다.

해결책:

base 경로 확인:

GitHub Pages 같은 하위 경로에 배포한다면 base가 설정되어 있는지 확인합니다.

// astro.config.mjs
export default defineConfig({
  site: 'https://yourdomain.com',
  base: process.env.BASE_PATH || '/',  // 로컬 개발에서는 /, 배포 시 실제 경로
});

그런 다음 CI 설정에 환경 변수를 추가합니다.

# .github/workflows/deploy.yml
env:
  BASE_PATH: /my-blog

통합 충돌 진단:

특정 통합이 원인으로 의심된다면 하나씩 주석 처리해 테스트합니다.

// astro.config.mjs
export default defineConfig({
  integrations: [
    // react(),
    // tailwind(),
    // sitemap(),
  ],
});

가장 단순한 설정에서 시작해 하나씩 다시 추가하면서 어떤 통합이 문제를 일으키는지 확인합니다.

원인 6: SSG/SSR과 호환되지 않는 서드파티 패키지

대표 오류 메시지:

ReferenceError: document is not defined
ReferenceError: window is not defined

근본 원인:

Astro는 기본적으로 서버, 즉 Node.js 환경에서 페이지를 빌드합니다. 하지만 일부 npm 패키지는 브라우저용으로 만들어져 document, window 같은 브라우저 API에 직접 접근합니다. 서버 빌드 환경에는 이런 API가 없으므로 오류가 발생합니다.

저는 차트 라이브러리를 사용했을 때 이 문제를 처음 겪었습니다. dev 모드에서는 브라우저에서 렌더링되므로 정상적으로 보였지만 build를 실행하자 document is not defined 오류가 발생했습니다.

문제가 자주 발생하는 패키지:

  • DOM 조작에 의존하는 UI 컴포넌트 라이브러리
  • 기기 유형이나 브라우저 버전을 확인하는 브라우저 감지 라이브러리
  • 오래된 jQuery 플러그인
  • 모듈 최상위에서 window.xxx를 직접 실행하는 패키지

해결책:

방법 1: client:only 지시어 사용

해당 컴포넌트는 클라이언트에서만 렌더링하고 서버에서는 실행하지 않도록 Astro에 지시합니다.

---
import ProblematicComponent from './ProblematicComponent';
---

<ProblematicComponent client:only="react" />

client:only 뒤에는 react, vue, svelte 같은 프레임워크 이름을 지정해야 합니다.

방법 2: 동적 import

클라이언트에서만 패키지를 불러옵니다.

---
// 서버에서는 import하지 않음
---

<script>
  // 클라이언트에서 동적으로 import
  const { default: MyLibrary } = await import('problematic-package');
  const instance = new MyLibrary();
</script>

방법 3: 조건부 import

환경을 확인한 뒤 사용합니다.

let myLib;
if (typeof window !== 'undefined') {
  myLib = await import('problematic-package');
}

방법 4: 호환되는 패키지로 교체

때로는 패키지를 바꾸는 것이 가장 간단한 해결책입니다.

  • nodejs-mysqlmysql2
  • 일부 오래된 차트 라이브러리 → SSR 친화적인 chart.js
  • jQuery 플러그인 → 네이티브 JS 또는 최신 프레임워크 컴포넌트

권장 사항:

서드파티 패키지를 선택하기 전에 문서에서 SSR/SSG 지원 여부를 확인하세요. 요즘 인기 있는 라이브러리는 서버 렌더링 지원 여부를 명확히 밝히는 경우가 많습니다. 문서에 “works with Next.js” 또는 “SSR compatible”이라고 되어 있다면 대체로 Astro에서도 사용할 수 있습니다.

원인 7: Astro 버전 업그레이드로 인한 Breaking Changes

대표 상황:

Astro 5 또는 다른 메이저 버전으로 올린 뒤 이전에는 빌드되던 프로젝트에서 갑자기 다음 문제가 발생합니다.

  • 빌드가 끝나지 않고 멈춤
  • 알 수 없는 모듈 해석 오류 발생
  • 일부 API를 더 이상 사용할 수 없음

흔한 문제:

  1. CommonJS 모듈 해석 변경

Astro 5에서 일부 모듈 해석 로직이 바뀌어 이전에 사용하던 CommonJS 패키지가 작동하지 않을 수 있습니다.

  1. API 폐기 또는 변경

메이저 버전마다 일부 이전 API가 폐기됩니다. 예를 들어 특정 Astro.xxx 메서드가 이름이 바뀌거나 제거될 수 있습니다.

  1. 호환되지 않는 통합 버전

Astro를 업그레이드하면 일부 공식 또는 서드파티 통합도 대응 버전으로 올려야 합니다. 그렇지 않으면 호환성 문제가 발생할 수 있습니다.

해결 전략:

버전을 건너뛰지 말고 단계적으로 업그레이드:

Astro 3에서 5로 올릴 때 한 번에 진행하지 마세요. 먼저 4로 올려 테스트한 뒤 5로 업그레이드하면 문제의 원인을 더 쉽게 찾을 수 있습니다.

# 잘못된 방법
npm install astro@latest

# 권장 방법
npm install astro@^4.0.0
# 테스트를 통과한 뒤
npm install astro@^5.0.0

Astro CLI 업그레이드 도구 사용:

Astro는 일반적인 Breaking Changes를 처리하는 데 도움이 되는 자동 업그레이드 도구를 제공합니다.

npx @astrojs/upgrade

이 도구는 다음 작업을 수행합니다.

  • 프로젝트 분석
  • 업그레이드가 필요한 의존성 안내
  • 폐기된 API 호출 같은 일부 코드 자동 수정

관련 통합 업그레이드:

Astro를 업그레이드했다면 공식 통합도 함께 업그레이드해야 합니다.

npm install @astrojs/react@latest @astrojs/tailwind@latest @astrojs/sitemap@latest

Astro 5에 Astro 4 시기의 통합 버전을 조합해 빌드가 실패하는 경우도 있습니다.

3. 배포 플랫폼별 특수 문제

공통적인 7가지 원인을 살펴봤으니 이제 각 배포 플랫폼에서만 나타나는 문제를 알아보겠습니다. 플랫폼마다 특성이 다르므로 이를 이해하면 불필요한 시행착오를 줄일 수 있습니다.

Vercel 배포 문제

대표 문제 1: 빌드 시간 초과

Vercel 무료 요금제에는 빌드 시간 제한이 있습니다. 프로젝트가 크거나 의존성 설치가 느리다면 제한 시간을 넘어 실패할 수 있습니다.

해결책:

  • package.json을 확인하고 불필요한 의존성을 제거합니다.
  • 설치 속도가 더 빠른 pnpmnpm 대신 사용합니다.
  • 예산이 허용된다면 프로젝트 설정에서 Pro plan으로 업그레이드합니다.

대표 문제 2: 잘못된 출력 디렉터리 설정

Vercel은 빌드 결과물이 어디에 있는지 알아야 합니다. Astro는 기본적으로 dist 디렉터리에 출력하지만 설정을 바꾸면 Vercel이 파일을 찾지 못할 수 있습니다.

올바른 설정:

  • Build Command: npm run build 또는 astro build
  • Output Directory: dist(Astro 기본값)
  • Install Command: npm install

pnpm을 사용한다면:

  • Install Command: pnpm install

Cloudflare Pages 배포 문제

대표 문제 1: 너무 낮은 Node.js 버전

Cloudflare Pages의 기본 Node 버전이 오래되었을 수 있습니다. 반드시 루트에 .nvmrc 파일을 만들어 버전을 지정하세요.

20

또는 프로젝트 설정에서 지정합니다.

Settings → Environment variables → NODE_VERSION = 20

대표 문제 2: astro-compress로 인한 실패

특히 이미지 최적화 후 astro-compress 패키지 때문에 Cloudflare에서 빌드가 실패한다는 보고가 많습니다.

이 문제가 발생한다면 다음과 같이 처리합니다.

  1. npm uninstall astro-compress로 astro-compress를 제거합니다.
  2. astro.config.mjs에서 해당 설정을 삭제합니다.
  3. Astro 내장 <Image /> 컴포넌트 같은 다른 이미지 최적화 방식을 사용합니다.

대표 문제 3: 빌드 명령 설정

Cloudflare Pages의 빌드 설정은 다음과 같습니다.

  • Build command: npm run build
  • Build output directory: /dist
  • Root directory: /(monorepo라면 조정 필요)

Build output directory 앞에는 /를 붙여야 합니다.

GitHub Pages 배포 문제

대표 문제 1: 페이지 404 또는 빈 화면

가장 흔한 문제로, base 경로가 올바르게 설정되지 않아 발생합니다.

GitHub Pages 저장소 URL은 https://username.github.io/repo-name/ 형식입니다. 여기서 /repo-name/이 바로 base 경로입니다.

astro.config.mjs에 다음과 같이 설정해야 합니다.

export default defineConfig({
  site: 'https://username.github.io',
  base: '/your-repo-name',  // 저장소 이름
});

대표 문제 2: 스타일 누락 또는 리소스 404

페이지는 열리지만 스타일이 없거나 이미지를 불러오지 못한다면 역시 base 경로 문제일 가능성이 큽니다.

브라우저 콘솔에서 리소스 요청 경로가 올바른지 확인하세요. 요청 주소가 https://username.github.io/style.css인데 실제 주소는 https://username.github.io/repo-name/style.css여야 한다면 base 설정이 빠진 것입니다.

4. 예방을 위한 모범 사례

이제 문제를 해결하는 방법을 알았지만, 더 중요한 것은 같은 문제를 다시 겪지 않도록 예방하는 것입니다.

로컬 진단 워크플로 만들기

최소 재현(minimal reproduction)

문제가 생겼다고 원래 프로젝트에서 무작정 수정하지 마세요. 먼저 최소 테스트 프로젝트를 만듭니다.

npm create astro@latest test-project -- --template minimal
cd test-project
# 문제가 있는 코드나 의존성만 추가

최소 프로젝트에서 문제가 재현된다면 프로젝트 전체가 아니라 특정 기능이나 의존성이 원인임을 알 수 있습니다. 이렇게 하면 훨씬 빠르게 진단할 수 있습니다.

브라우저 콘솔과 빌드 로그 활용

개발할 때는 브라우저 콘솔을 열어 두세요.

  • Console 탭: JavaScript 오류 확인
  • Network 탭: 리소스가 정상적으로 로드되는지 확인
  • Sources 탭: 코드 디버깅

빌드할 때는 로그를 저장합니다.

npm run build > build.log 2>&1

터미널 내용이 지나가 버려도 나중에 전체 로그를 다시 확인할 수 있습니다.

개인 오류 해결 노트 작성

저는 겪었던 오류와 해결책을 모두 기록하는 Markdown 파일을 따로 두고 있습니다. 형식은 간단합니다.

## 오류: SyntaxError: Unexpected token 'with'

**상황**: Vercel 배포 실패
**원인**: Node 버전이 너무 낮음
**해결**: Vercel 설정에서 Node 버전을 20.x로 지정
**날짜**: 2024-11-15

다음에 비슷한 문제가 생기면 먼저 이 노트를 확인하세요. 5분 만에 해결책을 찾을 수도 있습니다.

프로젝트 상태 관리

정기적으로 의존성 업데이트

매월 또는 분기마다 의존성 업데이트를 확인합니다.

# 오래된 의존성 확인
npm outdated

# 모든 의존성을 최신 버전으로 업데이트(신중하게 사용)
npm update

# 또는 하나씩 업데이트
npm install astro@latest

특히 메이저 버전 변경은 무작정 진행하면 안 됩니다. 업그레이드 전에 CHANGELOG를 읽고 Breaking Changes가 있는지 확인하세요.

Dependabot으로 의존성 업데이트 자동화

GitHub 저장소 루트에 .github/dependabot.yml을 만듭니다.

version: 2
updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
    open-pull-requests-limit: 5

Dependabot은 의존성 업데이트를 자동 확인해 PR을 만듭니다. 사용자는 검토하고 병합하기만 하면 됩니다.

빌드 테스트 스크립트 작성

package.json에 테스트 스크립트를 추가합니다.

{
  "scripts": {
    "build": "astro build",
    "test:build": "npm run build && echo 'Build successful!'"
  }
}

pre-commit hook 설정

husky를 사용해 커밋 전에 자동으로 빌드하고 코드가 컴파일되는지 확인합니다.

npm install --save-dev husky

# husky 초기화
npx husky init

# pre-commit hook 추가
echo "npm run build" > .husky/pre-commit

이제 커밋 전에 항상 빌드가 실행되고, 빌드가 실패하면 커밋할 수 없습니다. 다소 느려질 수 있지만 문제가 있는 코드를 커밋하는 일을 막아 줍니다.

유용한 디버깅 도구와 자료

Astro 공식 자료:

  1. 공식 문제 해결 가이드: 가장 먼저 확인할 자료입니다.
  2. 오류 참조 문서: 모든 Astro 오류에 대한 자세한 설명이 있습니다.
  3. Discord 커뮤니티: 어려운 문제가 생기면 질문할 수 있습니다.

유용한 명령:

# Astro 설정이 올바른지 확인
npx astro check

# 자세한 빌드 정보 확인
npx astro build --verbose

# 디버그 모드로 실행
DEBUG=astro:* npm run dev

커뮤니티 자료:

  • Astro GitHub Issues: 알려진 문제 검색
  • Stack Overflow: [astro] 태그 검색
  • 커뮤니티 포럼과 블로그: 많은 개발자가 시행착오 경험을 공유합니다.

결론

지금까지 살펴본 내용을 빠르게 정리해 보겠습니다.

Astro 빌드 실패의 90%는 다음 원인에서 발생합니다.

  1. 호환되지 않는 Node.js 버전: 18.17.1 이상 또는 20.3.0+인지 확인
  2. 의존성 패키지 문제: 캐시를 지우고 재설치하며 lock 파일 확인
  3. Content Collections 검증 실패: frontmatter 형식 수정
  4. 잘못된 환경 변수 설정: 배포 플랫폼에서 올바르게 설정하고 PUBLIC_ 접두사 확인
  5. 설정 파일 오류: base 경로를 확인하고 통합 충돌 진단
  6. SSR과 호환되지 않는 서드파티 패키지: client:only 또는 동적 import 사용
  7. 버전 업그레이드의 Breaking Changes: 마이그레이션 가이드를 확인하고 단계적으로 업그레이드

5단계 빠른 진단법도 기억해 두세요.

  1. Node 버전 확인
  2. 의존성 설치 상태 확인
  3. 캐시를 지우고 다시 빌드
  4. 최근 변경 사항 확인
  5. 로컬과 온라인 환경의 차이 비교

가장 중요한 것은 체계적으로 진단하는 습관입니다. 오류가 발생해도 당황하지 말고 먼저 메시지에서 오류 유형과 위치를 찾은 뒤 그에 맞는 해결책을 적용하세요.

저도 Astro를 처음 사용할 때는 빌드 오류 하나에 몇 시간씩 매달렸습니다. 하지만 이 방법을 익힌 뒤에는 대부분 5~10분이면 문제를 찾아 해결합니다. 이 글이 여러분의 시행착오를 줄이는 데 도움이 되길 바랍니다.

마지막으로 한 가지 기억할 점이 있습니다. 버전은 빠르게 바뀝니다. 이 글을 작성한 2024년 말에는 Astro의 최신 안정 버전이 4.x였습니다. 이 글을 읽을 때 이미 Astro 6.0이나 7.0이 나왔다면 구체적인 API와 오류 메시지는 달라졌을 수 있으므로 반드시 최신 공식 문서를 함께 확인하세요. 다만 여기에서 설명한 진단 관점과 방법은 계속 적용할 수 있습니다.

새로운 문제를 발견했다면 댓글로 공유해 주세요. 함께 이 진단 가이드를 더 탄탄하게 만들 수 있습니다. 이 글을 저장해 두었다가 다음에 빌드가 실패할 때 바로 대조하면 시간과 수고를 아낄 수 있습니다.

Astro 빌드 실패를 5분 안에 진단하는 전체 절차

체계적인 5단계 진단법과 가장 흔한 7가지 빌드 오류 상황별 해결책을 통해 문제의 90%를 5~10분 안에 해결합니다.

⏱️ Estimated time: 10 min

  1. 1

    Step 1: 5단계 빠른 진단법: 오류 메시지 이해하기

    오류 메시지를 이해하는 3가지 핵심:

    1. 오류 유형 식별
    • 오류의 첫 줄이나 핵심 단어 확인
    • SyntaxError: 코드 문법 문제
    • TypeError: 타입 오류
    • ReferenceError: 참조 오류
    • ModuleNotFoundError: 모듈을 찾을 수 없음

    2. 오류 위치 찾기
    • 오류가 발생한 파일과 줄 번호 확인
    • 일반적으로 Error at xxx:xx 형식

    3. 오류 문맥 분석
    • 오류 전후의 코드 확인
    • 오류가 발생한 이유 이해

    5단계 진단 절차:
    1. Node.js 버전 확인
    • Node 18.17.1+ 또는 20.3.0+ 사용
    • node -v로 확인

    2. 의존성 삭제 후 재설치
    • node_modules와 package-lock.json 삭제
    • npm install 다시 실행

    3. Content Collections 설정 확인
    • Markdown 파일의 frontmatter 형식이 올바른지 확인

    4. 서드파티 패키지 호환성 확인
    • client:only 또는 동적 import 사용

    5. 배포 플랫폼 설정 확인
    • 환경 변수, Node 버전, 빌드 명령 확인
  2. 2

    Step 2: 가장 흔한 7가지 빌드 오류 상황과 해결책

    오류 1: SyntaxError: Unexpected token 'with'
    • 원인: Node.js 버전이 너무 낮음
    • 해결책: Node 18.17.1+ 또는 20.3.0+로 업그레이드하고 nvm으로 Node 버전 관리

    오류 2: Cannot find module/ERR_MODULE_NOT_FOUND
    • 원인: 의존성 설치 문제
    • 해결책:
    - node_modules와 package-lock.json 삭제
    - npm install 다시 실행
    - package.json의 의존성이 올바른지 확인

    오류 3: frontmatter does not match schema
    • 원인: Content Collections 검증 실패
    • 해결책: Markdown 파일의 frontmatter 형식을 확인하고 필수 필드가 모두 있으며 형식이 올바른지 확인

    오류 4: document is not defined/window is not defined
    • 원인: 서드파티 패키지가 SSR과 호환되지 않음
    • 해결책: client:only 또는 동적 import를 사용하고 컴포넌트에 client:load 같은 지시어 추가

    오류 5: The build was canceled
    • 원인: 통합 충돌 또는 의존성 문제
    • 해결책: 통합을 하나씩 주석 처리해 확인하고 의존성 충돌 점검

    오류 6: 로컬에서는 정상인데 온라인에서 실패
    • 원인: 환경 변수 또는 Node 버전 차이
    • 해결책: 배포 플랫폼 설정을 확인하고 환경 변수와 Node 버전을 일치시킴

    오류 7: GitHub Pages 페이지 404
    • 원인: base 경로가 설정되지 않음
    • 해결책: astro.config.mjs의 base 필드를 올바르게 설정
  3. 3

    Step 3: 배포 플랫폼별 주의점

    Vercel 배포:
    • Node 버전 설정 확인(package.json의 engines 필드 또는 Vercel 프로젝트 설정에서 지정)
    • 필수 환경 변수가 모두 설정되었는지 확인
    • 빌드 명령 확인(일반적으로 npm run build)

    Cloudflare Pages 배포:
    • 빌드 명령이 올바른지 확인
    • 출력 디렉터리 설정 확인(일반적으로 dist)
    • Node 버전 확인(Cloudflare Pages 기본값은 Node 18이며 다른 버전이 필요하면 별도 설정)

    GitHub Pages 배포:
    • astro.config.mjs의 base 필드를 /repo-name/ 형식으로 설정
    • 정적 출력 모드(output: 'static') 사용
    • 빌드 명령과 출력 디렉터리 확인
  4. 4

    Step 4: 예방을 위한 모범 사례

    .nvm으로 Node 버전 관리
    • 팀원이 동일한 Node 버전을 사용하도록 보장
    • 버전 불일치로 인한 빌드 문제 예방

    정기적으로 의존성 업데이트
    • npm outdated로 오래된 의존성 확인
    • 최신 안정 버전으로 정기 업데이트

    TypeScript 타입 검사 사용
    • 빌드 전에 타입 검사 실행
    • 타입 오류를 미리 발견

    CI/CD 자동 빌드 테스트 설정
    • GitHub Actions 또는 다른 CI/CD 플랫폼에서 자동 빌드 테스트 설정
    • 커밋할 때마다 빌드 검사 자동 실행

    Git hooks로 커밋 전 빌드 검사 실행
    • pre-commit hook 설정
    • 커밋 전에 빌드 검사 자동 실행
    • 문제가 있는 코드의 커밋 방지

FAQ

Astro 빌드 실패의 가장 흔한 7가지 원인은 무엇인가요?
가장 흔한 7가지 빌드 오류:

1) SyntaxError: Unexpected token 'with':
• Node.js 버전이 너무 낮으므로 Node 18.17.1+ 또는 20.3.0+로 업그레이드합니다.

2) Cannot find module/ERR_MODULE_NOT_FOUND:
• 의존성 설치 문제이므로 node_modules를 삭제하고 다시 설치합니다.

3) frontmatter does not match schema:
• Content Collections 검증 실패이므로 Markdown 파일의 frontmatter 형식을 확인합니다.

4) document is not defined/window is not defined:
• 서드파티 패키지가 SSR과 호환되지 않으므로 client:only 또는 동적 import를 사용합니다.

5) The build was canceled:
• 통합 충돌 또는 의존성 문제이므로 통합을 하나씩 주석 처리해 확인합니다.

6) 로컬에서는 정상인데 온라인에서 실패:
• 환경 변수 또는 Node 버전 차이이므로 배포 플랫폼 설정을 확인합니다.

7) GitHub Pages 페이지 404:
• base 경로가 설정되지 않았으므로 astro.config.mjs의 base 필드를 지정합니다.

체계적인 5단계 진단법과 오류 메시지 빠른 참조표를 활용하면 문제의 90%를 5~10분 안에 빠르게 찾아 해결할 수 있습니다.
Astro 빌드 실패를 빠르게 진단하는 5단계 방법은 무엇인가요?
5단계 빠른 진단법:

1) 오류 메시지의 3가지 핵심 이해:
• 오류 유형 식별
• 오류 위치 찾기
• 오류 문맥 분석

2) Node.js 버전 확인:
• Node 18.17.1+ 또는 20.3.0+ 사용
• node -v로 확인

3) 의존성 삭제 후 재설치:
• node_modules와 package-lock.json 삭제
• npm install 다시 실행

4) Content Collections 설정 확인:
• Markdown 파일의 frontmatter 형식이 올바른지 확인

5) 서드파티 패키지 호환성 확인:
• client:only 또는 동적 import 사용

가장 중요한 것은 체계적인 진단 관점을 갖는 것입니다. 오류가 나도 당황하지 말고 먼저 메시지에서 오류 유형과 위치를 찾은 뒤 그에 맞는 해결책을 적용하세요. 저도 Astro를 처음 쓸 때는 빌드 오류 하나에 몇 시간씩 매달렸지만, 이 방법을 익힌 뒤에는 대부분 5~10분이면 원인을 찾아 해결합니다.
배포 플랫폼별로 Vercel, Cloudflare, GitHub Pages에서 주의할 점은 무엇인가요?
Vercel 배포:
• package.json의 engines 필드 또는 Vercel 프로젝트 설정에서 Node 버전 확인
• 필수 환경 변수가 모두 설정되었는지 확인
• 빌드 명령 확인(일반적으로 npm run build)

Cloudflare Pages 배포:
• 빌드 명령이 올바른지 확인
• 출력 디렉터리 설정 확인(일반적으로 dist)
• Node 버전 확인(Cloudflare Pages 기본값은 Node 18이며 다른 버전이 필요하면 별도 설정)

GitHub Pages 배포:
• astro.config.mjs의 base 필드를 /repo-name/ 형식으로 설정
• 정적 출력 모드(output: 'static') 사용
• 빌드 명령과 출력 디렉터리 확인
Astro 빌드 실패를 예방하려면 어떤 모범 사례를 적용해야 하나요?
예방을 위한 모범 사례:
• .nvm으로 Node 버전을 관리해 팀원이 같은 버전을 사용하게 하고 버전 불일치 문제를 예방합니다.
• npm outdated로 오래된 의존성을 확인하고 최신 안정 버전으로 정기 업데이트합니다.
• 빌드 전에 TypeScript 타입 검사를 실행해 타입 오류를 미리 발견합니다.
• GitHub Actions 또는 다른 CI/CD 플랫폼에서 자동 빌드 테스트를 설정해 커밋마다 검사를 실행합니다.
• pre-commit hook을 설정해 커밋 전에 빌드 검사를 자동 실행하고 문제가 있는 코드가 커밋되지 않도록 합니다.
Astro 빌드 실패를 해결하지 못했을 때 어디에서 도움을 받을 수 있나요?
공식 자료:
• Astro 공식 문서에서 최신 버전 문서와 API 설명 확인
• Astro GitHub Issues에서 알려진 유사 문제 검색
• Astro Discord 커뮤니티에서 실시간 질문

디버깅 도구:
• npx astro build --verbose로 자세한 빌드 정보 확인
• DEBUG=astro:* npm run dev로 디버그 모드 실행

커뮤니티 자료:
• Stack Overflow에서 [astro] 태그 검색
• 커뮤니티 포럼과 블로그에서 문제 해결 경험 참고

새로운 문제를 발견했다면 댓글로 공유해 주세요. 함께 이 진단 가이드를 더 탄탄하게 만들 수 있습니다. 저장해 두었다가 다음에 빌드가 실패할 때 바로 대조하면 시간과 수고를 아낄 수 있습니다.

5분 읽기 · 게시일: 2025년 12월 3일 · 수정일: 2026년 9월 4일

댓글

GitHub로 로그인하여 댓글을 남기세요

Easton BlogEaston Blog