개발 도구

Jenkins GitHub Webhook 트리거 완벽 가이드 — push 후 즉시 빌드를 시작하는 방법

pollSCM 대신 GitHub Webhook을 연결하면 push 직후 Jenkins 빌드가 시작된다. Jenkins Webhook 수신 설정부터 GitHub 등록, Jenkinsfile 트리거 선언까지 순서대로 정리했다.

JenkinsGitHubWebhookCI/CD자동배포
GitHub 저장소 Settings의 Webhooks 화면 — Jenkins Payload URL을 입력하고 push 이벤트를 선택한 상태
  • ·GitHub Webhook은 이벤트 발생 시 지정 URL로 HTTP POST를 보내는 기능
  • ·Jenkins Webhook 수신 경로: /github-webhook/ (끝 슬래시 필수)
  • ·GitHub Webhook 연동 시 Jenkins 서버가 외부 인터넷에서 접근 가능해야 함
  • ·Jenkinsfile의 triggers 블록은 파이프라인을 한 번 수동 실행해야 등록됨
Next.js 배포 파이프라인에 cron 트리거를 쓰다가 push 직후 바로 반영이 안 되는 게 불편해서 GitHub Webhook으로 전환했다. Jenkins 서버가 퍼블릭 IP를 가져야 한다는 조건이 처음엔 걸림돌처럼 느껴졌는데, Payload URL 하나만 등록하면 끝이었다. push 후 수초 안에 빌드가 시작되는 걸 보고 나서 pollSCM으로 돌아가고 싶은 생각은 사라졌다.

GitHub Webhook과 Jenkins 트리거의 동작 원리

Jenkins에서 GitHub Webhook 트리거란 무엇인가

GitHub Webhook은 GitHub 저장소에서 특정 이벤트가 발생했을 때 지정한 URL로 HTTP POST 요청을 보내는 기능이다. push, pull request, release 등 다양한 이벤트를 트리거로 설정할 수 있다. Jenkins에서 GitHub Webhook 트리거란, GitHub가 보내는 이 HTTP 요청을 Jenkins가 받아서 즉시 빌드를 시작하도록 연결하는 방식이다. cron 트리거가 시간표대로 움직이는 방식이라면, Webhook은 코드가 변경되는 순간에 즉각 반응한다. push 후 수초 안에 빌드가 시작되고, 빠르면 1~2분 안에 배포까지 완료되는 경험을 할 수 있다. pollSCM도 저장소 변경을 감지하지만 Jenkins가 주기적으로 저장소를 직접 폴링하는 방식이라 응답이 느리고 불필요한 요청이 계속 발생한다. Webhook은 GitHub가 먼저 알려주기 때문에 불필요한 폴링이 없고 즉각 반응한다. 다만 Jenkins 서버가 외부에서 접근 가능한 IP나 도메인을 가져야 한다는 전제 조건이 있다. 내부망에서 Jenkins를 운영한다면 Webhook 대신 pollSCM을 써야 하는 이유가 여기 있다. 직접 전환해보면 cron이나 pollSCM과 달리 push 후 빌드 알림이 거의 즉시 오는 게 확연히 체감된다.

Jenkins GitHub Webhook과 pollSCM 비교 — 어떤 상황에서 무엇을 쓰나

GitHub Webhook과 pollSCM은 모두 코드 변경을 감지해 빌드를 실행하지만 동작 방식이 근본적으로 다르다. pollSCM은 Jenkins가 설정한 주기(예: H/1 * * * *)로 Git 저장소에 직접 접근해 새 커밋이 있는지 확인한다. 변경이 없어도 계속 요청을 보내기 때문에 저장소 API 호출이 반복되고, 변경이 생겨도 다음 폴링 주기까지 기다려야 빌드가 시작된다. Webhook은 push가 발생하는 순간 GitHub가 Jenkins에 알림을 보내기 때문에 폴링 없이 즉각 반응한다. 불필요한 API 호출이 없고 반응 속도가 압도적으로 빠르다. 단점은 Jenkins 서버가 외부 인터넷에서 접근 가능해야 한다는 점이다. 퍼블릭 IP 없이 방화벽 뒤에서 운영되는 Jenkins라면 GitHub가 요청을 보낼 경로가 없어서 Webhook을 받을 수 없다. 이 경우 pollSCM을 쓰거나, ngrok 같은 터널링 도구로 임시 퍼블릭 URL을 만들어 테스트할 수 있다. 퍼블릭 서버라면 Webhook이 사실상 표준이고, 내부망이라면 pollSCM이 현실적인 선택이다. 프로젝트에서 두 방식을 모두 써본 결과, 팀원이 많아질수록 Webhook의 즉각성이 개발 흐름에 미치는 영향이 크다고 느꼈다.

Jenkins GitHub Webhook 수신 설정하기

Jenkins에서 GitHub Webhook을 수신하도록 설정하는 방법

Jenkins가 GitHub Webhook을 받으려면 두 가지 설정이 필요하다. 첫 번째는 GitHub Integration Plugin 설치다. Manage Jenkins → Plugins → Available plugins에서 'GitHub'를 검색해 GitHub Integration Plugin을 설치한다. 설치 후 재시작하면 Manage Jenkins → System에 GitHub Server 설정 항목이 생긴다. 두 번째는 Job 설정에서 Webhook 트리거를 활성화하는 것이다. 해당 Job의 Configure 화면에서 Build Triggers 섹션을 찾아 'GitHub hook trigger for GITScm polling'에 체크한다. 이 옵션이 활성화되어 있어야 GitHub에서 온 Webhook 요청을 Jenkins가 빌드 트리거로 인식한다. Jenkinsfile 방식을 쓴다면 이 체크 대신 triggers 블록에 githubPush()를 선언하는 방법도 있다. 주의할 점은 Manage Jenkins → System → Jenkins URL이 외부에서 접근 가능한 실제 주소로 설정되어 있어야 한다는 것이다. 이 URL이 잘못 설정되어 있으면 GitHub Webhook 연동이 정상 동작하지 않는다. 설정이 끝나면 GitHub에서 보내는 Webhook 요청은 http://your-jenkins/github-webhook/ 경로로 전달된다.

GitHub 저장소에 Jenkins Webhook URL을 등록하는 방법

Jenkins 설정이 끝났으면 GitHub 저장소에 Webhook을 등록해야 한다. 연동할 저장소로 이동해서 Settings → Webhooks → Add webhook을 클릭한다. Payload URL에 Jenkins 서버 주소 뒤에 /github-webhook/을 붙여 입력한다. Jenkins 주소가 http://123.45.67.89:8080이라면 Payload URL은 http://123.45.67.89:8080/github-webhook/이 된다. 끝에 슬래시가 없으면 302 리다이렉트가 발생해서 Webhook이 제대로 전달되지 않는다. Content type은 application/json을 선택한다. 'Which events would you like to trigger this webhook?' 항목에서 'Just the push event'를 선택하면 push할 때만 Jenkins 빌드가 시작된다. Add webhook 버튼을 누르면 GitHub가 즉시 테스트 요청을 보내고 Jenkins가 정상 수신했는지 확인한다. Webhooks 목록에서 방금 등록한 항목을 클릭하면 최근 요청 내역과 응답 코드를 확인할 수 있다. 응답 코드가 200이면 연동이 정상이고, 그렇지 않으면 Jenkins URL이 외부에서 접근 가능한지 다시 확인해야 한다. 처음에 Payload URL 끝 슬래시를 빠뜨려서 302가 계속 뜨다가 슬래시를 추가하자마자 200으로 바뀌었다.

Jenkinsfile에서 GitHub Webhook 트리거 선언하기

Jenkinsfile에 GitHub Webhook 트리거 블록을 추가하는 방법

Jenkinsfile에서 GitHub Webhook 트리거를 명시적으로 선언하려면 triggers 블록에 githubPush()를 추가한다. 위치는 pipeline { } 안에서 agent 아래, stages 앞이다. triggers { githubPush() } 한 줄이면 충분하다. 이 선언이 없어도 Job 설정에서 'GitHub hook trigger for GITScm polling'이 체크되어 있으면 Webhook을 받는다. 하지만 Jenkinsfile에 선언해두면 코드를 보는 것만으로 이 파이프라인이 push 이벤트로 트리거된다는 걸 알 수 있어서 명시성이 높아진다. cron 트리거와 동시에 쓸 수도 있다. push가 있으면 즉시 빌드하고, push가 없어도 매일 새벽에 한 번은 빌드를 돌리고 싶다면 triggers { githubPush() cron('H 2 * * *') } 형태로 두 트리거를 함께 선언하면 된다. 두 트리거는 서로 독립적으로 동작한다. 주의할 점은 cron 트리거와 마찬가지로 triggers 블록이 적용되려면 파이프라인을 한 번 수동으로 실행해야 한다는 것이다. Jenkinsfile을 저장하고 push만 해서는 트리거가 등록되지 않는다. 처음 설정할 때 반드시 Build Now를 한 번 눌러야 이후 push부터 자동 빌드가 시작된다.

pipeline {
  agent any
  tools { nodejs 'NodeJS 18' }
  triggers { githubPush() }
  stages {
    stage('Checkout') { steps { checkout scm } }
    stage('Install')  { steps { sh 'npm ci' } }
    stage('Build')    { steps { sh 'npm run build' } }
    stage('Deploy')   { steps { sh './deploy.sh' } }
  }
  post {
    success { echo '배포 완료' }
    failure { echo '배포 실패' }
  }
}

Jenkins GitHub Webhook 트리거 동작을 확인하는 방법

Webhook 연동이 제대로 됐는지 확인하는 가장 확실한 방법은 실제로 push를 해보는 것이다. 저장소에 아무 파일이나 수정해서 push하면 수초 안에 Jenkins의 해당 Job에 빌드가 시작돼야 한다. 빌드가 시작되지 않는다면 GitHub 저장소의 Settings → Webhooks에서 등록한 Webhook 항목을 클릭해 Recent Deliveries를 확인한다. 요청 기록과 응답 코드를 볼 수 있고, 빨간 아이콘이 있으면 요청이 실패했다는 의미다. 실패 원인은 대부분 세 가지 중 하나다. Jenkins URL이 외부에서 접근 안 되는 경우, Jenkins CSRF Protection이 Webhook 요청을 막는 경우, Job 설정에서 트리거 옵션이 체크되지 않은 경우다. CSRF 문제라면 Manage Jenkins → Security에서 GitHub Webhook에 대한 예외를 설정해야 한다. Jenkins 로그에서 Webhook 수신 관련 내용을 확인하면 정확한 원인을 파악할 수 있다. Recent Deliveries에서 실패한 요청을 선택하고 Redeliver 버튼을 누르면 같은 Webhook을 다시 보낼 수 있어서 설정 수정 후 테스트할 때 유용하다. 직접 해보면 이 Redeliver 기능이 디버깅 시간을 크게 줄여준다는 걸 알게 된다.

자주 묻는 질문

Jenkins 서버가 내부망에 있어서 GitHub Webhook을 받을 수 없는데 어떻게 하나요?+

Jenkins가 외부 인터넷에서 접근 불가한 환경이라면 Webhook 대신 pollSCM을 사용하세요. triggers { pollSCM('H/1 * * * *') }를 선언하면 1분마다 저장소를 확인해서 변경 시 빌드를 시작합니다. 테스트 목적이라면 ngrok로 임시 퍼블릭 URL을 만들어 Webhook을 테스트할 수 있습니다.

GitHub Deliveries에서 응답 코드가 302인 경우는 어떻게 해야 하나요?+

Payload URL 끝에 슬래시(/)가 빠진 경우가 가장 흔한 원인입니다. http://your-jenkins/github-webhook/ 처럼 끝에 슬래시가 반드시 있어야 합니다. 슬래시 없이 입력하면 Jenkins가 301/302 리다이렉트로 응답해서 Webhook이 제대로 전달되지 않습니다.

githubPush()와 pollSCM을 동시에 쓸 수 있나요?+

네, 가능합니다. triggers { githubPush() cron('H 2 * * *') } 형태로 선언하면 push 시 즉시 빌드하고 매일 새벽에도 한 번 빌드를 돌립니다. 두 트리거는 서로 독립적으로 동작하며 각각 별도로 빌드를 시작합니다.

push 외에 Pull Request를 열 때도 빌드를 트리거하고 싶으면 어떻게 하나요?+

GitHub Webhook 설정에서 'Let me select individual events'를 선택하고 'Pull requests'를 추가로 체크하면 됩니다. Jenkins에서 PR 이벤트를 처리하려면 GitHub Pull Request Builder 플러그인을 추가로 설치해야 합니다.

관련 글