목차
- 1. 왜 Vercel에서 GitLab CI/CD로 옮기게 됐는가
- 2. Vercel과 GitLab CI/CD의 차이, 쉽게 설명해보면
- 3. 마이그레이션 전에 먼저 체크한 항목
- 4. GitLab CI/CD로 기본 파이프라인 구성하기
- 4-1. 기본 디렉터리와 환경 준비
- 4-2. 정적 파일 서버로 배포하는 예시
- 5. 프리뷰 배포와 브랜치 전략은 어떻게 바꿨는가
- 6. ⚠️ 실제로 겪었던 문제와 트러블슈팅
- 6-1. SPA 라우팅이 깨지는 문제
- 6-2. 환경 변수 이름이 달라서 빌드가 실패한 문제
- 6-3. 캐시 때문에 이전 빌드 결과가 섞이는 문제
- 6-4. 배포는 성공인데 서비스는 실패한 문제
- 7. 검증은 이렇게 했습니다
- 8. 그래서 누구에게 적합한가: 선택 기준 정리
- 9. 마무리: 배포 도구보다 중요한 건 운영 기준입니다
- 자주 묻는 질문
- Q1. Vercel에서 GitLab CI/CD로 옮기면 무조건 비용 절감이 되나요?
- Q2. 프리뷰 배포가 꼭 필요하면 GitLab CI/CD는 불리한가요?
- Q3. 가장 먼저 검증해야 할 한 가지는 뭔가요?
[DevOps] Vercel GitLab CI/CD 마이그레이션 실제 경험과 고려사항
프론트엔드 배포를 빠르게 시작할 때는 Vercel이 정말 편합니다. 저도 처음엔 Git push만 하면 미리보기 배포(Preview Deployment, 변경사항 확인용 임시 배포)가 바로 올라오는 흐름이 너무 좋아서 한동안 만족하면서 썼거든요. 그런데 서비스가 조금씩 커지고, 백엔드와 인프라 정책까지 같이 맞춰야 하다 보니 Vercel GitLab CI/CD 마이그레이션을 진지하게 검토하게 되더라고요. 특히 팀에서 이미 GitLab을 중심으로 이슈, 머지 리퀘스트(Merge Request, 코드 리뷰 요청), 배포 이력을 관리하고 있다면 CI/CD 전환 자체가 단순한 툴 변경이 아니라 DevOps 워크플로우를 정리하는 작업이 됩니다. 이번 글에서는 제가 직접 정리하면서 겪었던 판단 포인트, 삽질했던 부분, 그리고 안정적으로 옮기는 방법을 차근차근 풀어보겠습니다.
Vercel 중심 배포에서 GitLab CI/CD 중심 배포로 흐름이 바뀌는 전체 구조를 보여주는 이미지입니다.
1. 왜 Vercel에서 GitLab CI/CD로 옮기게 됐는가
쉽게 말해, Vercel은 프론트엔드 배포 경험을 극도로 단순화해주는 플랫폼이고, GitLab CI/CD는 배포 과정을 내가 더 많이 통제할 수 있게 해주는 자동화 파이프라인입니다. 둘 중 뭐가 절대적으로 낫다기보다는, 팀 상황에 따라 기준이 달라집니다.
제가 마이그레이션을 고민한 가장 큰 이유는 세 가지였습니다.
- 배포 흐름 통합: 프론트엔드만 따로 Vercel에 있으면, 백엔드 배포와 인프라 변경 이력이 분리되기 쉽습니다.
- 권한과 정책 일원화: GitLab 프로젝트 권한, 브랜치 보호(Protected Branch), 승인 규칙을 한 곳에서 다루는 게 편하더라고요.
- 비용 절감: 서비스 규모와 팀 사용 방식에 따라 별도 플랫폼 비용보다 기존 GitLab Runner(러너, 작업 실행기)를 활용하는 쪽이 더 맞을 때가 있습니다.
여기서 중요한 포인트! CI/CD 전환은 단순히 배포 속도만 보는 게 아닙니다. 로그를 어디서 볼지, 실패 시 누가 복구할지, 시크릿(Secret, 비밀값)을 어디서 관리할지까지 같이 봐야 합니다.
2. Vercel과 GitLab CI/CD의 차이, 쉽게 설명해보면
저도 처음엔 이게 뭔가 싶었는데, 아주 단순하게 비유하면 이렇습니다.
- Vercel: 잘 차려진 배포 전문 주방입니다. 재료만 넣으면 빠르게 요리가 나옵니다.
- GitLab CI/CD: 주방을 직접 설계할 수 있습니다. 대신 가스불, 조리 순서, 청소 방식까지 내가 정해야 합니다.
그래서 소규모 프로젝트나 정적 사이트(Static Site, 서버 렌더링 없이 빌드 결과물만 배포하는 형태)는 Vercel이 아주 매력적입니다. 반대로 프론트엔드 빌드, 테스트, 컨테이너 이미지(Container Image), 쿠버네티스(Kubernetes, 컨테이너 오케스트레이션) 배포까지 한 줄로 이어야 한다면 GitLab CI/CD 쪽이 더 자연스러울 수 있습니다.
| 항목 | Vercel | GitLab CI/CD |
|---|---|---|
| 초기 설정 | 매우 간단 | 직접 설계 필요 |
| 프론트엔드 미리보기 | 강점 | 직접 구현 필요 |
| 배포 통제력 | 플랫폼 기준 | 높음 |
| 조직 내 표준화 | 분리 운영 가능성 | GitLab 중심 통합 유리 |
| 확장성 | 프론트엔드 친화적 | 전체 파이프라인 확장 유리 |
3. 마이그레이션 전에 먼저 체크한 항목
실제로 써보니까, 코드를 옮기는 것보다 현재 Vercel이 대신 해주던 것을 목록화하는 게 훨씬 중요했습니다. 이걸 빼먹으면 나중에 꼭 터집니다 ㅎㅎ
- 빌드 명령: 예를 들어
npm run build또는pnpm build가 정확히 무엇을 수행하는지 확인합니다. - 출력 디렉터리: 정적 결과물이
dist,build,out중 어디에 생성되는지 봅니다. - 환경 변수(Environment Variable, 실행 환경별 설정값): API URL, 토큰, 공개 키 등을 개발/스테이징/운영으로 나눠 정리합니다.
- 리라이트/리다이렉트: Vercel 설정에 있던 경로 재작성(Rewrite) 규칙이 있다면 웹 서버나 인그레스에서 다시 구현해야 합니다.
- 프리뷰 배포 전략: 머지 리퀘스트마다 미리보기 URL이 꼭 필요한지 결정합니다.
- 도메인과 TLS: 커스텀 도메인(Custom Domain)과 인증서(TLS Certificate) 종료 지점이 어디인지 확인합니다.
이 단계에서 제가 한 실수는, 빌드만 되면 끝이라고 생각한 거였습니다. 근데 실제 운영은 빌드보다 배포 후 라우팅과 환경 변수 관리에서 더 많이 흔들리더라고요.
4. GitLab CI/CD로 기본 파이프라인 구성하기
이제 실전입니다. 여기서는 가장 보편적인 방식으로, 프론트엔드 앱을 빌드한 뒤 정적 파일을 서버나 스토리지로 배포하는 흐름을 예시로 들겠습니다. 프레임워크는 Next.js, React, Vue 등 무엇이든 응용 가능하지만, 설정은 프로젝트 성격에 맞게 조정하셔야 합니다.
4-1. 기본 디렉터리와 환경 준비
먼저 프로젝트 루트에 .gitlab-ci.yml 파일을 둡니다. GitLab Runner가 Node.js 환경에서 의존성을 설치하고, 테스트 후 빌드를 수행하게 만들 겁니다.
stages:
- install
- test
- build
- deploy
variables:
NODE_ENV: production
npm_config_cache: .npm
cache:
paths:
- .npm/
- node_modules/
install:
stage: install
image: node:20
script:
- npm ci
unit_test:
stage: test
image: node:20
script:
- npm ci
- npm run test -- --runInBand
rules:
- if: '$CI_COMMIT_BRANCH'
build_app:
stage: build
image: node:20
script:
- npm ci
- npm run build
artifacts:
paths:
- dist/
expire_in: 1 day
deploy_production:
stage: deploy
image: alpine:latest
script:
- echo "Deploy step runs here"
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
위 예시는 아주 기본 골격입니다. 핵심은 install - test - build - deploy 단계를 분리해서 실패 지점을 명확하게 보는 겁니다. 나중에 장애가 나도 어디서 깨졌는지 바로 보이거든요.
설치, 테스트, 빌드, 배포 단계가 GitLab Runner에서 어떻게 순차 실행되는지 보여주는 이미지입니다.
4-2. 정적 파일 서버로 배포하는 예시
만약 Nginx(엔진엑스, 웹 서버)로 정적 파일을 서빙한다면 이런 식으로 배포 스크립트를 둘 수 있습니다.
#!/usr/bin/env bash
set -euo pipefail
TARGET_DIR="/var/www/my-frontend"
rm -rf "${TARGET_DIR:?}"/*
cp -r dist/* "$TARGET_DIR"/
echo "deploy completed"
그리고 GitLab CI에서는 SSH(Secure Shell, 원격 접속 프로토콜)로 원격 서버에 접속해 배포할 수 있습니다.
deploy_production:
stage: deploy
image: alpine:latest
before_script:
- apk add --no-cache openssh-client rsync
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
script:
- rsync -avz --delete dist/ deploy@your-server:/var/www/my-frontend/
- ssh deploy@your-server "sudo systemctl reload nginx"
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
여기서 중요한 포인트는 시크릿을 코드에 넣지 않는 겁니다. SSH 키, API 토큰, 배포 대상 주소는 GitLab CI/CD Variables에 넣어야 합니다.
5. 프리뷰 배포와 브랜치 전략은 어떻게 바꿨는가
Vercel을 쓰다가 GitLab으로 넘어오면 가장 아쉬운 부분 중 하나가 프리뷰 배포입니다. 저도 이 부분이 꽤 컸습니다. Vercel은 이 경험이 워낙 매끄럽거든요. 근데 GitLab에서도 포기할 필요는 없습니다.
- 옵션 1: 스테이징 환경 하나를 두고, 머지 전 검증은 공용 URL에서 진행
- 옵션 2: 브랜치별 또는 머지 리퀘스트별 임시 환경을 생성
- 옵션 3: 정적 아티팩트만 확인하고 실제 프리뷰 URL은 운영하지 않음
제가 해보니 팀 규모가 크지 않다면, 처음부터 브랜치별 임시 환경을 만들기보다 스테이징 하나를 안정적으로 운영하는 쪽이 훨씬 덜 피곤했습니다. 특히 프론트엔드 배포만 있는 게 아니라 API, 인증, CORS(Cross-Origin Resource Sharing, 교차 출처 요청 정책)까지 얽혀 있으면 프리뷰 환경 증식이 오히려 운영 복잡도를 키우더라고요.
6. ⚠️ 실제로 겪었던 문제와 트러블슈팅
이 섹션은 꼭 넣고 싶었습니다. 마이그레이션 자체보다 여기서 시간을 더 썼거든요.
6-1. SPA 라우팅이 깨지는 문제
React Router 같은 클라이언트 라우팅(Client-side Routing, 브라우저에서 경로 처리)을 쓰는 앱은 새로고침 시 404가 날 수 있습니다. Vercel에서는 비교적 자연스럽게 처리되던 부분이, Nginx에서는 별도 설정이 필요합니다.
location / {
try_files $uri $uri/ /index.html;
}
처음엔 정적 파일만 복사하면 끝인 줄 알았는데, 이 설정 빠져서 새로고침할 때마다 페이지가 죽더라고요. 여기서 좀 삽질했습니다 ㅎㅎ
6-2. 환경 변수 이름이 달라서 빌드가 실패한 문제
Vercel에 등록해 둔 환경 변수와 GitLab Variables 이름이 다르면 빌드는 되는데 런타임에서 깨지기도 하고, 아예 빌드 시점에 실패하기도 합니다. 그래서 저는 아래처럼 체크리스트를 따로 뒀습니다.
NODE_ENVPUBLIC_*또는 프레임워크별 공개 변수 prefix- API 엔드포인트 URL
- 서드파티 인증 키
6-3. 캐시 때문에 이전 빌드 결과가 섞이는 문제
CI 캐시는 속도에는 도움이 되지만, 설정이 애매하면 오히려 독이 됩니다. 의존성 캐시와 빌드 산출물 캐시는 분리해서 보시는 걸 추천드립니다. 저는 한 번은 캐시를 과하게 잡아놔서, 수정했는데도 예전 결과물이 살아남는 바람에 한참 헷갈렸습니다.
6-4. 배포는 성공인데 서비스는 실패한 문제
이거 많이 놓칩니다. 파이프라인이 초록불이라고 서비스가 정상이라는 뜻은 아니거든요. 배포 후 헬스 체크(Health Check, 상태 확인)나 간단한 smoke test(스모크 테스트, 핵심 기능 점검)를 꼭 넣어야 합니다.
배포 로그에서 자주 만나는 오류와 원인 분석 포인트를 시각적으로 정리한 이미지입니다.
7. 검증은 이렇게 했습니다
마이그레이션 후에는 감으로 보면 안 됩니다. 저는 최소한 아래 순서로 확인했습니다.
- 빌드 재현성: 같은 커밋에서 동일한 결과가 나오는지 확인
- 정적 자산 로딩: JS, CSS, 이미지 경로가 깨지지 않는지 확인
- 라우팅: 직접 URL 접근과 새로고침 테스트
- 환경별 설정: 개발/스테이징/운영에서 API 호출 대상이 올바른지 확인
- 롤백 가능성: 이전 결과물로 빠르게 되돌릴 수 있는지 점검
여기서 제가 특히 중요하게 본 건 롤백 전략이었습니다. Vercel은 비교적 되돌리기 경험이 좋았는데, GitLab 기반으로 직접 운영할 때는 내가 롤백 절차를 설계해야 하거든요. 배포 디렉터리를 버전별로 보관하거나, 아티팩트를 일정 기간 유지하는 방식이 실무적으로 꽤 유용했습니다.
curl -I https://your-service.example.com/
curl -s https://your-service.example.com/health
아주 단순한 명령이지만, 배포 직후 이 두 개만 자동으로 돌려도 문제를 빨리 찾는 데 도움이 됩니다.
파이프라인 성공 상태와 서비스 헬스 체크 결과를 함께 보여주는 검증 이미지입니다.
8. 그래서 누구에게 적합한가: 선택 기준 정리
결론적으로 Vercel GitLab CI/CD 마이그레이션은 모든 팀에 정답은 아닙니다. 다만 아래에 가깝다면 꽤 의미가 있습니다.
- 프론트엔드, 백엔드, 인프라 배포를 한 플랫폼에서 관리하고 싶은 팀
- 머지 리퀘스트 승인과 배포 이력을 강하게 연결하고 싶은 팀
- 러너 운영이 가능하고, YAML 기반 파이프라인 관리에 거부감이 없는 팀
- 배포 자동화와 권한 모델을 조직 표준에 맞추고 싶은 팀
반대로, 빠른 배포 경험과 프리뷰 환경이 최우선이고 운영 인력이 많지 않다면 Vercel 유지가 더 좋은 선택일 수도 있습니다. 사실 이건 기술 우열보다 운영 철학 차이에 가깝습니다.
| 상황 | 추천 방향 |
|---|---|
| 작은 팀, 프론트엔드 중심, 빠른 배포 우선 | Vercel 유지 검토 |
| 조직 표준 CI/CD 필요, 배포 통합 필요 | GitLab CI/CD 전환 검토 |
| 스테이징/운영 분리와 승인 규칙 중요 | GitLab CI/CD 유리 |
| 프리뷰 경험이 가장 중요 | Vercel 강점 큼 |
도입 난이도, 통제력, 프리뷰 배포, 운영 표준화 관점에서 두 방식을 비교한 요약 이미지입니다.
9. 마무리: 배포 도구보다 중요한 건 운영 기준입니다
이번에 정리하면서 다시 느낀 건, 도구를 바꾸는 것보다 배포 기준을 문서화하는 일이 더 중요하다는 점이었습니다. 제가 직접 해보니 GitLab CI/CD로 옮긴 뒤 얻은 가장 큰 장점은 화려한 기능보다도, 누가 봐도 같은 절차로 배포할 수 있는 상태가 됐다는 거였습니다. 이거 진짜 편하더라고요.
물론 처음엔 귀찮습니다. YAML도 손봐야 하고, 시크릿도 다시 넣어야 하고, 웹 서버 설정도 만져야 하거든요. 근데 한 번 기준을 잡아두면 이후에는 프론트엔드 배포뿐 아니라 배치 작업, 백엔드, 운영 스크립트까지 같은 방식으로 확장하기가 좋습니다. 이게 결국 장기적으로는 비용 절감과 운영 안정성으로 이어집니다.
혹시 지금 CI/CD 전환을 고민하고 계신다면, 먼저 현재 Vercel이 대신 해주고 있는 기능부터 목록으로 적어보세요. 그다음 GitLab CI/CD에서 반드시 재현해야 할 항목과, 과감히 포기해도 되는 항목을 나누는 게 좋습니다. 다음 글에서는 GitLab Runner를 Docker Executor(도커 실행기)로 운영할 때 주의할 점도 다뤄볼 예정입니다. 이전 글에서 다뤘던 Nginx 리버스 프록시 구성과 같이 보시면 흐름 잡는 데 더 도움이 되실 겁니다.
자주 묻는 질문
Q1. Vercel에서 GitLab CI/CD로 옮기면 무조건 비용 절감이 되나요?
꼭 그렇지는 않습니다. Runner 운영 비용, 저장소, 로그 관리, 엔지니어링 시간까지 같이 봐야 합니다. 다만 기존 GitLab 중심 운영 체계가 이미 있다면 중복 도구 비용을 줄이는 효과는 기대할 수 있습니다.
Q2. 프리뷰 배포가 꼭 필요하면 GitLab CI/CD는 불리한가요?
기본 경험은 Vercel이 더 좋다고 느끼는 경우가 많습니다. 대신 GitLab에서도 머지 리퀘스트 기반 임시 환경을 설계할 수 있으니, 팀이 감당할 운영 복잡도와 맞는지 보는 게 중요합니다.
Q3. 가장 먼저 검증해야 할 한 가지는 뭔가요?
저는 라우팅과 환경 변수라고 봅니다. 빌드는 됐는데 실제 서비스가 안 뜨는 경우가 대부분 여기서 나왔습니다. 특히 SPA 라우팅과 공개 환경 변수 prefix는 꼭 확인해보세요.
'IT > Cloud' 카테고리의 다른 글
| [Azure] Azure Cosmos DB 일관성 모델 심층 분석: 데이터 무결성과 성능 최적화 전략 (0) | 2026.07.05 |
|---|---|
| [AWS] AWS VPC 설계 실수, 이대로 괜찮을까? 사례로 보는 개선 방안 (0) | 2026.07.02 |
| [Cloud] FinOps 클라우드 비용 관리 베스트 프랙티스 체크리스트 10가지 (1) | 2026.06.30 |
| [인프라] Ansible을 활용한 프라이빗 네트워킹 자동화 구축 사례 (0) | 2026.06.25 |
| [Cloud] Ollama 클라우드 6개월 후기: 로컬 GPU 없이 LLM 활용 전략 (0) | 2026.06.24 |
| [CI/CD] Kubernetes 환경 Jenkins: 1년 운영하며 겪은 성능 최적화와 안정화 사례 (1) | 2026.06.19 |