1. 목적
레포지토리의 개발 활동(PR, Push, Issue 등)을 실시간으로 Discord 채널에 전달해 팀 협업 효율을 높이기 위함이다.
이전에는 Slack을 사용했지만, 메세지가 사라지는 문제가 있어서 디스코드로 사용하려고 한다.
노션과 피그마도 알림 시스템 자동화를 구축하려 했지만, 유료버젼만 가능했다. 우회하는 방법이 있을지 모르겠지만, 우리 팀에게 꼭 필요하진 않아서 보류했다.
이후 서버로그 중 위험한 시그널을 디스코드로 전송하도록 추후 구축할 예정이다.
스타트업은.. 비용을 아껴야해..
스타트업은.. 비용을 아껴야해..
2. 구현 방식
A. Cloudflare Worker를 Webhook 중계 서버로 사용
- 서버 없이 운영 가능한 Worker 환경을 사용해 GitHub Webhook 이벤트를 수신
- 이벤트 내용을 Discord Webhook URL로 포워딩
- Worker 내에서 이벤트 타입별 메시지 포맷 커스터마이징
B. GitHub Webhook 설정
- Repository → Settings → Webhooks
- Cloudflare Worker URL을 Webhook Receiver로 등록
- 아래 이벤트만 선택해 알림 최소화
- Pull requests
- Pull request reviews
- Pull request review comments
- Pushes
- Issues
- Issue comments
3. 예상 구현 단계
- Cloudflare Worker 생성
- DISCORD_WEBHOOK_URL 환경변수 등록
- GitHub Webhook → Worker URL 연결
- 이벤트 타입별 메시지 포맷 작성
- Discord webhook 메시지 검증 및 최종 적용
4. 상세 방법
1) Cloudflare Worker 생성
- Cloudflare Dashboard 접속
- Workers & Pages 누르면 Get started 화면 나옴 → start with Hello World! 클릭

3. 이름 입력하고 Deploy
4. 우측 상단 Edit Code 들어가서 아래의 코드 붙여넣기
export default {
async fetch(request, env) {
if (request.method !== "POST") {
return new Response("OK");
}
let bodyText = await request.text();
// GitHub가 content-type을 이상하게 보내면 JSON 파싱에 실패할 수 있음 → 안전하게 처리
let body = {};
try {
body = JSON.parse(bodyText);
} catch (e) {
return new Response("Invalid JSON", { status: 400 });
}
const event = request.headers.get("X-GitHub-Event") || "unknown";
let message = "";
switch (event) {
case "pull_request":
message = formatPullRequest(body);
break;
case "pull_request_review":
message = formatPRReview(body);
break;
case "pull_request_review_comment":
message = formatPRReviewComment(body);
break;
case "push":
message = formatPush(body);
break;
case "issues":
message = formatIssue(body);
break;
case "issue_comment":
message = formatIssueComment(body);
break;
default:
message = `📌 *Unhandled GitHub Event:* ${event}`;
break;
}
await fetch(env.DISCORD_WEBHOOK_URL, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ content: message })
});
return new Response("OK");
}
};
// ---------------- FORMATTERS --------------------
function formatPullRequest(body) {
const pr = body.pull_request || {};
return `🔀 **PR ${body.action?.toUpperCase() || ""}**
📌 *${pr.title || "(no title)"}*
👤 ${pr.user?.login || "unknown"}
➡️ ${pr.html_url || ""}`;
}
function formatPRReview(body) {
const review = body.review || {};
const pr = body.pull_request || {};
return `📝 **PR REVIEW ${body.action?.toUpperCase()}**
📌 *${pr.title || "(no title)"}*
👤 ${review.user?.login || "unknown"}
💬 ${review.body || "(no comment)"}
➡️ ${review.html_url || ""}`;
}
function formatPRReviewComment(body) {
const c = body.comment || {};
return `💬 **PR REVIEW COMMENT**
👤 ${c.user?.login || "unknown"}
💬 ${c.body || "(no comment)"}
➡️ ${c.html_url || ""}`;
}
function formatPush(body) {
const commits = (body.commits || [])
.map(c => `• ${c.message} — ${c.author?.name || "unknown"}`)
.join("\n");
return `📦 **PUSH**
👤 ${body.pusher?.name || "unknown"}
📁 ${body.ref?.replace("refs/heads/", "") || ""}
${commits}`;
}
function formatIssue(body) {
const issue = body.issue || {};
return `🐞 **ISSUE ${body.action?.toUpperCase()}**
📌 *${issue.title || "(no title)"}*
👤 ${issue.user?.login || "unknown"}
➡️ ${issue.html_url || ""}`;
}
function formatIssueComment(body) {
const issue = body.issue || {};
const c = body.comment || {};
return `💬 **ISSUE COMMENT**
📌 *${issue.title || "(no title)"}*
👤 ${c.user?.login || "unknown"}
💬 ${c.body || "(no comment)"}
➡️ ${c.html_url || ""}`;
}
Cloudflare Worker는 서버를 띄우지 않고도
GitHub → Worker → Discord 라우팅을 수행하는 Serverless Webhook Handler 역할을 한다.
2) DISCORD_WEBHOOK_URL 환경 변수 등록
- Cloudflare Worker → 사이드바에서 Settings 클릭
- Variable and Secrets 선택
type 안넣어도 됨, 이름 알아서 (DISCORD_WEBHOOK_URL), value에 디스코드 웹훅 url을 넣으면됨. - discord webhook Url은 아래 톱니 바퀴 클릭하고 좌측에서 연동 클릭


여기서 만들고 url 복사해오면 된다.
3) GitHub Webhook 설정
- GitHub Repository → Settings → Webhooks → Add Webhook
- Payload URL -> Cloudflare Worker 주소 입력(Cloudflare settings 맨위에 있음 밸류값으로)
- Content-Type은 application/json으로 넣으면 됨
- Secret 생략
- Which events would you like to trigger this webhook?
→ 아래 6개만 체크- Pull requests
- Pull request reviews
- Pull request review comments
- Pushes
- Issues
- Issue comments
4) 테스트 및 정상 동작 확인
- GitHub에서 Issue 하나 생성 → Worker Logs 확인
- Discord 채널에 메시지가 도착하면 성공
- 이후 PR, Push, Review 등 모든 이벤트도 동일하게 실시간 알림 제공됨
5) 장점
- 서버 비용 없음 → Cloudflare Worker 무료
- 응답 속도 빠름
- GitHub → Discord 실시간 Sync
- 팀 협업 투명성 증가
- 커스텀 가능 (이모지, 포맷, 필터 등 마음대로 바꿀 수 있음)
'지식 나눔' 카테고리의 다른 글
| [Vue] 오픈소스 이슈 제보 후기 (3) | 2025.07.24 |
|---|---|
| [Spring Security 6 + AWS] HTTP ERROR 403 해결 (Order Annotation와 securityMatcher 사용) (1) | 2025.01.25 |
| [Github Actions & Docker] unable to authenticate, attempted methods - 해결 (0) | 2025.01.20 |
| [Github Actions & Docker] error username and password required 해결 (0) | 2025.01.20 |
| Postman을 활용한 카카오톡 로그인 테스트 - Oauth2(Bad client credentials) (4) | 2024.01.28 |