GitHub는 저장소를 넘어 배포 도구가 됩니다
지금까지 GitHub를 코드 저장소, 협업 공간, 자동 테스트 실행 도구로 사용했습니다. 이제 한 단계 더 나아가 보겠습니다. GitHub는 완성된 결과물을 공개하고, 버전별로 정리하고, 배포 과정을 자동화하는 데도 사용할 수 있습니다.
대표 기능은 세 가지입니다.
GitHub Pages: 정적 웹사이트를 공개 URL로 배포합니다.
GitHub Releases: 특정 버전을 태그와 릴리스 노트로 관리합니다.
GitHub Actions: 테스트, 빌드, 배포, 릴리스 생성을 자동화합니다.
이 장의 목표는 "코드를 GitHub에 올렸다"에서 끝내지 않는 것입니다. 사용자가 접속할 수 있는 주소를 만들고, v1.0.0 같은 버전으로 결과물을 정리하며, main 브랜치에 병합되면 자동으로 배포되는 흐름까지 이해해 보겠습니다.

GitHub Pages로 정적 사이트 배포하기
GitHub Pages는 HTML, CSS, JavaScript로 구성된 정적 사이트를 호스팅하는 기능입니다. 포트폴리오, 프로젝트 소개 페이지, 문서 사이트, 간단한 프런트엔드 결과물을 공개하기에 좋습니다. GitHub 공식 문서에서도 GitHub Pages를 GitHub 저장소에서 직접 개인·조직·프로젝트 페이지를 호스팅할 수 있는 서비스로 설명합니다.1
가장 단순한 배포 흐름은 다음과 같습니다.
GitHub 저장소를 만듭니다.
index.html,style.css,script.js같은 파일을 저장소에 올립니다.저장소의 Settings → Pages로 이동합니다.
배포 소스를 선택합니다.
GitHub가 제공하는 URL로 접속합니다.
예를 들어 저장소 이름이 my-profile이고 GitHub 아이디가 octocat이라면 보통 다음과 같은 주소가 만들어집니다.
https://octocat.github.io/my-profile/개인 대표 페이지를 만들고 싶다면 저장소 이름을 다음처럼 만들 수도 있습니다.
octocat.github.io이 경우 주소는 더 짧아집니다.
https://octocat.github.io초보자가 가장 자주 하는 실수는 index.html이 없는 상태로 배포하는 것입니다. GitHub Pages는 기본 첫 화면으로 index.html을 찾습니다. 파일 이름이 main.html이나 home.html이면 첫 화면이 바로 열리지 않을 수 있습니다.
일반 HTML 사이트 배포 예시
간단한 정적 사이트라면 빌드 과정도 필요 없습니다. 아래처럼 파일을 준비했다고 해보겠습니다.
my-site/
├─ index.html
├─ style.css
└─ script.jsindex.html에는 다음처럼 CSS와 JavaScript를 연결합니다.
<!doctype html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<title>나의 첫 GitHub Pages</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<h1>Hello GitHub Pages</h1>
<button id="btn">클릭</button>
<script src="script.js"></script>
</body>
</html>이 파일들을 main 브랜치에 올린 뒤, GitHub에서 다음 순서로 설정합니다.
저장소 페이지로 이동합니다.
Settings를 클릭합니다.
왼쪽 메뉴에서 Pages를 클릭합니다.
Build and deployment에서
Deploy from a branch를 선택합니다.Branch를
main, 폴더를/root로 선택합니다.Save를 클릭합니다.
잠시 기다리면 Pages 주소가 표시됩니다. 처음 배포하면 반영까지 몇 분 걸릴 수 있습니다. 바로 404가 보인다고 해서 무조건 실패한 것은 아닙니다.
다만 404가 계속된다면 다음을 확인하세요.
저장소 이름을 잘못 입력하지 않았는가?
Pages 소스 브랜치를 제대로 선택했는가?
index.html파일이 루트 또는 선택한 폴더에 있는가?저장소가 삭제되었거나 권한 문제가 있지는 않은가?
React와 Vite 프로젝트는 빌드 후 배포합니다
HTML, CSS, JavaScript만 있는 사이트는 그대로 올리면 됩니다. 하지만 React나 Vite로 만든 프로젝트는 다릅니다.
React나 Vite 프로젝트에는 JSX, 모듈 번들링, 개발 서버 설정처럼 브라우저가 그대로 실행하기 어려운 개발용 구조가 들어 있습니다. 그래서 배포 전에는 반드시 빌드해야 합니다. Vite 공식 문서도 npm run build를 실행하면 기본적으로 dist 폴더에 배포용 결과물이 만들어진다고 설명합니다.2
Vite 프로젝트라면 보통 다음 명령어를 사용합니다.
npm run build빌드가 성공하면 대개 dist 폴더가 생깁니다.
my-vite-app/
├─ src/
├─ public/
├─ dist/
│ ├─ index.html
│ └─ assets/
└─ package.jsonGitHub Pages에 올려야 하는 것은 src 폴더가 아니라 빌드 결과물입니다. 즉, dist 안에 만들어진 파일들이 실제 배포 대상입니다.
Create React App 기반 프로젝트라면 결과 폴더 이름이 build일 수 있습니다.
build/
├─ index.html
└─ static/정리하면 다음과 같습니다.
| 프로젝트 종류 | 그대로 배포 가능? | 배포 대상 |
|---|---|---|
| HTML/CSS/JS 정적 사이트 | 가능 | 원본 파일 |
| React 프로젝트 | 대개 빌드 필요 | npm run build 결과 |
| Vite 프로젝트 | 빌드 필요 | dist 폴더 |
gh-pages 패키지로 배포하기
React나 Vite 프로젝트에서는 gh-pages 패키지를 사용해 배포할 수도 있습니다. 이 방식은 빌드 결과물을 gh-pages 브랜치에 올리고, GitHub Pages가 그 브랜치를 서비스하도록 하는 방식입니다.
먼저 패키지를 설치합니다.
npm install gh-pages --save-devVite 프로젝트라면 package.json의 scripts에 다음을 추가합니다.
{
"scripts": {
"dev": "vite",
"build": "vite build",
"predeploy": "npm run build",
"deploy": "gh-pages -d dist"
}
}여기서 핵심은 두 줄입니다.
"predeploy": "npm run build",
"deploy": "gh-pages -d dist"npm run deploy를 실행하면 먼저 predeploy가 실행되어 빌드가 되고, 그다음 dist 폴더가 gh-pages 브랜치로 배포됩니다.
npm run deployCreate React App처럼 빌드 폴더가 build라면 다음처럼 씁니다.
{
"scripts": {
"predeploy": "npm run build",
"deploy": "gh-pages -d build"
}
}배포 후 GitHub 저장소에서 Settings → Pages로 이동해 배포 소스를 gh-pages 브랜치로 설정합니다.
다만 요즘은 GitHub Actions를 사용해 빌드 결과물을 artifact로 올리고 Pages에 배포하는 방식도 많이 사용합니다. 뒤에서 이 방법을 함께 살펴보겠습니다.
Vite 배포에서 base 경로 맞추기
Vite 프로젝트를 GitHub Pages에 올릴 때 가장 많이 만나는 문제는 화면이 하얗게 보이거나 CSS와 JavaScript가 로드되지 않는 것입니다. 대부분 경로 문제입니다.
GitHub Pages의 프로젝트 사이트 주소는 보통 다음과 같습니다.
https://사용자명.github.io/저장소명/즉, 사이트가 루트(/)가 아니라 /저장소명/ 아래에서 열립니다. 그런데 Vite가 파일 경로를 /assets/...처럼 루트 기준으로 만들면 GitHub Pages에서 파일을 찾지 못할 수 있습니다.
Vite 공식 문서도 https://<USERNAME>.github.io/<REPO>/ 형태로 배포한다면 base를 /<REPO>/로 설정하라고 안내합니다.2
이때 vite.config.js에 base를 설정합니다.
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react()],
base: '/my-vite-app/'
})여기서 my-vite-app은 GitHub 저장소 이름입니다.
예를 들어 저장소 주소가 다음과 같다면,
https://github.com/octocat/my-vite-appbase는 다음처럼 설정합니다.
base: '/my-vite-app/'사용자 대표 페이지처럼 https://octocat.github.io/ 바로 아래에 배포한다면 base를 생략하거나 /로 두면 됩니다. 프로젝트 페이지와 사용자 페이지의 주소 구조가 다르다는 점을 기억하세요.
이 설정을 바꾼 뒤에는 다시 배포합니다.
npm run deploy실전에서 Pages 배포가 안 될 때는 먼저 세 가지를 확인하세요.
npm run build가 에러 없이 끝났는가?base경로가 저장소 이름과 같은가?GitHub Pages 소스 브랜치가 올바른가?
태그와 릴리스로 버전 관리하기
배포는 "현재 결과물을 공개하는 일"입니다. 릴리스는 "어떤 버전을 공식 결과물로 기록하는 일"입니다.
예를 들어 포트폴리오 사이트를 만들었다고 해보겠습니다.
v1.0.0: 첫 공개 버전v1.1.0: 프로젝트 섹션 추가v1.1.1: 모바일 화면 깨짐 수정v2.0.0: 전체 디자인 개편
이렇게 버전을 붙여 두면 나중에 어떤 시점에 무엇이 바뀌었는지 쉽게 알 수 있습니다.
Git에서는 특정 커밋에 이름표를 붙일 수 있는데, 이것을 태그(tag)라고 합니다.
git tag v1.0.0태그를 GitHub에 올리려면 push가 필요합니다.
git push origin v1.0.0GitHub Releases는 이 태그를 기반으로 릴리스 노트, 첨부 파일, 설치 방법, 변경 사항을 정리하는 기능입니다. GitHub 공식 문서에 따르면 릴리스에는 릴리스 노트, 기여자 언급, 바이너리 파일 링크 등을 포함할 수 있습니다.3
GitHub에서 릴리스를 만드는 기본 순서는 다음과 같습니다.
저장소 오른쪽 또는 상단의 Releases로 이동합니다.
Draft a new release를 클릭합니다.
태그 선택 또는 새 태그를 입력합니다.
릴리스 제목을 작성합니다.
변경 사항을 작성합니다.
필요한 파일을 첨부합니다.
Publish release를 클릭합니다.
릴리스 노트는 길게 쓸 필요 없습니다. 사용자가 알아야 할 내용을 간단히 정리하면 됩니다.
예시는 다음과 같습니다.
## v1.0.0
첫 정식 배포 버전입니다.
### 추가된 기능
- 메인 페이지 추가
- 프로젝트 목록 추가
- 반응형 레이아웃 적용
### 수정된 문제
- 모바일에서 버튼이 겹치던 문제 수정
### 사용 방법
아래 주소에서 확인할 수 있습니다.
https://octocat.github.io/my-profile/초보자에게 추천하는 버전 규칙은 v주.부.수 형식입니다.
v1.0.0각 숫자는 대략 다음 의미로 이해하면 됩니다.
첫 번째 숫자: 큰 변화가 있을 때 증가
두 번째 숫자: 기능이 추가될 때 증가
세 번째 숫자: 버그 수정처럼 작은 변경이 있을 때 증가
처음에는 너무 엄격하게 생각하지 않아도 됩니다. 중요한 것은 "버전별 기록을 남기는 습관"입니다.
Actions로 Pages 배포 자동화하기
수동 배포는 처음 배우기에는 좋습니다. 하지만 매번 npm run build, npm run deploy를 직접 실행하다 보면 실수하기 쉽습니다. 그래서 실무에서는 GitHub Actions로 자동화합니다.
GitHub Pages는 GitHub Actions 워크플로우를 통해 사이트를 빌드하고 배포할 수 있습니다. 공식 문서에서도 custom workflow를 사용하면 빌드 결과물을 artifact로 업로드하고 deploy-pages 액션으로 배포할 수 있다고 설명합니다.4
아래 예시는 main 브랜치에 push될 때 Vite 프로젝트를 빌드하고 GitHub Pages에 배포하는 흐름입니다.
먼저 GitHub 저장소의 Settings → Pages에서 Source를 GitHub Actions로 설정합니다.
그다음 .github/workflows/deploy.yml 파일을 만듭니다.
name: Deploy to GitHub Pages
on:
push:
branches: [main]
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: pages
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Setup Pages
uses: actions/configure-pages@v5
- name: Upload artifact
uses: actions/upload-pages-artifact@v4
with:
path: dist
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4흐름은 단순합니다.
main브랜치에 코드가 올라옵니다.GitHub Actions가 실행됩니다.
Node.js 환경을 준비합니다.
의존성을 설치합니다.
npm run build로 정적 파일을 만듭니다.빌드 결과물을 artifact로 업로드합니다.
GitHub Pages에 배포합니다.
여기서 artifact는 워크플로우 실행 중 만들어진 결과물을 저장하는 파일 묶음입니다. 빌드된 dist 폴더, 테스트 리포트, 압축 파일 등을 artifact로 저장할 수 있습니다. 이렇게 해두면 배포 작업에서 다시 사용하거나, 문제가 생겼을 때 다운로드해 확인할 수 있습니다.
Actions 예제에서 사용하는 액션 버전은 시간이 지나며 바뀔 수 있습니다. 실제 프로젝트에서는 GitHub 공식 문서나 각 Action의 README에서 최신 권장 버전을 확인하는 습관이 좋습니다.
배포용 값은 secrets와 variables로 분리합니다
배포 자동화를 만들다 보면 외부 서비스 토큰, API 키, 서버 주소 같은 값을 워크플로우에 넣어야 할 때가 있습니다. 이때 절대 코드에 직접 쓰면 안 되는 값이 있습니다.
예를 들어 다음 값은 노출되면 위험합니다.
배포 토큰
API 키
비밀번호
클라우드 접근 키
개인 액세스 토큰
이런 값은 GitHub의 Secrets에 저장합니다.
경로는 다음과 같습니다.
Settings → Secrets and variables → Actions → Secrets예를 들어 DEPLOY_TOKEN이라는 secret을 만들었다면 워크플로우에서는 다음처럼 사용합니다.
env:
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}반대로 공개되어도 괜찮은 설정값은 Variables에 넣을 수 있습니다.
예를 들면 다음과 같습니다.
사이트 이름
공개 API 주소
배포 환경 이름
기능 플래그 기본값
env:
SITE_NAME: ${{ vars.SITE_NAME }}간단히 구분하면 됩니다.
| 종류 | 용도 | 예시 |
|---|---|---|
| Secrets | 노출되면 안 되는 값 | API 키, 토큰, 비밀번호 |
| Variables | 공개되어도 되는 설정값 | 사이트 이름, 환경 이름 |
초보자가 기억할 원칙은 하나입니다.
비밀 값은 코드에 쓰지 않습니다. 반드시 Secrets에 넣습니다.
배포와 릴리스의 실전 흐름
이제 전체 흐름을 하나로 연결해 보겠습니다.
작은 프런트엔드 프로젝트를 운영한다고 가정합니다.
feature/header브랜치에서 작업합니다.Pull Request를 만듭니다.
PR에서 테스트가 자동 실행됩니다.
리뷰 후
main에 병합합니다.Actions가 자동으로 빌드하고 Pages에 배포합니다.
안정적인 시점에
v1.0.0태그를 만듭니다.GitHub Releases에 변경 사항을 정리합니다.
명령어로 보면 다음과 같습니다.
git switch main
git pull origin main
git tag v1.0.0
git push origin v1.0.0그다음 GitHub Releases에서 v1.0.0 태그를 선택하고 릴리스 노트를 작성합니다.
## v1.0.0
### 주요 변경 사항
- 첫 정식 배포
- GitHub Pages 배포 설정 추가
- 모바일 레이아웃 개선
### 배포 주소
https://octocat.github.io/my-project/이렇게 하면 사용자는 최신 사이트에 접속할 수 있고, 개발자는 버전별 변경 이력을 추적할 수 있습니다. 문제가 생기면 "언제부터 문제가 생겼는지"를 태그와 릴리스 기준으로 확인할 수 있습니다.
마무리: 저장소에서 제품 관리로
GitHub를 처음 배울 때는 커밋과 푸시만으로도 충분히 어렵습니다. 하지만 실제 프로젝트에서는 코드 저장만으로 끝나지 않습니다. 결과물을 공개해야 하고, 버전을 기록해야 하며, 반복 작업을 자동화해야 합니다.
이 장에서 배운 핵심은 다음과 같습니다.
GitHub Pages는 정적 사이트를 공개하는 데 적합합니다.
React와 Vite 프로젝트는 원본 코드가 아니라 빌드 결과물을 배포합니다.
Vite를 GitHub Pages에 올릴 때는 배포 주소에 맞게
base설정을 확인합니다.Git 태그와 GitHub Releases를 연결하면 버전별 변경 사항을 정리할 수 있습니다.
GitHub Actions를 사용하면
main병합 후 빌드와 배포를 자동화할 수 있습니다.민감한 값은 secrets, 공개 설정값은 variables로 분리합니다.
이제 GitHub는 단순한 코드 보관함이 아닙니다. 프로젝트를 공개하고, 버전을 관리하고, 배포를 자동화하는 운영 도구입니다. 다음 장에서는 이렇게 공개된 프로젝트를 더 안전하게 운영하기 위한 보안과 실무 운영 원칙을 다룹니다.
참고
2Deploying a Static Site - Vite
이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.
