InfoGrab DocsInfoGrab Docs

웹훅

요약

웹훅은 실시간 알림을 통해 GitLab을 다른 도구 및 시스템과 연결합니다. 웹훅을 사용하면 변경이 발생할 때 팀이 동기화된 상태를 유지합니다. GitLab의 다양한 이벤트가 웹훅을 트리거할 수 있습니다. GitLab.com은 다음을 포함한 웹훅 한도를 적용합니다.

웹훅은 실시간 알림을 통해 GitLab을 다른 도구 및 시스템과 연결합니다. GitLab에서 중요한 이벤트가 발생하면 웹훅이 그 정보를 외부 애플리케이션으로 직접 보냅니다. 머지 리퀘스트, 코드 푸시, 이슈 업데이트에 반응해 자동화 워크플로를 구축합니다.

웹훅을 사용하면 변경이 발생할 때 팀이 동기화된 상태를 유지합니다.

  • GitLab 이슈가 변경되면 외부 이슈 트래커가 자동으로 업데이트됩니다.
  • 채팅 애플리케이션이 파이프라인 완료를 팀 멤버에게 알립니다.
  • 코드가 main 브랜치에 도달하면 커스텀 스크립트가 애플리케이션을 배포합니다.
  • 모니터링 시스템이 조직 전체의 개발 활동을 추적합니다.

웹훅 이벤트#

GitLab의 다양한 이벤트가 웹훅을 트리거할 수 있습니다. 예를 들어 다음과 같습니다.

  • 리포지터리에 코드 푸시.
  • 이슈에 코멘트 게시.
  • 머지 리퀘스트 생성.

웹훅 한도#

GitLab.com은 다음을 포함한 웹훅 한도를 적용합니다.

  • 프로젝트 또는 그룹당 최대 웹훅 수.
  • 분당 웹훅 호출 수.
  • 웹훅 제한 시간.

GitLab Self-Managed에서는 관리자가 이 한도를 수정할 수 있습니다.

푸시 이벤트 한도#

GitLab은 여러 변경이 포함된 푸시 이벤트에 대해 웹훅 트리거를 제한합니다.

  • 기본 한도: 푸시당 브랜치 또는 태그 3개.
  • 초과 시 동작: 해당 푸시 이벤트 전체에 대해 웹훅이 트리거되지 않습니다.
  • 적용 대상: 프로젝트 웹훅과 시스템 훅 모두.
  • 구성: GitLab Self-Managed 관리자는 애플리케이션 설정 API로 push_event_hooks_limit 설정을 수정할 수 있습니다.

여러 태그나 브랜치를 동시에 자주 푸시하면서 웹훅 알림이 필요하면, GitLab 관리자에게 연락해 이 한도를 늘립니다.

그룹 웹훅#

그룹 웹훅은 그룹과 그 하위 그룹의 모든 프로젝트에서 발생하는 이벤트에 대한 알림을 보내는 커스텀 HTTP 콜백입니다.

그룹 웹훅 이벤트 유형#

그룹 웹훅이 다음을 수신하도록 구성할 수 있습니다.

  • 그룹과 하위 그룹의 프로젝트에서 발생하는 모든 이벤트
  • 그룹 멤버 이벤트, 프로젝트 이벤트, 하위 그룹 이벤트를 포함한 그룹 전용 이벤트

프로젝트와 그룹 양쪽의 웹훅#

그룹과 그 그룹의 프로젝트에 동일한 웹훅을 구성하면, 해당 프로젝트의 이벤트에 대해 두 웹훅이 모두 트리거됩니다. 이를 통해 GitLab 조직의 여러 수준에서 이벤트를 유연하게 처리할 수 있습니다.

웹훅 구성#

프로젝트 워크플로와 통합하기 위해 GitLab에서 웹훅을 생성하고 구성합니다. 이 기능으로 요구 사항에 맞는 웹훅을 설정합니다.

웹훅 생성#

히스토리

새 웹훅에는 시크릿 토큰 대신 서명 토큰을 사용합니다. 서명 토큰은 페이로드에 대해 HMAC-SHA256 서명을 계산하므로, 엔드포인트가 요청의 진위성과 무결성을 모두 확인할 수 있습니다. 시크릿 토큰은 헤더에 일반 텍스트 값만 제공하므로 보장이 더 약합니다. 새 웹훅에는 시크릿 토큰을 권장하지 않습니다.

프로젝트나 그룹의 이벤트에 대한 알림을 보내려면 웹훅을 생성합니다.

사전 요구 사항:

  • 프로젝트 웹훅의 경우 해당 프로젝트에 대한 Maintainer 또는 Owner 권한이 있어야 합니다.
  • 그룹 웹훅의 경우 해당 그룹에 대한 Owner 권한이 있어야 합니다.

웹훅을 생성하려면 다음과 같이 진행합니다.

  1. 상단 바에서 Search or go to를 선택하고 프로젝트나 그룹을 찾습니다.
  2. 왼쪽 사이드바에서 Settings > Webhooks를 선택합니다.
  3. Add new webhook을 선택합니다.
  4. URL에 웹훅 엔드포인트의 URL을 입력합니다. 특수 문자에는 퍼센트 인코딩을 사용합니다.
  5. 선택 사항. 웹훅의 Name과 Description을 입력합니다.
  6. 선택 사항. 요청 인증을 구성합니다. 보안을 더 강화하려면 서명 토큰을 사용합니다.
    • Signing token(권장): Generate signing token을 선택합니다. 토큰은 한 번만 표시되므로 지금 복사해 저장합니다. 웹훅 엔드포인트는 이 토큰으로 HMAC-SHA256 서명을 확인할 수 있습니다.
    • Secret token(권장하지 않음): Secret token 필드에 토큰을 입력합니다. 이 토큰은 X-Gitlab-Token HTTP 헤더에 일반 텍스트로 전송되며, 서명 토큰보다 보안 보장이 약합니다. 새 웹훅에는 대신 서명 토큰을 사용합니다.
  7. Trigger 섹션에서 웹훅을 트리거할 이벤트를 선택합니다.
  8. 선택 사항. GitLab Duo flow 수명 주기 이벤트를 이 웹훅으로 보내려면 GitLab Duo Agent Platform 아래에서 Send Duo flow events to this webhook 체크박스를 선택합니다. 이 섹션은 GitLab Duo flow 웹훅 콜백을 사용할 수 있는 곳에서만 표시됩니다.
  9. 선택 사항. SSL 검증을 비활성화하려면 Enable SSL verification 체크박스를 지웁니다.
  10. Add webhook을 선택합니다.

서명 토큰#

히스토리

웹훅 페이로드가 GitLab에서 왔고 변조되지 않았음을 확인하려면 서명 토큰을 사용합니다. 시크릿 토큰과 달리 서명 토큰은 페이로드에 대한 HMAC-SHA256 서명을 계산하는 데 사용됩니다. 따라서 수신자는 받은 페이로드의 진위성과 무결성을 독립적으로 확인할 수 있습니다.

GitLab 웹훅 전달은 Standard Webhooks 명세를 따릅니다. 모든 웹훅 요청에는 webhook-id와 webhook-timestamp 헤더가 포함됩니다. 서명 토큰이 구성되어 있으면 GitLab은 HMAC-SHA256 서명이 담긴 webhook-signature 헤더도 포함합니다. 각 서명은 v1,{base64_signature} 형식입니다. 이 헤더에는 공백으로 구분된 여러 서명이 들어갈 수 있습니다. GitLab은 현재 서명 하나를 보내지만, 이는 앞으로 바뀔 수 있습니다. 서명은 {message_id}.{timestamp}.{body} 문자열에 대해 계산되며, 각 항목은 다음과 같습니다.

  • {message_id}는 webhook-id 헤더의 값입니다.
  • {timestamp}는 webhook-timestamp 헤더의 값입니다.
  • {body}는 원시 JSON 요청 본문입니다.

서명 확인#

웹훅 엔드포인트에서 서명을 확인하려면 다음과 같이 진행합니다.

  1. webhook-id, webhook-timestamp, webhook-signature 헤더 값을 가져옵니다.
  2. webhook-signature 값을 공백으로 분리해 서명 목록을 얻습니다.
  3. 메시지 문자열 "{message_id}.{timestamp}.{body}"를 구성합니다.
  4. 서명 토큰을 디코딩합니다. whsec_ 접두사를 제거한 뒤 나머지를 base64 디코딩합니다.
  5. 디코딩한 키로 HMAC-SHA256 다이제스트를 계산합니다.
  6. 다이제스트를 base64로 인코딩하고 앞에 v1,을 붙입니다.
  7. 계산한 서명이 서명 목록의 항목 중 하나와 일치하는지 확인합니다. 타이밍 공격을 방지하기 위해 상수 시간 비교를 사용합니다.

Ruby 예시:

require 'base64'
require 'openssl'

def valid_signature?(signing_token, message_id, timestamp, body, received_signatures)
  raw_key = Base64.strict_decode64(signing_token.delete_prefix('whsec_'))
  message = "#{message_id}.#{timestamp}.#{body}"
  digest = OpenSSL::HMAC.digest('sha256', raw_key, message)
  expected = "v1,#{Base64.strict_encode64(digest)}"
  received_signatures.split(' ').any? do |sig|
    ActiveSupport::SecurityUtils.secure_compare(expected, sig)
  end
end

Python 예시:

import base64
import hashlib
import hmac

def valid_signature(signing_token, message_id, timestamp, body, received_signatures):
    raw_key = base64.b64decode(signing_token.removeprefix('whsec_'))
    message = f"{message_id}.{timestamp}.{body}".encode('utf-8')
    digest = hmac.new(raw_key, message, hashlib.sha256).digest()
    expected = "v1," + base64.b64encode(digest).decode('utf-8')
    return any(
        hmac.compare_digest(expected, sig)
        for sig in received_signatures.split(' ')
    )

이전 버전과의 호환성#

서명 토큰은 기존 시크릿 토큰과 함께 작동합니다. 같은 웹훅에 둘 다 구성할 수 있습니다.

  • 시크릿 토큰이 구성되어 있으면 X-Gitlab-Token 헤더가 계속 전송됩니다.
  • 서명 토큰이 구성되어 있으면 webhook-signature와 webhook-id 헤더가 전송됩니다.

시크릿 토큰을 사용하는 기존 웹훅을 다운타임 없이 서명 토큰으로 마이그레이션하려면, 전환 기간에 같은 웹훅에 두 토큰을 모두 구성합니다. webhook-signature가 있으면 서명을 확인하고 없으면 시크릿 토큰으로 대체하도록 수신기를 업데이트합니다.

수신기가 서명을 올바르게 처리하면 웹훅 설정에서 시크릿 토큰을 제거할 수 있습니다.

보안 고려 사항#

재생 공격을 방지하려면 페이로드를 처리하기 전에 webhook-timestamp의 타임스탬프가 최근 값인지 검증합니다.

서명 토큰은 API가 반환하지 않습니다.

웹훅 URL의 민감한 부분 마스킹#

보안을 강화하려면 웹훅 URL의 민감한 부분을 마스킹합니다. 마스킹된 부분은 웹훅이 실행될 때 구성된 값으로 대체되고, 로그에 남지 않으며, 데이터베이스에 저장될 때 암호화됩니다.

웹훅 URL의 민감한 부분을 마스킹하려면 다음과 같이 진행합니다.

  1. 상단 바에서 Search or go to를 선택하고 프로젝트나 그룹을 찾습니다.
  2. 왼쪽 사이드바에서 Settings > Webhooks를 선택합니다.
  3. URL에 웹훅의 전체 URL을 입력합니다.
  4. 마스킹할 부분을 정의하려면 Add URL masking을 선택합니다.
  5. Sensitive portion of URL에 마스킹할 URL 부분을 입력합니다.
  6. How it looks in the UI에 마스킹된 부분 대신 표시할 값을 입력합니다. 변수 이름에는 소문자(a-z), 숫자(0-9), 밑줄(_)만 포함해야 합니다.
  7. Save changes를 선택합니다.

마스킹된 값은 UI에서 숨겨진 상태로 표시됩니다. 예를 들어 변수 path와 value를 정의했다면 웹훅 URL은 다음과 같이 보일 수 있습니다.

https://webhook.example.com/{path}?key={value}

커스텀 헤더#

히스토리

외부 서비스 인증을 위해 웹훅 요청에 커스텀 헤더를 추가합니다. 웹훅당 최대 20개의 커스텀 헤더를 구성할 수 있습니다.

커스텀 헤더는 다음 조건을 충족해야 합니다.

  • 전달 헤더의 값을 재정의하지 않습니다.
  • 영숫자, 마침표, 하이픈, 밑줄만 포함합니다.
  • 문자로 시작하고 문자 또는 숫자로 끝납니다.
  • 마침표, 하이픈, 밑줄이 연속되지 않습니다.

커스텀 헤더는 Recent events에 값이 마스킹된 상태로 표시됩니다.

커스텀 웹훅 템플릿#

히스토리

요청 본문으로 보내는 데이터를 제어하려면 웹훅에 대한 커스텀 페이로드 템플릿을 생성합니다.

커스텀 웹훅 템플릿 생성#

  • 프로젝트 웹훅의 경우 해당 프로젝트에 대한 Maintainer 또는 Owner 권한이 있어야 합니다.
  • 그룹 웹훅의 경우 해당 그룹에 대한 Owner 권한이 있어야 합니다.

커스텀 웹훅 템플릿을 생성하려면 다음과 같이 진행합니다.

  1. 웹훅 구성으로 이동합니다.
  2. 커스텀 웹훅 템플릿을 설정합니다.
  3. 템플릿이 유효한 JSON으로 렌더링되는지 확인합니다.

템플릿에서 이벤트 페이로드의 필드를 사용합니다. 예를 들어 다음과 같습니다.

  • job 이벤트의 {{build_name}}
  • 배포 이벤트의 {{deployable_url}}

중첩된 속성에 접근하려면 마침표로 경로 세그먼트를 구분합니다.

커스텀 웹훅 템플릿 예시#

다음 커스텀 페이로드 템플릿의 경우:

{
  "event": "{{object_kind}}",
  "project_name": "{{project.name}}"
}

push 이벤트에 대한 결과 요청 페이로드는 다음과 같습니다.

{
  "event": "push",
  "project_name": "Example"
}

커스텀 웹훅 템플릿은 배열 안의 속성에 접근할 수 없습니다.

브랜치별 푸시 이벤트 필터링#

웹훅 엔드포인트로 전송되는 push 이벤트를 브랜치 이름으로 필터링합니다. 다음 필터링 옵션 중 하나를 사용합니다.

  • All branches: 모든 브랜치의 푸시 이벤트를 받습니다.
  • Wildcard pattern: 와일드카드 패턴과 일치하는 브랜치의 푸시 이벤트를 받습니다.
  • Regular expression: 정규 표현식(regex)과 일치하는 브랜치의 푸시 이벤트를 받습니다.

와일드카드 패턴 사용#

와일드카드 패턴으로 필터링하려면 다음과 같이 진행합니다.

  1. 웹훅 구성에서 Wildcard pattern을 선택합니다.
  2. 패턴을 입력합니다. 예를 들어 다음과 같습니다.
    • -stable로 끝나는 브랜치와 일치시키려면 *-stable.
    • production/ 네임스페이스의 브랜치와 일치시키려면 production/*.

정규 표현식 사용#

정규 표현식으로 필터링하려면 다음과 같이 진행합니다.

  1. 웹훅 구성에서 Regular expression을 선택합니다.
  2. RE2 구문을 따르는 regex 패턴을 입력합니다.

예를 들어 main 브랜치를 제외하려면 다음을 사용합니다.

^(?:.{0,3}|.{5,}|[^m].*|m[^a].*|ma[^i].*|mai[^n].*)$

상호 TLS를 지원하도록 웹훅 구성#

PEM 형식의 전역 클라이언트 인증서를 설정해 웹훅이 상호 TLS를 지원하도록 구성합니다.

사전 요구 사항:

  • GitLab 관리자여야 합니다.

웹훅에 상호 TLS를 구성하려면 다음과 같이 진행합니다.

  1. PEM 형식의 클라이언트 인증서를 준비합니다.
  2. 선택 사항. PEM 패스프레이즈로 인증서를 보호합니다.
  3. 인증서를 사용하도록 GitLab을 구성합니다.
  1. /etc/gitlab/gitlab.rb를 편집합니다.

    gitlab_rails['http_client']['tls_client_cert_file'] = ''
    gitlab_rails['http_client']['tls_client_cert_password'] = ''
    
  2. 파일을 저장하고 GitLab을 재구성합니다.

    sudo gitlab-ctl reconfigure
    
  1. docker-compose.yml을 편집합니다.

    version: "3.6"
    services:
      gitlab:
        image: 'gitlab/gitlab-ee:latest'
        restart: always
        hostname: 'gitlab.example.com'
        environment:
          GITLAB_OMNIBUS_CONFIG: |
             gitlab_rails['http_client']['tls_client_cert_file'] = ''
             gitlab_rails['http_client']['tls_client_cert_password'] = ''
    
  2. 파일을 저장하고 GitLab을 다시 시작합니다.

    docker compose up -d
    
  1. /home/git/gitlab/config/gitlab.yml을 편집합니다.

    production: &base
      http_client:
        tls_client_cert_file: ''
        tls_client_cert_password: ''
    
  2. 파일을 저장하고 GitLab을 다시 시작합니다.

    # For systems running systemd
    sudo systemctl restart gitlab.target
    
    # For systems running SysV init
    sudo service gitlab restart
    

구성 후 GitLab은 웹훅 연결의 TLS 핸드셰이크 중에 이 인증서를 서버에 제시합니다.

웹훅 트래픽에 대한 방화벽 구성#

GitLab이 웹훅을 보내는 방식에 따라 웹훅 트래픽에 대한 방화벽을 구성합니다.

  • Sidekiq 노드에서 비동기로 전송(가장 일반적)
  • Rails 노드에서 동기로 전송(특정 경우)

UI에서 웹훅을 테스트하거나 재시도하면 웹훅이 Rails 노드에서 동기로 전송됩니다.

방화벽을 구성할 때는 Sidekiq 노드와 Rails 노드 모두 웹훅 트래픽을 보낼 수 있도록 합니다.

웹훅 관리#

GitLab에서 구성한 웹훅을 모니터링하고 유지 관리합니다.

웹훅 요청 기록 보기#

성능을 모니터링하고 문제를 해결하기 위해 웹훅 요청 기록을 확인합니다.

사전 요구 사항:

  • 프로젝트 웹훅의 경우 해당 프로젝트에 대한 Maintainer 또는 Owner 권한이 있어야 합니다.
  • 그룹 웹훅의 경우 해당 그룹에 대한 Owner 권한이 있어야 합니다.

웹훅의 요청 기록을 확인하려면 다음과 같이 진행합니다.

  1. 상단 바에서 Search or go to를 선택하고 프로젝트나 그룹을 찾습니다.
  2. 왼쪽 사이드바에서 Settings > Webhooks를 선택합니다.
  3. 해당 웹훅의 Edit를 선택합니다.
  4. Recent events 섹션으로 이동합니다.

Recent events 섹션은 지난 2일 동안 웹훅에 대해 이루어진 모든 요청을 표시합니다. 표에는 다음이 포함됩니다.

  • HTTP 상태 코드:
    • 200-299 코드는 녹색
    • 그 밖의 코드는 빨간색
    • 전달 실패는 internal error
  • 트리거된 이벤트
  • 요청의 경과 시간
  • 요청이 이루어진 상대 시간

상태 코드와 응답 시간을 보여 주는 웹훅 이벤트 로그

요청 및 응답 세부 정보 검사#

사전 요구 사항:

  • 프로젝트 웹훅의 경우 해당 프로젝트에 대한 Maintainer 또는 Owner 권한이 있어야 합니다.
  • 그룹 웹훅의 경우 해당 그룹에 대한 Owner 권한이 있어야 합니다.

Recent events의 각 웹훅 요청에는 Request details 페이지가 있습니다. 이 페이지에는 다음의 본문과 헤더가 담겨 있습니다.

  • GitLab이 웹훅 수신기 엔드포인트에서 받은 응답
  • GitLab이 보낸 웹훅 요청

웹훅 이벤트의 요청 및 응답 세부 정보를 검사하려면 다음과 같이 진행합니다.

  1. 상단 바에서 Search or go to를 선택하고 프로젝트나 그룹을 찾습니다.
  2. 왼쪽 사이드바에서 Settings > Webhooks를 선택합니다.
  3. 해당 웹훅의 Edit를 선택합니다.
  4. Recent events 섹션으로 이동합니다.
  5. 해당 이벤트의 View details를 선택합니다.

같은 데이터와 같은 Idempotency-Key 헤더로 요청을 다시 보내려면 Resend Request를 선택합니다. 웹훅 URL이 변경되었으면 요청을 다시 보낼 수 없습니다. 프로젝트 웹훅 API로 프로그래밍 방식으로 요청을 다시 보낼 수도 있습니다.

웹훅 테스트#

웹훅이 정상적으로 작동하는지 확인하거나 비활성화된 웹훅을 다시 활성화하려면 웹훅을 테스트합니다.

사전 요구 사항:

  • 프로젝트 웹훅의 경우 해당 프로젝트에 대한 Maintainer 또는 Owner 권한이 있어야 합니다.
  • 그룹 웹훅의 경우 해당 그룹에 대한 Owner 권한이 있어야 합니다.
  • push events를 테스트하려면 프로젝트에 커밋이 하나 이상 있어야 합니다.

웹훅을 테스트하려면 다음과 같이 진행합니다.

  1. 상단 바에서 Search or go to를 선택하고 프로젝트나 그룹을 찾습니다.
  2. 왼쪽 사이드바에서 Settings > Webhooks를 선택해 이 프로젝트의 모든 웹훅을 확인합니다.
  3. 구성된 웹훅 목록에서 바로 웹훅을 테스트하려면 다음과 같이 진행합니다.
    1. 테스트할 웹훅을 찾습니다.
    2. Test 드롭다운 목록에서 테스트할 이벤트 유형을 선택합니다.
  4. 웹훅을 편집하면서 테스트하려면 다음과 같이 진행합니다.
    1. 테스트할 웹훅을 찾아 Edit를 선택합니다.
    2. 웹훅을 변경합니다.
    3. Test 드롭다운 목록을 선택한 다음 테스트할 이벤트 유형을 선택합니다.

프로젝트 및 그룹 웹훅의 일부 이벤트 유형은 테스트를 지원하지 않습니다. 자세한 내용은 이슈 379201을 참고합니다.

웹훅 참조#

이 기술 참조 자료는 다음 목적으로 사용합니다.

  • GitLab 웹훅의 작동 방식을 이해합니다.
  • 웹훅을 시스템과 통합합니다.
  • 웹훅 구성을 설정하고, 문제를 해결하고, 최적화합니다.

웹훅 수신기 요구 사항#

웹훅 전달의 신뢰성을 보장하려면 빠르고 안정적인 웹훅 수신기 엔드포인트를 구현합니다.

느리거나 불안정하거나 잘못 구성된 수신기는 자동으로 비활성화될 수 있습니다. 유효하지 않은 HTTP 응답은 실패한 요청으로 처리됩니다.

웹훅 수신기를 최적화하려면 다음과 같이 진행합니다.

  1. 200 또는 201 상태로 빠르게 응답합니다.
    • 같은 요청에서 웹훅을 처리하지 않습니다.
    • 웹훅을 받은 뒤 처리하도록 큐를 사용합니다.
    • GitLab.com에서 자동 비활성화되지 않도록 제한 시간 전에 응답합니다.
  2. 중복 이벤트 가능성에 대비합니다.
    • 웹훅에서 제한 시간이 초과되는 경우 중복 이벤트에 대비합니다.
    • 엔드포인트가 일관되게 빠르고 안정적인지 확인합니다.
  3. 응답 헤더와 본문을 최소화합니다.
    • GitLab은 이후 검사를 위해 응답 헤더와 본문을 저장합니다.
    • 반환하는 헤더의 개수와 크기를 제한합니다.
    • 본문을 비워 응답하는 방안을 고려합니다.
  4. 적절한 상태 코드를 사용합니다.
    • 클라이언트 오류 상태 응답(4xx 범위)은 잘못 구성된 웹훅에만 반환합니다.
    • 지원하지 않는 이벤트에는 400을 반환하거나 페이로드를 무시합니다.
    • 처리한 이벤트에는 500 서버 오류 응답을 사용하지 않습니다.

자동 비활성화된 웹훅#

히스토리
Feature flag

이 기능의 가용성은 기능 플래그로 제어됩니다. 자세한 내용은 히스토리를 참고합니다.

GitLab은 연속 4회 실패한 프로젝트 또는 그룹 웹훅을 자동으로 비활성화합니다.

자동 비활성화된 웹훅을 확인하려면 다음과 같이 진행합니다.

  1. 상단 바에서 Search or go to를 선택하고 프로젝트나 그룹을 찾습니다.
  2. 왼쪽 사이드바에서 Settings > Webhooks를 선택합니다.

웹훅 목록에서 자동 비활성화된 웹훅은 다음과 같이 표시됩니다.

  • 연속 4회 실패하면 Temporarily disabled
  • 연속 40회 실패하면 Disabled

비활성화 및 일시 비활성화 상태 배지를 보여 주는 웹훅 목록.

일시적으로 비활성화된 웹훅#

웹훅이 연속 4회 실패하면 일시적으로 비활성화됩니다. 웹훅이 연속 40회 실패하면 영구적으로 비활성화됩니다.

다음 경우에 실패가 발생합니다.

  • 웹훅 수신기가 4xx 또는 5xx 범위의 응답 코드를 반환합니다.
  • 웹훅이 웹훅 수신기에 연결하려 할 때 제한 시간을 초과합니다.
  • 웹훅에서 그 밖의 HTTP 오류가 발생합니다.

일시적으로 비활성화된 웹훅은 처음에 1분 동안 비활성화되고, 이후 실패가 반복되면 최대 24시간까지 기간이 늘어납니다. 이 기간이 지나면 이러한 웹훅은 자동으로 다시 활성화됩니다.

영구적으로 비활성화된 웹훅#

웹훅이 연속 40회 실패하면 영구적으로 비활성화됩니다. 일시적으로 비활성화된 웹훅과 달리 이러한 웹훅은 자동으로 다시 활성화되지 않습니다.

GitLab 17.10 및 이전 버전에서 영구적으로 비활성화된 웹훅은 데이터 마이그레이션을 거쳤습니다. 이러한 웹훅은 UI가 실패 40회로 표시하더라도 Recent events에는 실패 4회로 표시될 수 있습니다.

비활성화된 웹훅 다시 활성화#

비활성화된 웹훅을 다시 활성화하려면 테스트 요청을 보냅니다. 테스트 요청이 2xx 범위의 응답 코드를 반환하면 웹훅이 다시 활성화됩니다.

전달 헤더#

히스토리

GitLab은 엔드포인트로 보내는 웹훅 요청에 다음 헤더를 포함합니다.

Header Description Example
Idempotency-Key 웹훅 재시도 간에 유지되는 고유 ID. 레거시 이유로 제공됩니다. webhook-id를 우선 사용합니다. "f5e5f430-f57b-4e6e-9fac-d9128cd7232f"
User-Agent "Gitlab/" 형식의 사용자 에이전트. "GitLab/15.5.0-pre"
webhook-id 웹훅 재시도 간에 유지되는 고유 메시지 ID. Idempotency-Key와 같습니다. "f5e5f430-f57b-4e6e-9fac-d9128cd7232f"
webhook-signature 각각 v1,{base64_signature} 형식인, 공백으로 구분된 HMAC-SHA256 서명 목록. 서명 토큰이 구성된 경우에만 포함됩니다. "v1,abc123def456=="
webhook-timestamp 요청이 생성된 시점의 Unix 타임스탬프(에포크 이후 초). "1744578123"
X-Gitlab-Event-UUID 재귀적이지 않은 웹훅의 고유 ID. 재귀 웹훅(이전 웹훅이 트리거한 웹훅)은 같은 값을 공유합니다. "13792a34-cac6-4fda-95a8-c58e00a3954e"
X-Gitlab-Event 웹훅 유형 이름. " Hook" 형식의 이벤트 유형에 해당합니다. "Push Hook"
X-Gitlab-Instance 웹훅을 보낸 GitLab 인스턴스의 호스트 이름. "https://gitlab.com"
X-Gitlab-Token 웹훅의 시크릿 토큰으로, 일반 텍스트로 전송됩니다. 시크릿 토큰이 구성된 경우에만 포함됩니다. "my-secret-token"
X-Gitlab-Webhook-UUID 각 웹훅의 고유 ID. "02affd2d-2cba-4033-917d-ec22d5dc4b38"

웹훅 본문의 이미지 URL 표시#

GitLab은 웹훅 본문에서 상대 이미지 참조를 절대 URL로 다시 작성합니다.

이미지 URL 재작성 예시#

머지 리퀘스트, 코멘트, 위키 페이지의 원래 이미지 참조가 다음과 같다면:

![A Markdown image with a relative URL.](/uploads/$sha/image.png)

웹훅 본문에서 다시 작성된 이미지 참조는 다음과 같습니다.

![A Markdown image with an absolute URL.](https://gitlab.example.com/-/project/:id/uploads//image.png)

이 예시는 다음을 전제합니다.

  • GitLab이 gitlab.example.com에 설치되어 있습니다.
  • 프로젝트 ID는 123입니다.

이미지 URL 재작성의 예외#

GitLab은 다음 경우에 이미지 URL을 다시 작성하지 않습니다.

  • 이미 HTTP, HTTPS 또는 프로토콜 상대 URL을 사용하는 경우.
  • 링크 레이블처럼 고급 Markdown 기능을 사용하는 경우.

관련 주제#

웹훅

GitLab v19.5
Tier: Premium, Ultimate
Offering: GitLab Self-Managed
원문 보기

요약

웹훅은 실시간 알림을 통해 GitLab을 다른 도구 및 시스템과 연결합니다. 웹훅을 사용하면 변경이 발생할 때 팀이 동기화된 상태를 유지합니다. GitLab의 다양한 이벤트가 웹훅을 트리거할 수 있습니다. GitLab.com은 다음을 포함한 웹훅 한도를 적용합니다.

웹훅은 실시간 알림을 통해 GitLab을 다른 도구 및 시스템과 연결합니다. GitLab에서 중요한 이벤트가 발생하면 웹훅이 그 정보를 외부 애플리케이션으로 직접 보냅니다. 머지 리퀘스트, 코드 푸시, 이슈 업데이트에 반응해 자동화 워크플로를 구축합니다.

웹훅을 사용하면 변경이 발생할 때 팀이 동기화된 상태를 유지합니다.

  • GitLab 이슈가 변경되면 외부 이슈 트래커가 자동으로 업데이트됩니다.
  • 채팅 애플리케이션이 파이프라인 완료를 팀 멤버에게 알립니다.
  • 코드가 main 브랜치에 도달하면 커스텀 스크립트가 애플리케이션을 배포합니다.
  • 모니터링 시스템이 조직 전체의 개발 활동을 추적합니다.

웹훅 이벤트#

GitLab의 다양한 이벤트가 웹훅을 트리거할 수 있습니다. 예를 들어 다음과 같습니다.

  • 리포지터리에 코드 푸시.
  • 이슈에 코멘트 게시.
  • 머지 리퀘스트 생성.

웹훅 한도#

GitLab.com은 다음을 포함한 웹훅 한도를 적용합니다.

  • 프로젝트 또는 그룹당 최대 웹훅 수.
  • 분당 웹훅 호출 수.
  • 웹훅 제한 시간.

GitLab Self-Managed에서는 관리자가 이 한도를 수정할 수 있습니다.

푸시 이벤트 한도#

GitLab은 여러 변경이 포함된 푸시 이벤트에 대해 웹훅 트리거를 제한합니다.

  • 기본 한도: 푸시당 브랜치 또는 태그 3개.
  • 초과 시 동작: 해당 푸시 이벤트 전체에 대해 웹훅이 트리거되지 않습니다.
  • 적용 대상: 프로젝트 웹훅과 시스템 훅 모두.
  • 구성: GitLab Self-Managed 관리자는 애플리케이션 설정 API로 push_event_hooks_limit 설정을 수정할 수 있습니다.

여러 태그나 브랜치를 동시에 자주 푸시하면서 웹훅 알림이 필요하면, GitLab 관리자에게 연락해 이 한도를 늘립니다.

그룹 웹훅#

그룹 웹훅은 그룹과 그 하위 그룹의 모든 프로젝트에서 발생하는 이벤트에 대한 알림을 보내는 커스텀 HTTP 콜백입니다.

그룹 웹훅 이벤트 유형#

그룹 웹훅이 다음을 수신하도록 구성할 수 있습니다.

  • 그룹과 하위 그룹의 프로젝트에서 발생하는 모든 이벤트
  • 그룹 멤버 이벤트, 프로젝트 이벤트, 하위 그룹 이벤트를 포함한 그룹 전용 이벤트

프로젝트와 그룹 양쪽의 웹훅#

그룹과 그 그룹의 프로젝트에 동일한 웹훅을 구성하면, 해당 프로젝트의 이벤트에 대해 두 웹훅이 모두 트리거됩니다. 이를 통해 GitLab 조직의 여러 수준에서 이벤트를 유연하게 처리할 수 있습니다.

웹훅 구성#

프로젝트 워크플로와 통합하기 위해 GitLab에서 웹훅을 생성하고 구성합니다. 이 기능으로 요구 사항에 맞는 웹훅을 설정합니다.

웹훅 생성#

히스토리

새 웹훅에는 시크릿 토큰 대신 서명 토큰을 사용합니다. 서명 토큰은 페이로드에 대해 HMAC-SHA256 서명을 계산하므로, 엔드포인트가 요청의 진위성과 무결성을 모두 확인할 수 있습니다. 시크릿 토큰은 헤더에 일반 텍스트 값만 제공하므로 보장이 더 약합니다. 새 웹훅에는 시크릿 토큰을 권장하지 않습니다.

프로젝트나 그룹의 이벤트에 대한 알림을 보내려면 웹훅을 생성합니다.

사전 요구 사항:

  • 프로젝트 웹훅의 경우 해당 프로젝트에 대한 Maintainer 또는 Owner 권한이 있어야 합니다.
  • 그룹 웹훅의 경우 해당 그룹에 대한 Owner 권한이 있어야 합니다.

웹훅을 생성하려면 다음과 같이 진행합니다.

  1. 상단 바에서 Search or go to를 선택하고 프로젝트나 그룹을 찾습니다.
  2. 왼쪽 사이드바에서 Settings > Webhooks를 선택합니다.
  3. Add new webhook을 선택합니다.
  4. URL에 웹훅 엔드포인트의 URL을 입력합니다. 특수 문자에는 퍼센트 인코딩을 사용합니다.
  5. 선택 사항. 웹훅의 Name과 Description을 입력합니다.
  6. 선택 사항. 요청 인증을 구성합니다. 보안을 더 강화하려면 서명 토큰을 사용합니다.
    • Signing token(권장): Generate signing token을 선택합니다. 토큰은 한 번만 표시되므로 지금 복사해 저장합니다. 웹훅 엔드포인트는 이 토큰으로 HMAC-SHA256 서명을 확인할 수 있습니다.
    • Secret token(권장하지 않음): Secret token 필드에 토큰을 입력합니다. 이 토큰은 X-Gitlab-Token HTTP 헤더에 일반 텍스트로 전송되며, 서명 토큰보다 보안 보장이 약합니다. 새 웹훅에는 대신 서명 토큰을 사용합니다.
  7. Trigger 섹션에서 웹훅을 트리거할 이벤트를 선택합니다.
  8. 선택 사항. GitLab Duo flow 수명 주기 이벤트를 이 웹훅으로 보내려면 GitLab Duo Agent Platform 아래에서 Send Duo flow events to this webhook 체크박스를 선택합니다. 이 섹션은 GitLab Duo flow 웹훅 콜백을 사용할 수 있는 곳에서만 표시됩니다.
  9. 선택 사항. SSL 검증을 비활성화하려면 Enable SSL verification 체크박스를 지웁니다.
  10. Add webhook을 선택합니다.

서명 토큰#

히스토리

웹훅 페이로드가 GitLab에서 왔고 변조되지 않았음을 확인하려면 서명 토큰을 사용합니다. 시크릿 토큰과 달리 서명 토큰은 페이로드에 대한 HMAC-SHA256 서명을 계산하는 데 사용됩니다. 따라서 수신자는 받은 페이로드의 진위성과 무결성을 독립적으로 확인할 수 있습니다.

GitLab 웹훅 전달은 Standard Webhooks 명세를 따릅니다. 모든 웹훅 요청에는 webhook-id와 webhook-timestamp 헤더가 포함됩니다. 서명 토큰이 구성되어 있으면 GitLab은 HMAC-SHA256 서명이 담긴 webhook-signature 헤더도 포함합니다. 각 서명은 v1,{base64_signature} 형식입니다. 이 헤더에는 공백으로 구분된 여러 서명이 들어갈 수 있습니다. GitLab은 현재 서명 하나를 보내지만, 이는 앞으로 바뀔 수 있습니다. 서명은 {message_id}.{timestamp}.{body} 문자열에 대해 계산되며, 각 항목은 다음과 같습니다.

  • {message_id}는 webhook-id 헤더의 값입니다.
  • {timestamp}는 webhook-timestamp 헤더의 값입니다.
  • {body}는 원시 JSON 요청 본문입니다.

서명 확인#

웹훅 엔드포인트에서 서명을 확인하려면 다음과 같이 진행합니다.

  1. webhook-id, webhook-timestamp, webhook-signature 헤더 값을 가져옵니다.
  2. webhook-signature 값을 공백으로 분리해 서명 목록을 얻습니다.
  3. 메시지 문자열 "{message_id}.{timestamp}.{body}"를 구성합니다.
  4. 서명 토큰을 디코딩합니다. whsec_ 접두사를 제거한 뒤 나머지를 base64 디코딩합니다.
  5. 디코딩한 키로 HMAC-SHA256 다이제스트를 계산합니다.
  6. 다이제스트를 base64로 인코딩하고 앞에 v1,을 붙입니다.
  7. 계산한 서명이 서명 목록의 항목 중 하나와 일치하는지 확인합니다. 타이밍 공격을 방지하기 위해 상수 시간 비교를 사용합니다.

Ruby 예시:

require 'base64'
require 'openssl'

def valid_signature?(signing_token, message_id, timestamp, body, received_signatures)
  raw_key = Base64.strict_decode64(signing_token.delete_prefix('whsec_'))
  message = "#{message_id}.#{timestamp}.#{body}"
  digest = OpenSSL::HMAC.digest('sha256', raw_key, message)
  expected = "v1,#{Base64.strict_encode64(digest)}"
  received_signatures.split(' ').any? do |sig|
    ActiveSupport::SecurityUtils.secure_compare(expected, sig)
  end
end

Python 예시:

import base64
import hashlib
import hmac

def valid_signature(signing_token, message_id, timestamp, body, received_signatures):
    raw_key = base64.b64decode(signing_token.removeprefix('whsec_'))
    message = f"{message_id}.{timestamp}.{body}".encode('utf-8')
    digest = hmac.new(raw_key, message, hashlib.sha256).digest()
    expected = "v1," + base64.b64encode(digest).decode('utf-8')
    return any(
        hmac.compare_digest(expected, sig)
        for sig in received_signatures.split(' ')
    )

이전 버전과의 호환성#

서명 토큰은 기존 시크릿 토큰과 함께 작동합니다. 같은 웹훅에 둘 다 구성할 수 있습니다.

  • 시크릿 토큰이 구성되어 있으면 X-Gitlab-Token 헤더가 계속 전송됩니다.
  • 서명 토큰이 구성되어 있으면 webhook-signature와 webhook-id 헤더가 전송됩니다.

시크릿 토큰을 사용하는 기존 웹훅을 다운타임 없이 서명 토큰으로 마이그레이션하려면, 전환 기간에 같은 웹훅에 두 토큰을 모두 구성합니다. webhook-signature가 있으면 서명을 확인하고 없으면 시크릿 토큰으로 대체하도록 수신기를 업데이트합니다.

수신기가 서명을 올바르게 처리하면 웹훅 설정에서 시크릿 토큰을 제거할 수 있습니다.

보안 고려 사항#

재생 공격을 방지하려면 페이로드를 처리하기 전에 webhook-timestamp의 타임스탬프가 최근 값인지 검증합니다.

서명 토큰은 API가 반환하지 않습니다.

웹훅 URL의 민감한 부분 마스킹#

보안을 강화하려면 웹훅 URL의 민감한 부분을 마스킹합니다. 마스킹된 부분은 웹훅이 실행될 때 구성된 값으로 대체되고, 로그에 남지 않으며, 데이터베이스에 저장될 때 암호화됩니다.

웹훅 URL의 민감한 부분을 마스킹하려면 다음과 같이 진행합니다.

  1. 상단 바에서 Search or go to를 선택하고 프로젝트나 그룹을 찾습니다.
  2. 왼쪽 사이드바에서 Settings > Webhooks를 선택합니다.
  3. URL에 웹훅의 전체 URL을 입력합니다.
  4. 마스킹할 부분을 정의하려면 Add URL masking을 선택합니다.
  5. Sensitive portion of URL에 마스킹할 URL 부분을 입력합니다.
  6. How it looks in the UI에 마스킹된 부분 대신 표시할 값을 입력합니다. 변수 이름에는 소문자(a-z), 숫자(0-9), 밑줄(_)만 포함해야 합니다.
  7. Save changes를 선택합니다.

마스킹된 값은 UI에서 숨겨진 상태로 표시됩니다. 예를 들어 변수 path와 value를 정의했다면 웹훅 URL은 다음과 같이 보일 수 있습니다.

https://webhook.example.com/{path}?key={value}

커스텀 헤더#

히스토리

외부 서비스 인증을 위해 웹훅 요청에 커스텀 헤더를 추가합니다. 웹훅당 최대 20개의 커스텀 헤더를 구성할 수 있습니다.

커스텀 헤더는 다음 조건을 충족해야 합니다.

  • 전달 헤더의 값을 재정의하지 않습니다.
  • 영숫자, 마침표, 하이픈, 밑줄만 포함합니다.
  • 문자로 시작하고 문자 또는 숫자로 끝납니다.
  • 마침표, 하이픈, 밑줄이 연속되지 않습니다.

커스텀 헤더는 Recent events에 값이 마스킹된 상태로 표시됩니다.

커스텀 웹훅 템플릿#

히스토리

요청 본문으로 보내는 데이터를 제어하려면 웹훅에 대한 커스텀 페이로드 템플릿을 생성합니다.

커스텀 웹훅 템플릿 생성#

  • 프로젝트 웹훅의 경우 해당 프로젝트에 대한 Maintainer 또는 Owner 권한이 있어야 합니다.
  • 그룹 웹훅의 경우 해당 그룹에 대한 Owner 권한이 있어야 합니다.

커스텀 웹훅 템플릿을 생성하려면 다음과 같이 진행합니다.

  1. 웹훅 구성으로 이동합니다.
  2. 커스텀 웹훅 템플릿을 설정합니다.
  3. 템플릿이 유효한 JSON으로 렌더링되는지 확인합니다.

템플릿에서 이벤트 페이로드의 필드를 사용합니다. 예를 들어 다음과 같습니다.

  • job 이벤트의 {{build_name}}
  • 배포 이벤트의 {{deployable_url}}

중첩된 속성에 접근하려면 마침표로 경로 세그먼트를 구분합니다.

커스텀 웹훅 템플릿 예시#

다음 커스텀 페이로드 템플릿의 경우:

{
  "event": "{{object_kind}}",
  "project_name": "{{project.name}}"
}

push 이벤트에 대한 결과 요청 페이로드는 다음과 같습니다.

{
  "event": "push",
  "project_name": "Example"
}

커스텀 웹훅 템플릿은 배열 안의 속성에 접근할 수 없습니다.

브랜치별 푸시 이벤트 필터링#

웹훅 엔드포인트로 전송되는 push 이벤트를 브랜치 이름으로 필터링합니다. 다음 필터링 옵션 중 하나를 사용합니다.

  • All branches: 모든 브랜치의 푸시 이벤트를 받습니다.
  • Wildcard pattern: 와일드카드 패턴과 일치하는 브랜치의 푸시 이벤트를 받습니다.
  • Regular expression: 정규 표현식(regex)과 일치하는 브랜치의 푸시 이벤트를 받습니다.

와일드카드 패턴 사용#

와일드카드 패턴으로 필터링하려면 다음과 같이 진행합니다.

  1. 웹훅 구성에서 Wildcard pattern을 선택합니다.
  2. 패턴을 입력합니다. 예를 들어 다음과 같습니다.
    • -stable로 끝나는 브랜치와 일치시키려면 *-stable.
    • production/ 네임스페이스의 브랜치와 일치시키려면 production/*.

정규 표현식 사용#

정규 표현식으로 필터링하려면 다음과 같이 진행합니다.

  1. 웹훅 구성에서 Regular expression을 선택합니다.
  2. RE2 구문을 따르는 regex 패턴을 입력합니다.

예를 들어 main 브랜치를 제외하려면 다음을 사용합니다.

^(?:.{0,3}|.{5,}|[^m].*|m[^a].*|ma[^i].*|mai[^n].*)$

상호 TLS를 지원하도록 웹훅 구성#

PEM 형식의 전역 클라이언트 인증서를 설정해 웹훅이 상호 TLS를 지원하도록 구성합니다.

사전 요구 사항:

  • GitLab 관리자여야 합니다.

웹훅에 상호 TLS를 구성하려면 다음과 같이 진행합니다.

  1. PEM 형식의 클라이언트 인증서를 준비합니다.
  2. 선택 사항. PEM 패스프레이즈로 인증서를 보호합니다.
  3. 인증서를 사용하도록 GitLab을 구성합니다.
  1. /etc/gitlab/gitlab.rb를 편집합니다.

    gitlab_rails['http_client']['tls_client_cert_file'] = ''
    gitlab_rails['http_client']['tls_client_cert_password'] = ''
    
  2. 파일을 저장하고 GitLab을 재구성합니다.

    sudo gitlab-ctl reconfigure
    
  1. docker-compose.yml을 편집합니다.

    version: "3.6"
    services:
      gitlab:
        image: 'gitlab/gitlab-ee:latest'
        restart: always
        hostname: 'gitlab.example.com'
        environment:
          GITLAB_OMNIBUS_CONFIG: |
             gitlab_rails['http_client']['tls_client_cert_file'] = ''
             gitlab_rails['http_client']['tls_client_cert_password'] = ''
    
  2. 파일을 저장하고 GitLab을 다시 시작합니다.

    docker compose up -d
    
  1. /home/git/gitlab/config/gitlab.yml을 편집합니다.

    production: &base
      http_client:
        tls_client_cert_file: ''
        tls_client_cert_password: ''
    
  2. 파일을 저장하고 GitLab을 다시 시작합니다.

    # For systems running systemd
    sudo systemctl restart gitlab.target
    
    # For systems running SysV init
    sudo service gitlab restart
    

구성 후 GitLab은 웹훅 연결의 TLS 핸드셰이크 중에 이 인증서를 서버에 제시합니다.

웹훅 트래픽에 대한 방화벽 구성#

GitLab이 웹훅을 보내는 방식에 따라 웹훅 트래픽에 대한 방화벽을 구성합니다.

  • Sidekiq 노드에서 비동기로 전송(가장 일반적)
  • Rails 노드에서 동기로 전송(특정 경우)

UI에서 웹훅을 테스트하거나 재시도하면 웹훅이 Rails 노드에서 동기로 전송됩니다.

방화벽을 구성할 때는 Sidekiq 노드와 Rails 노드 모두 웹훅 트래픽을 보낼 수 있도록 합니다.

웹훅 관리#

GitLab에서 구성한 웹훅을 모니터링하고 유지 관리합니다.

웹훅 요청 기록 보기#

성능을 모니터링하고 문제를 해결하기 위해 웹훅 요청 기록을 확인합니다.

사전 요구 사항:

  • 프로젝트 웹훅의 경우 해당 프로젝트에 대한 Maintainer 또는 Owner 권한이 있어야 합니다.
  • 그룹 웹훅의 경우 해당 그룹에 대한 Owner 권한이 있어야 합니다.

웹훅의 요청 기록을 확인하려면 다음과 같이 진행합니다.

  1. 상단 바에서 Search or go to를 선택하고 프로젝트나 그룹을 찾습니다.
  2. 왼쪽 사이드바에서 Settings > Webhooks를 선택합니다.
  3. 해당 웹훅의 Edit를 선택합니다.
  4. Recent events 섹션으로 이동합니다.

Recent events 섹션은 지난 2일 동안 웹훅에 대해 이루어진 모든 요청을 표시합니다. 표에는 다음이 포함됩니다.

  • HTTP 상태 코드:
    • 200-299 코드는 녹색
    • 그 밖의 코드는 빨간색
    • 전달 실패는 internal error
  • 트리거된 이벤트
  • 요청의 경과 시간
  • 요청이 이루어진 상대 시간

상태 코드와 응답 시간을 보여 주는 웹훅 이벤트 로그

요청 및 응답 세부 정보 검사#

사전 요구 사항:

  • 프로젝트 웹훅의 경우 해당 프로젝트에 대한 Maintainer 또는 Owner 권한이 있어야 합니다.
  • 그룹 웹훅의 경우 해당 그룹에 대한 Owner 권한이 있어야 합니다.

Recent events의 각 웹훅 요청에는 Request details 페이지가 있습니다. 이 페이지에는 다음의 본문과 헤더가 담겨 있습니다.

  • GitLab이 웹훅 수신기 엔드포인트에서 받은 응답
  • GitLab이 보낸 웹훅 요청

웹훅 이벤트의 요청 및 응답 세부 정보를 검사하려면 다음과 같이 진행합니다.

  1. 상단 바에서 Search or go to를 선택하고 프로젝트나 그룹을 찾습니다.
  2. 왼쪽 사이드바에서 Settings > Webhooks를 선택합니다.
  3. 해당 웹훅의 Edit를 선택합니다.
  4. Recent events 섹션으로 이동합니다.
  5. 해당 이벤트의 View details를 선택합니다.

같은 데이터와 같은 Idempotency-Key 헤더로 요청을 다시 보내려면 Resend Request를 선택합니다. 웹훅 URL이 변경되었으면 요청을 다시 보낼 수 없습니다. 프로젝트 웹훅 API로 프로그래밍 방식으로 요청을 다시 보낼 수도 있습니다.

웹훅 테스트#

웹훅이 정상적으로 작동하는지 확인하거나 비활성화된 웹훅을 다시 활성화하려면 웹훅을 테스트합니다.

사전 요구 사항:

  • 프로젝트 웹훅의 경우 해당 프로젝트에 대한 Maintainer 또는 Owner 권한이 있어야 합니다.
  • 그룹 웹훅의 경우 해당 그룹에 대한 Owner 권한이 있어야 합니다.
  • push events를 테스트하려면 프로젝트에 커밋이 하나 이상 있어야 합니다.

웹훅을 테스트하려면 다음과 같이 진행합니다.

  1. 상단 바에서 Search or go to를 선택하고 프로젝트나 그룹을 찾습니다.
  2. 왼쪽 사이드바에서 Settings > Webhooks를 선택해 이 프로젝트의 모든 웹훅을 확인합니다.
  3. 구성된 웹훅 목록에서 바로 웹훅을 테스트하려면 다음과 같이 진행합니다.
    1. 테스트할 웹훅을 찾습니다.
    2. Test 드롭다운 목록에서 테스트할 이벤트 유형을 선택합니다.
  4. 웹훅을 편집하면서 테스트하려면 다음과 같이 진행합니다.
    1. 테스트할 웹훅을 찾아 Edit를 선택합니다.
    2. 웹훅을 변경합니다.
    3. Test 드롭다운 목록을 선택한 다음 테스트할 이벤트 유형을 선택합니다.

프로젝트 및 그룹 웹훅의 일부 이벤트 유형은 테스트를 지원하지 않습니다. 자세한 내용은 이슈 379201을 참고합니다.

웹훅 참조#

이 기술 참조 자료는 다음 목적으로 사용합니다.

  • GitLab 웹훅의 작동 방식을 이해합니다.
  • 웹훅을 시스템과 통합합니다.
  • 웹훅 구성을 설정하고, 문제를 해결하고, 최적화합니다.

웹훅 수신기 요구 사항#

웹훅 전달의 신뢰성을 보장하려면 빠르고 안정적인 웹훅 수신기 엔드포인트를 구현합니다.

느리거나 불안정하거나 잘못 구성된 수신기는 자동으로 비활성화될 수 있습니다. 유효하지 않은 HTTP 응답은 실패한 요청으로 처리됩니다.

웹훅 수신기를 최적화하려면 다음과 같이 진행합니다.

  1. 200 또는 201 상태로 빠르게 응답합니다.
    • 같은 요청에서 웹훅을 처리하지 않습니다.
    • 웹훅을 받은 뒤 처리하도록 큐를 사용합니다.
    • GitLab.com에서 자동 비활성화되지 않도록 제한 시간 전에 응답합니다.
  2. 중복 이벤트 가능성에 대비합니다.
    • 웹훅에서 제한 시간이 초과되는 경우 중복 이벤트에 대비합니다.
    • 엔드포인트가 일관되게 빠르고 안정적인지 확인합니다.
  3. 응답 헤더와 본문을 최소화합니다.
    • GitLab은 이후 검사를 위해 응답 헤더와 본문을 저장합니다.
    • 반환하는 헤더의 개수와 크기를 제한합니다.
    • 본문을 비워 응답하는 방안을 고려합니다.
  4. 적절한 상태 코드를 사용합니다.
    • 클라이언트 오류 상태 응답(4xx 범위)은 잘못 구성된 웹훅에만 반환합니다.
    • 지원하지 않는 이벤트에는 400을 반환하거나 페이로드를 무시합니다.
    • 처리한 이벤트에는 500 서버 오류 응답을 사용하지 않습니다.

자동 비활성화된 웹훅#

히스토리
Feature flag

이 기능의 가용성은 기능 플래그로 제어됩니다. 자세한 내용은 히스토리를 참고합니다.

GitLab은 연속 4회 실패한 프로젝트 또는 그룹 웹훅을 자동으로 비활성화합니다.

자동 비활성화된 웹훅을 확인하려면 다음과 같이 진행합니다.

  1. 상단 바에서 Search or go to를 선택하고 프로젝트나 그룹을 찾습니다.
  2. 왼쪽 사이드바에서 Settings > Webhooks를 선택합니다.

웹훅 목록에서 자동 비활성화된 웹훅은 다음과 같이 표시됩니다.

  • 연속 4회 실패하면 Temporarily disabled
  • 연속 40회 실패하면 Disabled

비활성화 및 일시 비활성화 상태 배지를 보여 주는 웹훅 목록.

일시적으로 비활성화된 웹훅#

웹훅이 연속 4회 실패하면 일시적으로 비활성화됩니다. 웹훅이 연속 40회 실패하면 영구적으로 비활성화됩니다.

다음 경우에 실패가 발생합니다.

  • 웹훅 수신기가 4xx 또는 5xx 범위의 응답 코드를 반환합니다.
  • 웹훅이 웹훅 수신기에 연결하려 할 때 제한 시간을 초과합니다.
  • 웹훅에서 그 밖의 HTTP 오류가 발생합니다.

일시적으로 비활성화된 웹훅은 처음에 1분 동안 비활성화되고, 이후 실패가 반복되면 최대 24시간까지 기간이 늘어납니다. 이 기간이 지나면 이러한 웹훅은 자동으로 다시 활성화됩니다.

영구적으로 비활성화된 웹훅#

웹훅이 연속 40회 실패하면 영구적으로 비활성화됩니다. 일시적으로 비활성화된 웹훅과 달리 이러한 웹훅은 자동으로 다시 활성화되지 않습니다.

GitLab 17.10 및 이전 버전에서 영구적으로 비활성화된 웹훅은 데이터 마이그레이션을 거쳤습니다. 이러한 웹훅은 UI가 실패 40회로 표시하더라도 Recent events에는 실패 4회로 표시될 수 있습니다.

비활성화된 웹훅 다시 활성화#

비활성화된 웹훅을 다시 활성화하려면 테스트 요청을 보냅니다. 테스트 요청이 2xx 범위의 응답 코드를 반환하면 웹훅이 다시 활성화됩니다.

전달 헤더#

히스토리

GitLab은 엔드포인트로 보내는 웹훅 요청에 다음 헤더를 포함합니다.

Header Description Example
Idempotency-Key 웹훅 재시도 간에 유지되는 고유 ID. 레거시 이유로 제공됩니다. webhook-id를 우선 사용합니다. "f5e5f430-f57b-4e6e-9fac-d9128cd7232f"
User-Agent "Gitlab/" 형식의 사용자 에이전트. "GitLab/15.5.0-pre"
webhook-id 웹훅 재시도 간에 유지되는 고유 메시지 ID. Idempotency-Key와 같습니다. "f5e5f430-f57b-4e6e-9fac-d9128cd7232f"
webhook-signature 각각 v1,{base64_signature} 형식인, 공백으로 구분된 HMAC-SHA256 서명 목록. 서명 토큰이 구성된 경우에만 포함됩니다. "v1,abc123def456=="
webhook-timestamp 요청이 생성된 시점의 Unix 타임스탬프(에포크 이후 초). "1744578123"
X-Gitlab-Event-UUID 재귀적이지 않은 웹훅의 고유 ID. 재귀 웹훅(이전 웹훅이 트리거한 웹훅)은 같은 값을 공유합니다. "13792a34-cac6-4fda-95a8-c58e00a3954e"
X-Gitlab-Event 웹훅 유형 이름. " Hook" 형식의 이벤트 유형에 해당합니다. "Push Hook"
X-Gitlab-Instance 웹훅을 보낸 GitLab 인스턴스의 호스트 이름. "https://gitlab.com"
X-Gitlab-Token 웹훅의 시크릿 토큰으로, 일반 텍스트로 전송됩니다. 시크릿 토큰이 구성된 경우에만 포함됩니다. "my-secret-token"
X-Gitlab-Webhook-UUID 각 웹훅의 고유 ID. "02affd2d-2cba-4033-917d-ec22d5dc4b38"

웹훅 본문의 이미지 URL 표시#

GitLab은 웹훅 본문에서 상대 이미지 참조를 절대 URL로 다시 작성합니다.

이미지 URL 재작성 예시#

머지 리퀘스트, 코멘트, 위키 페이지의 원래 이미지 참조가 다음과 같다면:

![A Markdown image with a relative URL.](/uploads/$sha/image.png)

웹훅 본문에서 다시 작성된 이미지 참조는 다음과 같습니다.

![A Markdown image with an absolute URL.](https://gitlab.example.com/-/project/:id/uploads//image.png)

이 예시는 다음을 전제합니다.

  • GitLab이 gitlab.example.com에 설치되어 있습니다.
  • 프로젝트 ID는 123입니다.

이미지 URL 재작성의 예외#

GitLab은 다음 경우에 이미지 URL을 다시 작성하지 않습니다.

  • 이미 HTTP, HTTPS 또는 프로토콜 상대 URL을 사용하는 경우.
  • 링크 레이블처럼 고급 Markdown 기능을 사용하는 경우.

관련 주제#