Git Push to Deploy 완벽 가이드 2026: bare repo로 VPS 배포 자동화

이 글에는 제휴 링크(affiliate link)가 포함되어 있습니다. 서버 가입 링크로 가입하시면 추가 비용 없이 크레딧 혜택을 받으실 수 있으며, 블로그 운영에 도움이 됩니다.

git push 한 번에 배포가 끝나는 세계

VPS에 코드를 올릴 때마다 FTP로 파일을 드래그하거나, SSH로 접속해서 git pull을 치고 있지 않으신가요? push-to-deploy는 로컬에서 git push 한 번으로 서버 배포가 끝나는 자동화 패턴입니다. CI/CD 도구(GitHub Actions, Jenkins) 없이도 Git 자체 기능만으로 구축할 수 있어 소규모 프로젝트와 1인 운영에 완벽합니다.

이 튜토리얼에서는 VPS에 bare 저장소를 만들고 post-receive 훅으로 배포를 자동화하는 전체 과정을 다룹니다. Vultr, DigitalOcean, Hetzner 모든 VPS에서 동일하게 적용됩니다.

1. push-to-deploy가 좋은 이유

  • 단순함: git push 한 번이면 배포 완료. 별도 도구 불필요.
  • 롤백: 이전 커밋으로 push하면 즉시 복구. git revert 후 push.
  • 브랜치 배포: main은 운영, dev 브랜치는 스테이징 등 분리 가능.
  • 이력 추적: 누가 언제 무엇을 배포했는지 Git 로그에 전부 기록.

2. VPS에 bare 저장소 만들기

bare 저장소는 워킹 디렉토리가 없는 Git 전용 저장소입니다. push를 받기만 하고 코드를 직접 실행하지 않습니다.

# VPS에서 실행
sudo mkdir -p /srv/git/myapp.git
sudo chown $USER:$USER /srv/git/myapp.git
cd /srv/git/myapp.git
git init --bare

--bare 옵션이 핵심입니다. 이 저장소는 push를 받는 용도입니다.

3. post-receive 훅 작성 (배포 자동화 핵심)

push가 도착하면 자동으로 실행되는 스크립트를 작성합니다:

cat > /srv/git/myapp.git/hooks/post-receive <<'EOF'
#!/bin/bash
set -e
DEPLOY_DIR=/var/www/myapp
GIT_DIR=/srv/git/myapp.git

while read oldrev newrev ref; do
    branch=$(echo "$ref" | sed 's|refs/heads/||')
    if [ "$branch" = "main" ]; then
        echo "Deploying branch: $branch"
        mkdir -p "$DEPLOY_DIR"
        git --work-tree="$DEPLOY_DIR" --git-dir="$GIT_DIR" checkout -f "$branch"
        cd "$DEPLOY_DIR"
        # 의존성 설치 (프로젝트에 맞게 수정)
        # npm install --production
        # pip install -r requirements.txt
        # 서비스 재시작
        sudo systemctl restart myapp
        echo "Deploy complete: $(date)"
    fi
done
EOF

chmod +x /srv/git/myapp.git/hooks/post-receive

이 훅은 main 브랜치에 push가 들어오면 /var/www/myapp으로 코드를 체크아웃하고 서비스를 재시작합니다.

4. 로컬에서 원격 저장소 추가 후 배포

이제 로컬 저장소에 VPS를 배포 원격으로 추가합니다:

# 로컬에서 실행
cd ~/projects/myapp
git remote add deploy user@your-vps-ip:/srv/git/myapp.git

# 배포!
git push deploy main

push가 완료되면 VPS의 post-receive 훅이 자동으로 실행되어 배포가 끝납니다. 이후부터는 git push deploy main 한 줄이면 배포 완료입니다.

5. 롤백 (이전 버전으로 복귀)

문제가 생기면 이전 커밋으로 되돌립니다:

# 로컬에서 이전 커밋으로 리셋 후 push
git reset --hard HEAD~1
git push deploy main --force

주의: --force는 히스토리를 덮어씁니다. 팀 환경에서는 git revert로 새 커밋을 만드는 것이 안전합니다.

6. systemd 서비스 연동

배포 후 자동으로 서비스를 재시작하려면 systemd 서비스가 필요합니다:

sudo tee /etc/systemd/system/myapp.service > /dev/null <<'EOF'
[Unit]
Description=My App
After=network.target

[Service]
Type=simple
User=www-data
WorkingDirectory=/var/www/myapp
ExecStart=/usr/bin/node server.js
Restart=always
RestartSec=5
Environment=NODE_ENV=production

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now myapp

이제 post-receive 훅의 sudo systemctl restart myapp가 배포 후 자동으로 앱을 재시작합니다. systemd에 대한 자세한 내용은 systemd 서비스 관리 완벽 가이드를 참고하세요.

7. SSH 키 인증으로 비밀번호 없이 push

매번 비밀번호를 치지 않으려면 SSH 키를 설정합니다:

# 로컬에서 (키가 없다면)
ssh-keygen -t ed25519
ssh-copy-id user@your-vps-ip

# 이제 비밀번호 없이 push 가능
git push deploy main

push-to-deploy vs GitHub Actions — 언제 뭘 쓰나?

GitHub Actions CI/CD는 테스트 자동 실행, 빌드, 다중 서버 동시 배포가 필요할 때 적합합니다. 반면 이 튜토리얼의 push-to-deploy(bare repo + post-receive)는 단일 서버, 단순 배포에 충분하며 설정이 5분이면 끝납니다. 1인 프로젝트라면 bare repo 방식부터 시작하고, 팀/테스트 자동화가 필요해지면 GitHub Actions로 넘어가세요.

요약

  1. VPS에 git init --bare로 배포 수신 저장소 생성
  2. post-receive 훅으로 push 시 자동 체크아웃 + 서비스 재시작
  3. 로컬에서 git remote add deploygit push deploy main
  4. 롤백은 이전 커밋으로 push

추천 VPS: 이 튜토리얼은 Vultr, DigitalOcean, Hetzner 어떤 VPS에서도 동일하게 적용됩니다. 한국 사용자 기준 Vultr 서울 리전이 지연시간이 가장 짧습니다.

다음 단계로 Nginx 리버스 프록시로 도메인 연결하고 restic 백업 자동화로 코드를 보호하세요. VPS 데브옵스 시리즈의 모든 영상은 채널에서 확인할 수 있습니다.

관련 글

📎 이 영상의 발표 자료

누구나 무료로 다운로드할 수 있습니다.