Skip to main content

웹후크 배달 처리

웹후크 배달을 수신 대기하고 그에 응답하는 코드를 작성하는 방법을 알아봅니다.

소개

웹후크를 만들 때 URL을 지정하고 이벤트 유형을 구독합니다. 웹후크가 구독되는 이벤트가 발생하면 GitHub 이벤트에 대한 데이터가 포함된 HTTP 요청을 지정한 URL로 보냅니다. 서버가 해당 URL에서 웹후크 배달을 수신 대기하도록 설정되어 있는 경우 수신 시 작업을 수행할 수 있습니다.

이 문서에서는 서버가 웹후크 배달을 수신 대기하고 그에 응답할 수 있도록 코드를 작성하는 방법을 설명합니다. 컴퓨터 또는 codespace를 로컬 서버로 사용하여 코드를 테스트합니다.

설정

웹후크를 로컬로 테스트하기 위해 웹후크 프록시 URL을 사용하여 웹후크를 컴퓨터 또는 코드스페이스로 GitHub 전달할 수 있습니다. 이 문서에서는 smee.io를 사용하여 웹후크 프록시 URL을 제공하고 웹후크를 전달합니다.

웹후크 프록시 URL 가져오기

  1. 브라우저에서 https://smee.io/(으)로 이동합니다.
  2. 새 채널 시작을 클릭합니다.
  3. "웹후크 프록시 URL" 아래에 전체 URL을 복사합니다. 다음 설정 단계에서 이 URL을 사용합니다.

웹후크 전달

  1. smee-client가 아직 설치되어 있지 않은 경우 터미널에서 다음 명령을 실행합니다.

    Shell
    npm install --global smee-client
    
  2. smee.io에서 전달한 웹후크를 수신하려면 터미널에서 다음 명령을 실행합니다. WEBHOOK_PROXY_URL을 이전의 웹후크 프록시 URL로 바꿉니다.

    Shell
    smee --url WEBHOOK_PROXY_URL --path /webhook --port 3000
    

    다음과 같은 출력이 표시됩니다. 여기서 WEBHOOK_PROXY_URL은 웹후크 프록시 URL입니다.

    Shell
    Forwarding WEBHOOK_PROXY_URL to http://127.0.0.1:3000/webhook
    Connected WEBHOOK_PROXY_URL
    

    경로는 /webhook이고 포트는 3000입니다. 나중에 웹후크 배달을 처리하는 코드를 작성할 때 이 값을 사용합니다.

  3. 웹후크를 테스트하는 동안 계속 실행해 둡니다. 웹후크 전달을 중지하려면 Ctrl+C를 입력합니다.

웹후크 만들기

  1. 다음 설정을 사용하여 웹후크를 만듭니다. 자세한 내용은 웹후크 만들기을(를) 참조하세요.

    • URL은 앞서 복사한 웹후크 프록시 URL을 사용합니다.
    • 콘텐츠 유형을 선택할 수 있는 옵션이 있는 경우 JSON을 사용합니다.

웹후크 배달을 처리하는 코드 작성

웹후크 배달을 처리하려면 다음을 수행하는 코드를 작성해야 합니다.

  • 웹후크 URL에 대한 요청을 수신 대기하도록 서버 초기화
  • 요청에서 HTTP 헤더 및 본문 읽기
  • 요청에 대한 응답으로 원하는 작업 수행

서버에서 실행할 수 있는 모든 프로그래밍 언어를 사용할 수 있습니다.

다음 예에서는 웹후크 배달이 수신되면 메시지를 출력합니다. 그러나 API에 대한 요청 또는 Slack 메시지 보내기와 같은 다른 작업을 수행하도록 코드를 수정할 GitHub 수 있습니다.

Ruby 예제

이 예에서는 Ruby gem인 Sinatra를 사용하여 경로를 정의하고 HTTP 요청을 처리합니다. 자세한 내용은 Sinatra 추가 정보를 참조하세요.

Ruby 예제: 종속성 설치

이 예를 사용하려면 Ruby 프로젝트에 sinatra gem을 설치해야 합니다. 예를 들면 Bundler를 사용하여 설치할 수 있습니다.

  1. Bundler가 아직 설치되어 있지 않은 경우 해당 터미널에서 다음 명령을 실행합니다.

    Shell
    gem install bundler
    
  2. 앱에 Gemfile이 없는 경우 터미널에서 다음 명령을 실행합니다.

    Shell
    bundle init
    
  3. 앱에 Gemfile.lock이 없는 경우 터미널에서 다음 명령을 실행합니다.

    Shell
    bundle install
    
  4. 터미널에서 다음 명령을 실행하여 Sinatra gem을 설치합니다.

    Shell
    bundle add sinatra
    

Ruby 예제: 코드 작성

다음 내용으로 Ruby 파일을 만듭니다. 웹후크가 구독 중인 이벤트 유형뿐만 아니라, 웹후크를 생성할 때 ping에서 보내는 GitHub 이벤트도 처리하도록 코드를 수정하세요. 이 예에서는 issuesping 이벤트를 처리합니다.

Ruby
require 'sinatra'
require 'json'

These are the dependencies for this code. You installed the sinatra gem earlier. For more information, see Ruby example: Install dependencies. The json library is a standard Ruby library, so you don't need to install it.

post '/webhook' do

The /webhook route matches the path that you specified for the smee.io forwarding. For more information, see Forward webhooks.

Once you deploy your code to a server and update your webhook URL, you should change this to match the path portion of the URL for your webhook.

  status 202

Respond to indicate that the delivery was successfully received. Your server should respond with a 2XX response within 10 seconds of receiving a webhook delivery. If your server takes longer than that to respond, then GitHub terminates the connection and considers the delivery a failure.

  github_event = request.env['HTTP_X_GITHUB_EVENT']

Check the X-GitHub-Event header to learn what event type was sent. Sinatra changes X-GitHub-Event to HTTP_X_GITHUB_EVENT.

  if github_event == "issues"
    data = JSON.parse(request.body.read)
    action = data['action']
    if action == "opened"
      puts "An issue was opened with this title: #{data['issue']['title']}"
    elsif action == "closed"
      puts "An issue was closed by #{data['issue']['user']['login']}"
    else
      puts "Unhandled action for the issue event: #{action}"
    end
  elsif github_event == "ping"
    puts "GitHub sent the ping event"
  else
    puts "Unhandled event: #{github_event}"
  end
end

You should add logic to handle each event type that your webhook is subscribed to. For example, this code handles the issues and ping events.

If any events have an action field, you should also add logic to handle each action that you are interested in. For example, this code handles the opened and closed actions for the issue event.

For more information about the data that you can expect for each event type, see AUTOTITLE.

# These are the dependencies for this code. You installed the `sinatra` gem earlier. For more information, see [Ruby example: Install dependencies](#ruby-example-install-dependencies). The `json` library is a standard Ruby library, so you don't need to install it.
require 'sinatra'
require 'json'

# The `/webhook` route matches the path that you specified for the smee.io forwarding. For more information, see [Forward webhooks](#forward-webhooks).
#
# Once you deploy your code to a server and update your webhook URL, you should change this to match the path portion of the URL for your webhook.
post '/webhook' do

  # Respond to indicate that the delivery was successfully received.
  # Your server should respond with a 2XX response within 10 seconds of receiving a webhook delivery. If your server takes longer than that to respond, then GitHub terminates the connection and considers the delivery a failure.
  status 202

  # Check the `X-GitHub-Event` header to learn what event type was sent.
  # Sinatra changes `X-GitHub-Event` to `HTTP_X_GITHUB_EVENT`.
  github_event = request.env['HTTP_X_GITHUB_EVENT']

  # You should add logic to handle each event type that your webhook is subscribed to.
  # For example, this code handles the `issues` and `ping` events.
  #
  # If any events have an `action` field, you should also add logic to handle each action that you are interested in.
  # For example, this code handles the `opened` and `closed` actions for the `issue` event.
  #
  # For more information about the data that you can expect for each event type, see [AUTOTITLE](/webhooks/webhook-events-and-payloads).
  if github_event == "issues"
    data = JSON.parse(request.body.read)
    action = data['action']
    if action == "opened"
      puts "An issue was opened with this title: #{data['issue']['title']}"
    elsif action == "closed"
      puts "An issue was closed by #{data['issue']['user']['login']}"
    else
      puts "Unhandled action for the issue event: #{action}"
    end
  elsif github_event == "ping"
    puts "GitHub sent the ping event"
  else
    puts "Unhandled event: #{github_event}"
  end
end

Ruby 예제: 코드 테스트

웹후크를 테스트하려면 컴퓨터 또는 codespace를 로컬 서버 역할로 사용할 수 있습니다. 이 단계에 문제가 있는 경우 문제 해결을 참조하세요.

  1. 웹후크를 전달하고 있는지 확인합니다. 더 이상 웹후크를 전달하지 않는 경우 웹후크 전달의 단계를 다시 따릅니다.

  2. 별도의 터미널 창에서 다음 명령을 실행하여 컴퓨터 또는 codespace에서 로컬 서버를 시작합니다. FILE_PATH를 이전 섹션의 코드가 저장된 파일의 경로로 바꿉니다. PORT=3000은 이전 단계에서 웹후크 전달에 지정한 포트와 일치합니다.

    Shell
    PORT=3000 ruby FILE_NAME
    

    출력 결과에서 "Sinatra가 3000에서 스테이징되었습니다."와 같은 유사한 메세지를 확인하실 수 있을 것입니다.

  3. 웹후크를 작동시킵니다. 예를 들어 issues 이벤트를 구독하는 리포지토리 웹후크를 만든 경우 리포지토리에서 이슈를 엽니다. 이전 웹후크 배달을 다시 배달할 수도 있습니다. 자세한 내용은 웹후크 다시 제공을(를) 참조하세요.

  4. smee.io에서 웹후크 프록시 URL로 이동합니다. 트리거하거나 다시 배달한 이벤트에 해당하는 이벤트가 표시되어야 합니다. 이는 지정한 GitHub 페이로드 URL에 웹후크 배달을 성공적으로 전송했음을 나타냅니다.

  5. smee --url WEBHOOK_PROXY_URL --path /webhook --port 3000를 실행한 터미널 창에 POST http://127.0.0.1:3000/webhook - 202와 같은 내용이 표시되어야 합니다. 이는 smee가 웹후크를 로컬 서버로 전달했음을 나타냅니다.

  6. PORT=3000 ruby FILE_NAME을(를) 실행한 터미널 창에 전송한 이벤트에 해당하는 메시지가 표시되어야 합니다. 예를 들어 위의 예제 코드를 사용하고 이벤트를 다시 배달한 ping 경우 "GitHub ping 이벤트를 보냈습니다."가 표시됩니다. Sinatra가 자동으로 출력하는 다른 몇 줄의 메시지들도 함께 보일 수 있습니다.

  7. 두 터미널 창 모두에서 Ctrl+C 를 입력하여 로컬 서버를 중지하고 전달된 웹후크 수신 대기를 중지합니다.

이제 코드를 로컬로 테스트했으므로 프로덕션에서 웹후크를 사용하도록 변경할 수 있습니다. 자세한 내용은 다음 단계를 참조합니다. 코드를 테스트하는 데 문제가 있는 경우 문제 해결의 단계를 시도해 보세요.

JavaScript 예제

이 예에서는 Node.js 및 Express 라이브러리를 사용하여 경로를 정의하고 HTTP 요청을 처리합니다. 자세한 내용은 expressjs.com을 참조하세요.

's Octokit.js SDK를 사용하는 GitHub예제는 웹후크 이벤트에 응답하는 GitHub 앱 빌드을 참조하세요.

이 예에서 Node.js 버전 12 이상 및 npm 버전 6.12.0 이상을 실행하려면 컴퓨터 또는 codespace가 필요합니다. 자세한 내용은 Node.js를 참조하세요.

JavaScript 예제: 종속성 설치

이 예를 사용하려면 Node.js 프로젝트에 express 라이브러리를 설치해야 합니다. 예시:

Shell
npm install express

JavaScript 예제: 코드 작성

다음 내용으로 JavaScript 파일을 만듭니다. 웹후크가 구독 중인 이벤트 유형뿐만 아니라, 웹후크를 생성할 때 ping에서 보내는 GitHub 이벤트도 처리하도록 코드를 수정하세요. 이 예에서는 issuesping 이벤트를 처리합니다.

JavaScript
const express = require('express');

You installed the express library earlier. For more information, see JavaScript example: Install dependencies.

const app = express();

This initializes a new Express application.

app.post('/webhook', express.json({type: 'application/json'}), (request, response) => {

This defines a POST route at the /webhook path. This path matches the path that you specified for the smee.io forwarding. For more information, see Forward webhooks.

Once you deploy your code to a server and update your webhook URL, you should change this to match the path portion of the URL for your webhook.

  response.status(202).send(