들어가며: 전체 그림을 이해하는 것이 중요합니다

안녕하세요! 지난 1편에서는 GitHub Webhook을 활용한 자동 배포 시스템을 직접 구축하려는 이유와 필요한 준비물에 대해 알아보았습니다. 이번 2편에서는 본격적인 코드 구현에 앞서, 우리가 만들 자동 배포 시스템이 어떤 방식으로 동작할지 전체적인 아키텍처와 프로세스를 설계하는 시간을 가질 것입니다.

각자의 개발 환경은 조금씩 다를 수 있습니다. 어떤 분은 라즈베리파이를, 어떤 분은 클라우드 VPS를 사용하실 수 있고, 배포하려는 프로젝트의 구조도 제각각일 것입니다. 이처럼 다양한 환경 속에서 유연하게 시스템을 구축하고, 문제가 발생했을 때 스스로 해결해 나갈 수 있으려면, 세부 코드보다는 전체적인 흐름과 맥락을 이해하는 것이 무엇보다 중요합니다.

이번 편을 통해 우리가 만들 시스템의 큰 그림을 머릿속에 그려보고, 각 구성 요소가 어떤 역할을 하는지 명확히 파악하는 시간을 가져봅시다.

자동 배포 시스템 흐름도

자동 배포 워크플로우: 전체 흐름 개요

우리가 구현할 자동 배포 시스템은 다음과 같은 일련의 과정을 거쳐 동작합니다.

  1. 로컬 작업 머신에서 코드 변경 및 Git 푸시: 개발자가 로컬 환경에서 코드를 수정하고, 변경 사항을 GitHub 저장소의 특정 브랜치(예: main 또는 develop)로 푸시합니다.

  2. GitHub 저장소에서 웹훅 이벤트 발생: GitHub 저장소는 push 이벤트가 감지되면, 사전에 설정된 웹훅(Webhook)을 통해 지정된 URL로 HTTP POST 요청을 보냅니다.

  3. 스테이징 서버의 웹훅 엔드포인트로 요청 전달: GitHub가 보내는 웹훅 요청은 우리가 준비한 스테이징 서버의 특정 URL(예: https://deployer.example.com/webhook)을 가리키게 됩니다. 이 요청에는 푸시된 커밋 정보, 변경된 파일 목록 등 다양한 페이로드(Payload)가 포함됩니다.

  4. 스테이징 서버의 FastAPI 서비스 웹훅 수신: 스테이징 서버에서 실행 중인 우리의 FastAPI 애플리케이션이 이 웹훅 요청을 수신합니다. 여기서부터 FastAPI 서비스의 역할이 시작됩니다.

FastAPI Webhook 서비스의 핵심 역할

우리가 FastAPI로 구현할 웹훅 서비스는 단순히 요청을 받는 것을 넘어, 다음과 같은 중요한 역할들을 수행하게 됩니다.

웹훅 수신 및 초기 처리

FastAPI 애플리케이션은 GitHub로부터 전송되는 HTTP POST 요청을 받을 수 있는 엔드포인트(예: /webhook)를 제공합니다. 이 엔드포인트는 요청의 HTTP 헤더와 바디(Payload)를 파싱하여 필요한 정보를 추출합니다.

Secret 검증

보안은 자동 배포 시스템에서 가장 중요합니다. GitHub Webhook은 X-Hub-Signature-256이라는 헤더를 통해 요청의 무결성을 검증할 수 있는 Secret 값을 제공합니다. 우리의 FastAPI 서비스는 이 Secret 값을 사용하여 GitHub에서 보낸 요청이 맞는지, 그리고 중간에 변조되지 않았는지 검증하는 로직을 포함해야 합니다. 이 검증에 실패하면 즉시 요청을 거부하여 무단 접근을 차단합니다.

즉시 응답 및 백그라운드 작업

GitHub Webhook은 요청을 보낸 후 일정 시간(기본 10초) 내에 응답을 받지 못하면 타임아웃으로 간주하고 재시도를 하거나 실패로 기록합니다. 하지만 실제 배포 과정(Git Pull, Docker 빌드/재시작 등)은 시간이 오래 걸릴 수 있습니다.

따라서 우리의 FastAPI 서비스는 웹훅 요청을 받자마자 Secret 검증 등의 초기 처리를 마친 후 즉시 200 OK 응답을 GitHub에 보낼 것입니다. 그리고 실제 배포 로직은 FastAPI의 BackgroundTasks 기능을 활용하여 백그라운드에서 비동기적으로 실행되도록 설계할 것입니다. 이렇게 하면 GitHub의 타임아웃 문제를 피하면서도 안정적으로 배포 작업을 수행할 수 있습니다.

배포 핸들러 로직 상세

백그라운드에서 실행될 배포 핸들러는 다음과 같은 핵심적인 작업을 수행합니다.

다중 프로젝트 관리: 레포지토리 경로 읽기

우리는 하나의 FastAPI 웹훅 서비스로 여러 개의 GitHub 저장소(프로젝트)에 대한 자동 배포를 처리할 수 있도록 설계할 것입니다. 이를 위해 환경 변수나 설정 파일에서 각 프로젝트의 GitHub 저장소 경로와 해당 프로젝트가 배포될 서버 내의 로컬 경로를 매핑하여 관리할 것입니다. 웹훅 페이로드에서 어떤 저장소에서 이벤트가 발생했는지 확인한 후, 해당 프로젝트의 경로로 이동하여 배포 작업을 수행합니다.

프로젝트별 맞춤형 설정: .env 파일 파싱 (선택 사항)

각 프로젝트는 빌드 또는 배포 시 필요한 고유한 환경 변수나 설정값을 가질 수 있습니다. 예를 들어, 특정 Docker 이미지 태그, 빌드 옵션, 서비스 재시작 명령어 등이 다를 수 있습니다. 이를 효율적으로 관리하기 위해, 각 프로젝트의 로컬 저장소 경로에 있는 .env 파일에서 필요한 값들을 파싱하여 배포 로직에 활용할 수 있도록 구현할 것입니다. 이는 유연하고 맞춤형 배포 로직을 구현하는 데 큰 도움이 됩니다.

코드 업데이트: git pull 실행

가장 기본적인 단계입니다. subprocess 모듈을 사용하여 해당 프로젝트의 로컬 저장소에서 git pull origin <branch_name> 명령어를 실행하여 GitHub 저장소의 최신 코드를 가져옵니다.

Docker 이미지 재빌드 결정: git diff 활용

Docker 기반 프로젝트의 경우, 코드만 변경되었을 때는 docker compose up -d만으로 충분하지만, Dockerfile이나 requirements.txt (Python 프로젝트의 경우)와 같이 Docker 이미지 빌드에 영향을 주는 파일이 변경되었다면 이미지를 새로 빌드해야 합니다.

우리는 git diff 명령어를 활용하여 최근 푸시된 커밋과 이전 커밋 사이에서 Dockerfile 또는 기타 빌드 관련 파일의 변경 유무를 판단할 것입니다. 만약 변경이 감지되면 docker compose up -d --build를 실행하고, 그렇지 않으면 docker compose up -d만 실행하여 불필요한 이미지 재빌드를 방지하고 배포 시간을 단축할 것입니다.

Docker Compose 실행: subprocess 모듈 활용

최신 코드를 가져오고 이미지 재빌드 여부를 결정한 후, subprocess 모듈을 사용하여 docker compose up -d 또는 docker compose up -d --build 명령어를 실행하여 Docker 컨테이너를 최신 상태로 업데이트하고 서비스를 재시작합니다.

로깅: 모든 과정에 대한 기록

모든 배포 과정(웹훅 수신, 검증, Git Pull 결과, Docker 빌드/재시작 로그 등)은 상세하게 기록되어야 합니다. 이는 문제 발생 시 원인을 파악하고 디버깅하는 데 필수적입니다. 파이썬의 logging 모듈을 활용하여 파일에 로그를 남기도록 구현할 것입니다.

FastAPI 서비스 배포 및 운영 전략

우리가 구현할 FastAPI 웹훅 서비스는 스테이징 서버에서 안정적으로 항상 실행되어야 합니다.

Systemd Service 활용의 중요성

FastAPI 애플리케이션을 직접 Docker 컨테이너로 띄우는 대신, Systemd Service로 구동하는 것을 강력히 권장합니다. 그 이유는 다음과 같습니다.

  • 자원 효율성: 이미 스테이징 서버에는 git, docker, docker compose 등 배포에 필요한 도구들이 설치되어 있을 확률이 높습니다. FastAPI 웹훅 서비스 자체를 Docker 컨테이너로 만들고, 그 컨테이너 내부에 다시 git이나 docker를 설치하여 시스템의 docker 데몬을 제어하도록 설정하는 것은 불필요하게 컨테이너의 크기를 늘리고, docker-in-docker 또는 docker-out-of-docker와 같은 복잡한 설정 및 보안 문제를 야기할 수 있습니다.

  • 간결한 관리: Systemd는 Linux 시스템의 서비스 관리 표준입니다. FastAPI 앱을 Systemd 서비스로 등록하면 서버 부팅 시 자동 시작, 서비스 상태 확인, 손쉬운 재시작/중지 등 OS 수준에서 통합적이고 간결한 관리가 가능합니다.

  • 시스템 리소스 활용: Systemd를 통해 FastAPI 앱을 구동하면, 앱이 시스템에 설치된 gitdocker 명령어를 직접 호출하여 배포 작업을 수행하므로, 시스템의 기존 리소스를 가장 효율적으로 활용할 수 있습니다.

다음 편에서는 FastAPI 애플리케이션을 Systemd 서비스로 등록하고 관리하는 방법을 상세히 설명할 것입니다.

Nginx/Apache2를 통한 리버스 프록시 및 HTTPS

지난 1편에서 강조했듯이, FastAPI 애플리케이션을 인터넷에 직접 노출하는 것은 보안상 매우 위험합니다. 따라서 우리는 Nginx 또는 Apache2와 같은 웹 서버를 리버스 프록시(Reverse Proxy) 로 사용하여 웹훅 요청을 안전하게 FastAPI 애플리케이션으로 전달할 것입니다.

또한, GitHub Webhook은 HTTPS 통신을 강력히 권장하므로, deployer.example.com과 같은 전용 서브도메인을 준비하고, Let's Encrypt 등을 통해 HTTPS 인증서를 발급받아 웹 서버에 적용해야 합니다. 이로써 외부로부터의 모든 통신이 암호화되어 보안을 강화할 수 있습니다.

모니터링 및 디버깅

자동 배포 시스템이 제대로 작동하는지 확인하고, 문제가 발생했을 때 원인을 파악하기 위해 다음 두 가지 방법을 활용할 것입니다.

  • FastAPI 서비스 로깅 파일: 우리가 구현할 FastAPI 서비스는 배포 과정의 모든 단계를 자체 로깅 파일에 기록할 것입니다. 이 파일을 확인하여 배포의 성공 여부, 발생한 에러 메시지 등을 파악할 수 있습니다.

  • Systemd journalctl: Systemd로 FastAPI 서비스를 관리하므로, journalctl -u your-fastapi-service.service 명령어를 통해 서비스의 표준 출력 및 에러 로그를 실시간으로 확인하고 분석할 수 있습니다.

마무리하며: 다음 편 예고

이번 2편에서는 GitHub Webhook을 활용한 자동 배포 시스템의 전체적인 아키텍처와 FastAPI 서비스의 핵심 역할, 그리고 배포 및 운영 전략에 대해 상세히 살펴보았습니다. 이제 큰 그림이 머릿속에 그려지셨기를 바랍니다.

다음 3편에서는 오늘 설계한 내용을 바탕으로, 실제 FastAPI 웹훅 서비스의 코드를 작성하고, GitHub Webhook을 설정하며, Systemd 서비스로 등록하는 구체적인 구현 과정을 다룰 것입니다. 기대해주세요!


GitHub Webhook을 활용한 나만의 자동 배포 시스템 구축 시리즈

1편 - 왜 직접 구현하는가?