Vite 게시판을 Vercel에 무료로 배포하고 GitHub Actions로 자동 배포하기

지난 글에서 만든 Vite + JavaScript + Tailwind CSS 게시판을 실제 인터넷에 올려보겠습니다. 친구나 가족에게 링크 하나 보내면 누구나 접속할 수 있는, 진짜 "내 사이트"를 만드는 거예요.
이 글에서는 Vercel이라는 무료 호스팅 서비스를 사용합니다. 가입부터 도메인 발급, 그리고 GitHub에 코드를 푸시하면 자동으로 다시 배포되도록 GitHub Actions 워크플로우를 구성하는 단계까지 전부 다룹니다.
완성하면 다음과 같은 흐름이 만들어져요.

내 컴퓨터에서 git push를 한 번 하면, GitHub이 변경을 감지해서 GitHub Actions를 깨우고, Actions가 빌드한 결과물을 Vercel로 보내고, Vercel이 그걸 라이브 사이트에 반영합니다. 이 모든 게 1~2분 안에 자동으로 일어나요.
시작하기 전에
준비물은 세 가지예요.
- GitHub 계정 — 코드를 올려둘 곳. 없다면 github.com에서 무료 가입
- 로컬에 있는 board-app 프로젝트 — 지난 튜토리얼의 결과물 (github.com/urstory/board-app)
- 이메일 주소 — Vercel 가입용
예상 소요 시간은 30~40분입니다. 처음 해보는 분은 한 시간 정도 잡아두면 여유롭게 할 수 있어요.
무료로 운영하기 좋은 서비스는 Vercel 말고도 Netlify, Cloudflare Pages, GitHub Pages가 있어요. 이 글에서는 손에 익히기 가장 편한 Vercel을 기준으로 설명하지만, 큰 흐름은 다른 서비스도 거의 같습니다.
1. 왜 Vercel인가요?
Vercel은 정적 사이트와 프론트엔드 앱을 무료로 호스팅해 주는 서비스예요. Next.js를 만든 회사의 서비스인 만큼, Vite 같은 도구는 거의 "설정 없이" 배포할 수 있습니다.
무료 플랜(Hobby)에서 챙길 수 있는 건 이렇습니다.
- HTTPS가 적용된
*.vercel.app도메인 - 자동으로 갱신되는 SSL 인증서
- GitHub 푸시마다 자동 빌드와 배포
- 전 세계 CDN
- 월 100GB 대역폭
개인 프로젝트나 포트폴리오 용도로 쓰기에는 충분하고도 남습니다. 신용카드 등록도 필요 없어요.
2. 코드를 GitHub에 올리기
이미 github.com/urstory/board-app에 올라가 있다면 이 단계를 건너뛰어도 됩니다. 처음이라면 자기 계정으로 새 저장소를 하나 만들어 둘게요.
GitHub에서 새 저장소를 만들면 됩니다. 이름은 board-app으로 합시다. 저장소를 만든 뒤, 로컬 프로젝트 폴더에서 다음 명령어를 실행해요.
cd board-app git init git add . git commit -m "first commit" git branch -M main git remote add origin https://github.com/<본인계정>/board-app.git git push -u origin main
<본인계정> 부분은 자기 GitHub 사용자명으로 바꿔주세요. 푸시가 끝나면 브라우저에서 저장소 페이지를 새로고침해서 파일들이 잘 올라갔는지 확인합니다.
확인 포인트: GitHub 저장소에
index.html,package.json,src/폴더 등이 보이면 OK.node_modules는 올라가면 안 됩니다. 안 올라갔다면.gitignore가 잘 동작한 거예요.
3. 코드가 API를 어떻게 호출하는지 확인하기
본격적으로 배포에 들어가기 전에, 우리 코드가 API를 어떻게 호출하고 있는지 한 번 짚고 갈 필요가 있어요. 여기를 이해하지 못하고 그냥 배포하면 "로컬에서는 잘 되는데 배포 사이트에서는 로그인이 안 된다" 같은 함정에 빠질 수 있거든요.
board-app/src/utils/api.js 파일의 첫 줄을 보면 이렇게 되어 있습니다.
const BASE_URL = 'https://api.fullstackfamily.com/api/edu/ws-283fc1'
https://로 시작하는 절대 경로예요. 브라우저가 이걸 보고 곧장 api.fullstackfamily.com으로 요청을 보냅니다. 우리 사이트 도메인(localhost:5173이든 board-app-rho.vercel.app이든)을 거치지 않고요.
왜 절대 경로로 적어두었나요?
/api/edu/ws-283fc1 같은 상대 경로로도 같은 일을 할 수 있긴 해요. 그런데 그렇게 하면 한 가지 문제가 생깁니다. 브라우저가 "이 경로는 내가 지금 떠 있는 사이트 도메인의 일부"라고 해석해 버려요. 그러면 다음 같은 차이가 생깁니다.

왼쪽처럼 개발 환경에서는 Vite 개발 서버에 프록시 설정을 끼워 넣으면, 개발 서버가 중간에서 /api/... 요청을 가로채 진짜 API 서버로 다시 보내줍니다. 잘 돌아가요. 하지만 배포 환경(오른쪽)에는 그 중간자가 없습니다. Vercel은 정적 파일만 서빙하니까요. 그래서 /api/edu/ws-283fc1/posts 같은 요청이 board-app-rho.vercel.app/api/...로 향해버리고, 그런 경로는 존재하지 않으니까 404가 떨어집니다.
해결 방법은 두 가지예요.
- Vercel에 프록시 규칙을 알려주기 (
vercel.json의rewrites) - API를 처음부터 직접 호출하도록 코드를 작성하기
이 글의 board-app은 2번 방식으로 만들어져 있습니다. BASE_URL이 절대 경로니까 개발 환경이든 배포 환경이든 똑같이 동작해요. 그래서 vite.config.js에도 별도의 프록시 설정이 필요 없습니다.
import { defineConfig } from 'vite' import tailwindcss from '@tailwindcss/vite' export default defineConfig({ plugins: [ tailwindcss(), ], })
이게 더 직관적이고, Vercel이 아닌 Netlify나 Cloudflare Pages 같은 다른 정적 호스팅으로 옮겨도 코드를 손대지 않아도 되거든요.
단, CORS는 따로 챙겨야 합니다
브라우저가 다른 도메인의 서버를 직접 호출하려면 그 서버가 응답 헤더에 "이 출처에서 오는 요청은 받아도 돼"라는 표시(Access-Control-Allow-Origin)를 같이 내려줘야 합니다. 이걸 CORS(Cross-Origin Resource Sharing)라고 해요.
fullstackfamily의 학습용 API 서버는 Vite 기본 포트(http://localhost:5173)만 CORS로 허용해 두었습니다. 그래서 로컬 개발은 바로 되지만, 배포한 Vercel 도메인(https://board-xxx.vercel.app)에서 호출하려면 API 운영자에게 본인의 도메인을 CORS 허용 목록에 추가해 달라고 요청해야 해요. 이 글에서는 그 등록까지 받았다는 가정 아래 진행하겠습니다.
본인이 직접 만든 백엔드를 배포한다면, 서버 쪽에서 본인 사이트 도메인을 CORS 허용 목록에 추가해 두면 됩니다. CORS 설정은 6번 섹션 "Vercel이 만들어주는 세 종류의 URL 이해하기"에서 좀 더 다룰게요.
로컬에서 동작 확인
여기까지 이해했다면 로컬에서 한번 잘 돌아가는지 확인해 봅시다. 반드시 기본 포트인 5173으로 띄워야 해요. 학습용 API가 이 포트만 허용하니까요.
npm run dev
브라우저에서 http://localhost:5173으로 접속해서 게시글 목록이 뜨면 OK. 로그인까지 한번 해보면 더 확실해요. 브라우저 개발자 도구의 네트워크 탭을 열어보면, 요청 URL이 https://api.fullstackfamily.com/...로 찍히는 게 보일 겁니다.
확인 포인트: 네트워크 탭에서 요청이
api.fullstackfamily.com으로 향하고 200 OK가 떨어지면 정상입니다. 콘솔에 "blocked by CORS policy" 같은 빨간 메시지가 보인다면 포트가 5173이 아닌 다른 포트로 떠 있을 가능성이 커요. 다른 프로세스가 5173을 점유하고 있다면 끄고 다시 띄워주세요.
4. Vercel 가입하기
이제 본격적으로 Vercel에 들어갑시다. vercel.com에 접속해서 오른쪽 위 Sign Up 버튼을 누릅니다.
가입 방식이 여러 개 나오는데, Continue with GitHub를 선택하세요. 이렇게 해야 나중에 GitHub 저장소를 연결하기가 훨씬 편합니다.
GitHub 계정으로 로그인하면 Vercel이 권한을 요청해요. Authorize Vercel을 눌러 승인합니다. 그다음 화면에서 이름과 사용자명을 적당히 적어주면 가입이 끝나요. Hobby(무료) 플랜을 선택하고 진행합니다.
대시보드 화면이 나오면 가입 성공입니다.
확인 포인트: 화면 왼쪽 위에 본인 이름이나 사용자명이 보이면 OK.
5. GitHub 저장소 연결해서 첫 배포
가입을 마치면 Vercel은 "New Project"라는 화면으로 안내해 줍니다. Let's build something new라는 큰 문구 아래로 두 개의 영역이 나란히 보일 거예요. 왼쪽이 Import Git Repository(기존 저장소 가져오기), 오른쪽이 Clone Template(템플릿으로 새로 시작)입니다. 우리는 GitHub에 이미 board-app을 올려뒀으니 왼쪽 영역만 쓰면 돼요.
5-1. GitHub App 설치 (처음 한 번만)
먼저 Vercel에게 "내 GitHub 저장소를 들여다봐도 된다"고 권한을 줘야 합니다. 이 단계는 처음 한 번만 거치면 다음부터는 자동이에요.
왼쪽 Import Git Repository 영역 안에 세 개의 버튼이 있어요. 그중 ❶번이 표시된 Continue with GitHub 버튼을 클릭합니다.

GitLab이나 Bitbucket을 쓰는 분이라면 그 아래 두 개의 버튼이 같은 역할을 해요. 우리는 GitHub 기준으로 갈게요.
버튼을 누르면 새 창이 뜨면서 GitHub의 Install Vercel 페이지로 이동합니다. 여기서 두 가지를 결정해야 해요. 하나는 "어떤 계정에 설치할지", 다른 하나는 "어떤 저장소까지 권한을 줄지"입니다.

❶ Only select repositories를 선택합니다. 위쪽 All repositories를 고르면 내 모든 저장소(미래에 만들 것까지 포함)에 권한이 가니까, 보안상 필요한 것만 골라 주는 게 좋아요.
❷ 그러면 Select repositories 드롭다운이 활성화됩니다. 클릭해서 목록을 펼친 다음 board-app을 찾아 선택합니다.
❸ 추가된 저장소(urstory/board-app)가 목록에 나타나면 OK. 페이지를 아래로 스크롤해서 Install 버튼을 누르면 권한 설치가 끝납니다.
설치가 끝나면 자동으로 Vercel 창으로 돌아가요. 이제 같은 New Project 화면이 다른 모습으로 바뀌어 있을 겁니다.

왼쪽 영역에 계정 셀렉터(urstory)와 함께 방금 권한을 준 board-app 저장소가 보일 거예요. 그 줄 오른쪽의 Import 버튼을 클릭하면 다음 단계로 넘어갑니다.
저장소가 안 보일 때: 화면 아래쪽의 Adjust GitHub App Permissions 링크를 클릭해서 권한을 다시 설정할 수 있어요. 5-1에서 다른 저장소를 선택했거나 원하는 저장소를 빠뜨린 경우에 유용합니다.
5-2. 프로젝트 설정 확인하고 배포
Import 버튼을 누르면 New Project 설정 화면이 나타납니다. Vercel이 board-app의 코드를 미리 읽어 본 다음, 빌드에 필요한 값을 자동으로 채워 둔 상태예요. 우리는 그 값들이 맞는지 한 번만 훑어보면 됩니다.

- Importing from GitHub:
urstory/board-app의main브랜치를 가져온다는 안내. 우리가 푸시한 그 저장소가 맞는지 확인합니다. - Vercel Team:
urstory's projects로 표시되어 있고 옆에 Hobby 배지가 있어요. 무료 플랜으로 진행한다는 뜻이니 그대로 두면 됩니다. - Project Name: 자동으로
board-app이 채워져 있습니다. 다른 이름을 쓰고 싶으면 여기서 바꿀 수 있어요. 이 이름이 나중에 프로덕션 URL의 일부가 됩니다. - Application Preset: Vite가 자동으로 잡혀 있어요. Vercel이
package.json을 보고 알아서 인식한 거예요. 그대로 둡니다. - Root Directory:
./로 지정되어 있는데, 저장소 루트에package.json이 있는 우리 같은 경우엔 이게 정답입니다. - Build and Output Settings: 접혀 있는 영역이에요. Vercel이 Vite 프리셋에 맞춰 빌드 명령어(
npm run build)와 출력 디렉터리(dist)를 자동으로 설정해 둡니다. 클릭해서 펼쳐보면 그 값들이 회색으로 비활성화되어 있을 거예요. 손댈 필요 없습니다. - Environment Variables: board-app은 환경 변수가 없으니까 비워두면 돼요.
전부 확인했으면 가장 아래의 검은색 Deploy 버튼을 클릭합니다.
이제 Vercel이 빌드 로그를 한 줄씩 보여주면서 빌드를 진행해요. 1~2분쯤 걸립니다. 빌드가 끝나면 폭죽 같은 축하 화면이 뜨고, 미리보기 이미지와 함께 사이트로 가는 링크가 표시될 거예요.
확인 포인트: 빌드 로그 마지막에 "Deployment completed" 같은 메시지와 함께 초록 체크가 뜨면 성공입니다. 빨간 X와 함께 빌드가 실패하면 로그를 위로 올려 어떤 단계에서 멈췄는지 확인하세요. 대부분
package.json의dependencies또는devDependencies에 빠진 패키지가 원인이에요.
6. Vercel이 만들어주는 세 종류의 URL 이해하기
배포가 끝났으니 Vercel 프로젝트의 Overview 화면을 열어봅시다. 이 화면 한 장에서 우리 배포에 관한 핵심 정보가 다 보여요.

❶ 왼쪽 사이드바의 Overview가 지금 우리가 보고 있는 메뉴예요. 그 아래로 Deployments, Logs, Analytics, Domains, Settings 같은 다른 메뉴들이 쭉 보입니다. 처음에는 Overview 하나만 알면 됩니다.
가운데에는 Production Deployment라는 큰 박스가 있고, 오른쪽 패널에 우리가 알아야 할 정보가 모여 있어요. 여기서 처음 본 사람이 헷갈리는 게 등장합니다. URL이 두 군데에 다르게 적혀 있다는 점이에요.
❷ Domains 항목에 적힌 board-app-rho.vercel.app — 우리가 기억해야 할 진짜 사이트 주소입니다.
❸ Deployment 항목에 적힌 board-ksqo5nom9-urstorys-projects.vercel.app — 똑같이 우리 사이트인 것 같은데 모양이 영 달라요.
거기에 더해 사실은 또 다른 URL도 같이 발급되어 있어서, 정리하면 한 프로젝트에 다음 같은 도메인들이 동시에 살아 있습니다.
board-app-rho.vercel.app board-app-git-main-urstorys-projects.vercel.app board-ksqo5nom9-urstorys-projects.vercel.app
왜 이렇게 여러 개를 주는 걸까요? 각각 역할이 다르기 때문이에요.
| 도메인 모양 | 종류 | 무엇을 가리키는가 | 변하는가 |
|---|---|---|---|
board-app-rho.vercel.app | 프로덕션 별칭 | 현재 프로덕션 배포 | 새 배포 때마다 자동 갱신 |
board-app-git-main-... | 브랜치 별칭 | 특정 브랜치(여기선 main)의 최신 배포 | 그 브랜치에 푸시할 때마다 갱신 |
board-ksqo5nom9-... | 배포 고유 URL | 특정 빌드 하나 | 영원히 안 변함 (immutable) |
비유하자면 이렇습니다.
프로덕션 별칭 = 회사 대표 전화번호 (변하지 않음, 항상 최신 응대) 브랜치 별칭 = 부서 직통 번호 (해당 부서 사람들이 응대) 배포 고유 URL = 특정 직원의 사번 (그 사람만 영구적으로 가리킴)
각각 언제 쓰나요?
- 프로덕션 별칭 — 친구한테 공유하거나 명함에 적을 URL이에요. 항상 최신 코드를 보여줍니다. 일반적으로 이 URL을 "내 사이트 주소"라고 생각하면 돼요.
- 브랜치 별칭 — 특정 브랜치의 상태를 보고 싶을 때 씁니다. 예를 들어
feature/login브랜치를 푸시하면board-app-git-feature-login-...같은 URL이 자동으로 만들어져요. PR 코드 리뷰할 때 정말 유용합니다. - 배포 고유 URL — "어제 그 버전 그대로" 같이 특정 시점의 결과물을 보존해야 할 때 사용해요. 롤백, 디버깅, 옛날 데모 공유 같은 용도예요. 한 번 만들어진 뒤에는 절대 변하지 않습니다.
흔히 빠지는 함정: "옛날 URL"의 화석
이 시스템 때문에 처음 배포해보는 사람이 자주 겪는 혼란이 있어요. 코드를 고치고 푸시했는데 "왜 사이트가 안 바뀌지?" 싶을 때예요.
원인은 대부분 이전 배포의 고유 URL을 보고 있기 때문입니다. 그 URL은 영원히 옛날 코드를 가리키니까요. Vercel은 정상적으로 새 배포를 만들었지만, 그건 다른 URL에 살아 있는 거예요.
새 코드를 확인하고 싶을 때는 항상 프로덕션 별칭 또는 Deployments 탭의 가장 위 항목을 보세요. 그게 항상 최신입니다.
CORS 설정과의 관계
API 서버에서 CORS 허용 목록을 관리할 때도 이 차이를 알아두면 편해요. 기본적으로 프로덕션 별칭 하나만 등록해 두면 됩니다.
http://localhost:5173 ← 로컬 개발용 https://board-app-rho.vercel.app ← 라이브 사이트
PR 미리보기까지 적극적으로 활용하실 거라면 브랜치 별칭도 같이 등록하거나, 백엔드에서 정규식 패턴으로 한 번에 풀어둘 수 있어요. Spring Boot라면 다음과 같은 식이에요.
@Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**") .allowedOriginPatterns( "http://localhost:5173", "https://board-app-*.vercel.app", "https://board-app-git-*-urstorys-projects.vercel.app" ) .allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS") .allowCredentials(true) .maxAge(3600); } }
배포 고유 URL은 푸시할 때마다 새로 생기기 때문에 등록해도 의미가 없어요. 변하지 않는 별칭만 신경 쓰면 됩니다.
확인 포인트: Vercel 프로젝트 → Settings → Domains에 들어가서 본인의 프로덕션 별칭을 확인하세요. 그걸 즐겨찾기에 저장해두고, 친구한테 공유할 때도 이 URL을 보내면 됩니다.
7. 자동 배포 확인하기
사실 여기까지 왔으면 한 가지 짚을 게 있어요. 이미 자동 배포가 켜져 있습니다.
Vercel이 GitHub 저장소를 import할 때 푸시 이벤트를 감지하는 webhook을 자동으로 달아둬요. 한번 확인해 봅시다. 아무 파일이나 살짝 고쳐볼게요. index.html의 <title>을 바꿔봅니다.
<title>나의 게시판</title>
저장하고 푸시합니다.
git add index.html git commit -m "change title" git push
Vercel 대시보드의 Deployments 탭을 새로고침해 보세요. 새 배포가 진행 중인 게 보일 거예요. 1~2분 뒤에 사이트를 새로고침하면 탭 제목이 바뀌어 있습니다.
여기까지 왔다면 사실 자동 배포는 끝난 셈입니다. Vercel은 이걸 "Git Integration"이라고 부르고, 공식 문서에서도 이 방식을 먼저 권합니다. 개인 프로젝트나 학습용으로 배포하는 거라면 여기서 멈춰도 충분해요. 다음 8단계는 건너뛰고 9단계 마무리로 바로 가셔도 됩니다.
그런데도 굳이 GitHub Actions를 따로 쓰는 경우가 있거든요. 다음 단계는 "나중에 회사 프로젝트에서 필요해질 수 있는" 진화 버전을 미리 한 번 보고 가는 차원에서 읽어주세요.
8. GitHub Actions로 명시적 배포 파이프라인 구성
Vercel의 기본 Git Integration도 편리하지만, 다음과 같은 상황이라면 GitHub Actions가 더 낫습니다.
- 배포 전에 테스트나 린트를 먼저 돌리고, 통과해야만 배포하고 싶을 때
- 배포를 다른 작업과 묶어서 관리하고 싶을 때 (Slack 알림, 빌드 결과 업로드 같은 거요)
- Vercel뿐 아니라 다른 곳에도 동시에 배포하고 싶을 때
- 배포 이력이 GitHub의 Actions 탭에서도 보이길 원할 때
GitHub Actions로 직접 배포하려면 Vercel의 자동 배포는 끄고, 대신 워크플로우 안에서 Vercel CLI를 호출하면 됩니다.
8-1. 자동 Git 배포 끄기
Vercel 프로젝트의 Settings → Git 메뉴로 들어갑니다. 페이지를 아래로 내리면 Vercel Bot이나 Auto-deploy 비슷한 이름의 토글이 있어요. 그걸 끄면 됩니다.
토글이 안 보이면 그대로 두어도 괜찮아요. GitHub Actions로 배포하면 같은 커밋이 두 번 배포될 뿐, 동작에는 문제가 없습니다. 신경 쓰이면 나중에 Git Integration을 disconnect 하면 돼요.
8-2. Vercel 토큰 발급
GitHub Actions가 우리 대신 Vercel에 배포하려면 인증 토큰이 필요해요. Vercel 오른쪽 위 프로필 → Account Settings → Tokens로 이동합니다.
Create Token 버튼을 누르고 다음을 입력합니다.
- Token Name:
github-actions(구분용 이름이라 자유) - Scope: 본인 계정
- Expiration:
No Expiration또는 원하는 기간
Create 버튼을 누르면 토큰 문자열이 한 번만 표시됩니다. 복사해서 메모장 같은 데 잠깐 붙여두세요. 다시 보여주지 않아요.
8-3. 프로젝트 ID와 조직 ID 알아내기
Vercel CLI를 한 번만 로컬에서 실행해서 프로젝트 ID를 받아옵니다. 터미널에서 board-app 폴더 안에 들어가 다음을 실행합니다.
npm install -g vercel vercel login vercel link
vercel login은 이메일을 입력하고 메일함에서 인증 링크를 클릭하면 됩니다. vercel link는 "이 폴더를 어떤 Vercel 프로젝트에 연결할까?"를 물어봐요. 이미 만들어 둔 board-app 프로젝트를 선택합니다.
링크가 끝나면 폴더 안에 .vercel이라는 숨김 폴더가 생겨요. 그 안의 project.json 파일을 열어보면 두 개의 값이 있습니다.
{ "projectId": "prj_xxxxxxxxxxxxxxxxxxxxxxxx", "orgId": "team_xxxxxxxxxxxxxxxxxxxxxxxx" }
이 두 값을 메모해 두세요. 그리고 .vercel 폴더는 GitHub에 올리면 안 되니까 .gitignore에 추가합니다.
echo ".vercel" >> .gitignore git add .gitignore git commit -m "ignore .vercel"
8-4. GitHub Secrets 등록
이제 토큰과 ID 값들을 GitHub 저장소의 비밀 변수로 등록합니다. 코드에 직접 적으면 누구나 볼 수 있으니 절대 안 돼요.
GitHub의 board-app 저장소 → Settings → Secrets and variables → Actions → New repository secret을 누르고, 다음 세 개를 차례로 등록합니다.
| Name | Value |
|---|---|
VERCEL_TOKEN | 8-2단계에서 발급받은 토큰 |
VERCEL_ORG_ID | project.json의 orgId 값 |
VERCEL_PROJECT_ID | project.json의 projectId 값 |
각각 입력하고 Add secret을 누르면 됩니다.
확인 포인트: Secrets 목록에 세 개 모두 보이면 됩니다. 값은 등록 이후엔 다시 볼 수 없으니 메모해 둔 토큰이 맞는지 등록 전에 한 번 더 확인하세요.
8-5. 워크플로우 파일 작성
프로젝트 루트에 .github/workflows/deploy.yml 파일을 만듭니다.
mkdir -p .github/workflows
그리고 다음 내용을 넣습니다.
name: Deploy to Vercel on: push: branches: - main env: VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }} jobs: deploy: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: 20 cache: npm - name: Install dependencies run: npm ci - name: Install Vercel CLI run: npm install -g vercel - name: Pull Vercel environment run: vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }} - name: Build project run: vercel build --prod --token=${{ secrets.VERCEL_TOKEN }} - name: Deploy to Vercel run: vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }}
워크플로우 전체 모양을 그림으로 보면 이렇습니다.

위에서 아래로 6단계가 차례로 실행되고, 마지막 단계가 끝나면 라이브 사이트가 갱신되는 구조예요. 각 단계가 하는 일을 짚어볼게요.
- Checkout: 저장소의 코드를 워크플로우 환경으로 가져옵니다.
- Setup Node.js: Node 20을 설치하고 npm 캐시도 챙겨둡니다.
- Install dependencies:
npm ci는package-lock.json을 정확히 따라가는 설치 명령어예요. CI 환경에서는npm install보다 안전합니다. - Pull Vercel environment: Vercel 프로젝트의 환경 변수와 설정을 워크플로우로 가져옵니다.
- Build project: Vercel 빌더로 빌드해서 결과물을
.vercel/output에 만듭니다. - Deploy to Vercel: 빌드된 결과물을 그대로 배포합니다.
--prebuilt플래그가 핵심이에요. 빌드를 다시 하지 않고 이미 만든 결과물만 올리는 거죠.
8-6. 푸시해서 동작 확인
저장하고 푸시합니다.
git add .github/workflows/deploy.yml git commit -m "add github actions deploy workflow" git push
GitHub 저장소의 Actions 탭으로 가면 "Deploy to Vercel"이라는 워크플로우가 노란 점을 깜빡이며 돌고 있어요. 클릭해서 들어가면 단계별 로그를 실시간으로 볼 수 있습니다.
3~4분 뒤 초록색 체크 표시가 뜨면 성공이에요. Vercel 대시보드에서도 새 배포가 추가된 게 보입니다.
이제 진짜로 다음 흐름이 완성됐어요.
코드 수정 → git push → GitHub Actions 빌드 → Vercel 배포 → 라이브 사이트 갱신
확인 포인트: Actions 탭에 초록색 체크가 뜨고, 라이브 사이트가 새 변경사항으로 갱신되면 성공입니다. 빨간 X가 뜨면 로그를 펼쳐서 어느 단계에서 실패했는지 확인하세요.
9. 마무리하며
여기까지 왔다면 다음을 갖춘 셈이에요.
- 인터넷 어디서나 접속 가능한 무료 사이트
- HTTPS 자동 적용
git push한 번이면 자동으로 배포되는 파이프라인- 배포 이력이 GitHub Actions와 Vercel 양쪽에 남는 추적성
처음에 쓴 한 줄 다이어그램을 다시 봅시다.
git push → GitHub → GitHub Actions → Vercel → https://board-app-xxx.vercel.app
이 흐름은 board-app 같은 토이 프로젝트뿐 아니라 회사에서 운영하는 실제 서비스에서도 거의 같은 모양으로 씁니다. 한번 손에 익혀두면 다음 프로젝트는 30분 만에 올릴 수 있어요.
직접 해볼 만한 것도 몇 가지 남겨둘게요.
- 커스텀 도메인 연결하기 — Vercel 프로젝트 Settings → Domains에서 본인이 산 도메인을 연결할 수 있어요. DNS 설정만 가이드대로 따라 하면 됩니다.
- Pull Request 미리보기 — main이 아닌 브랜치를 푸시하면 Vercel이 자동으로 임시 미리보기 URL을 만들어줘요. 코드 리뷰할 때 유용합니다.
- 빌드 전 테스트 추가 — 워크플로우에
npm test단계를 추가해서 테스트 통과 후에만 배포되도록 만들어보기.
문제 해결
"Build failed: Could not resolve entry module"
vite.config.js나 index.html이 프로젝트 루트에 없는 경우입니다. board-app 폴더 안에서 직접 import 했는지 확인하세요.
배포는 됐는데 로그인 시 404 에러가 발생해요
3단계의 api.js 수정이 안 들어간 경우입니다. BASE_URL이 /api/... 같은 상대 경로로 남아 있다면 https://api.fullstackfamily.com/api/...로 바꿔주세요. 변경 후 푸시하면 자동으로 재배포됩니다.
CORS 오류가 발생해요
브라우저 콘솔에 "blocked by CORS policy"라는 빨간 메시지가 뜨는 경우입니다. 두 가지 경우가 있어요.
- 로컬 개발 중이라면:
npm run dev가 5173 포트가 아닌 다른 포트로 떠 있을 가능성이 큽니다. 학습용 API는http://localhost:5173만 허용하거든요. 다른 프로세스가 5173을 점유하고 있다면 그걸 끄고 다시 띄우세요. - Vercel 배포 사이트라면: 본인의 Vercel 도메인이 API 서버의 CORS 허용 목록에 없는 경우예요. 학습용 API라면 운영자에게 본인의
*.vercel.app도메인을 등록해 달라고 요청해야 합니다. 본인이 만든 백엔드라면 서버 쪽 응답 헤더Access-Control-Allow-Origin에 본인 사이트 도메인을 추가하면 돼요.
Actions에서 "VERCEL_TOKEN is not set" 오류
GitHub Secrets 이름이 정확히 VERCEL_TOKEN인지 확인하세요. 대소문자도 정확히 일치해야 합니다. 또한 secrets는 fork된 PR에서는 보안상 제공되지 않으니, 워크플로우는 직접 푸시한 브랜치에서만 동작해요.
vercel pull 단계에서 권한 오류
VERCEL_ORG_ID와 VERCEL_PROJECT_ID 값이 잘못 들어간 경우입니다. 로컬에서 vercel link를 다시 실행해 새 .vercel/project.json을 확인하고, GitHub Secrets를 갱신하세요.
빌드는 성공하는데 빈 화면이 나타나요
브라우저 개발자 도구의 콘솔과 네트워크 탭을 확인합니다. 대부분 /api 요청 실패이거나, 절대 경로로 import 한 파일을 찾지 못해서 발생해요. 콘솔에 찍힌 오류 메시지를 그대로 검색해 보면 답이 빨리 나옵니다.






댓글
댓글을 작성하려면 이 필요합니다.