티스토리 뷰
GitHub Webhook 이벤트 처리 최적화 및 로깅 시스템 구축
이전 글에서는 GitHub Webhook을 활용하여 GitHub Project 보드 상태를 자동으로 변경하는 방법을 다뤘습니다.
이번 글에서는 Webhook 이벤트 처리를 최적화하고, 로깅 및 모니터링 시스템을 구축하여 안정적인 운영을 지원하는 방법을 설명합니다.
1. Webhook 이벤트 최적화의 필요성
GitHub Webhook은 다양한 이벤트를 발생시키며, 요청이 많아질수록 부하 관리 및 이벤트 중복 처리 방지가 중요해집니다.
Webhook 이벤트 처리 시 고려해야 할 사항은 다음과 같습니다.
✅ Webhook 이벤트 최적화 전략
✔️ 이벤트 큐를 활용한 비동기 처리 – Redis와 Bull을 활용하여 이벤트를 큐에 저장 후 순차 실행
✔️ 이벤트 중복 처리 방지 – 동일한 이벤트가 여러 번 처리되지 않도록 ID 기반 중복 필터링
✔️ 에러 핸들링 및 재시도 로직 적용 – 네트워크 오류 발생 시 자동 재시도
2. Webhook 이벤트 처리 아키텍처 개선
🔹 기존 방식 vs 개선된 방식 비교
기존 방식 개선된 방식
Webhook 요청을 즉시 처리 | 요청을 이벤트 큐에 저장 후 비동기 처리 |
이벤트 중복 방지 없음 | 이벤트 ID를 저장하여 중복 요청 차단 |
네트워크 오류 시 실패 | 실패한 요청은 일정 시간 후 재시도 |
3. Redis + Bull을 활용한 Webhook 이벤트 큐 적용
🔹 3-1. Redis 및 Bull 패키지 설치
npm install bull ioredis @nestjs/bull
🔹 3-2. Webhook 이벤트를 큐에 저장하여 비동기 처리
📌 src/webhook/webhook.processor.ts
import { Process, Processor } from '@nestjs/bull';
import { Job } from 'bull';
import axios from 'axios';
@Processor('webhookQueue')
export class WebhookProcessor {
@Process()
async handleWebhook(job: Job) {
const { event, payload } = job.data;
console.log(`🔄 Processing Webhook Event: ${event}`);
try {
if (event === 'issues' && payload.action === 'opened') {
console.log(`📌 Issue Created: #${payload.issue.number}`);
await this.updateIssueStatus(payload.issue.number);
}
if (event === 'pull_request' && payload.action === 'opened') {
console.log(`🚀 PR Created: #${payload.pull_request.number}`);
await this.assignReviewers(payload.pull_request.number);
}
} catch (error) {
console.error(`❌ Webhook Processing Failed: ${error.message}`);
throw error; // 자동 재시도 가능하도록 예외 발생
}
}
private async updateIssueStatus(issueNumber: number) {
// GitHub API 호출하여 Issue 상태 업데이트
console.log(`✅ Issue #${issueNumber} updated successfully`);
}
private async assignReviewers(prNumber: number) {
// GitHub API 호출하여 PR 리뷰어 자동 할당
console.log(`✅ Reviewers assigned to PR #${prNumber}`);
}
}
💡 handleWebhook()에서 Webhook 이벤트를 처리하며, 실패 시 자동으로 재시도됩니다.
🔹 3-3. Webhook 컨트롤러에서 Bull Queue 적용
📌 src/webhook/webhook.controller.ts
import { Controller, Post, Headers, Body } from '@nestjs/common';
import { InjectQueue } from '@nestjs/bull';
import { Queue } from 'bull';
@Controller('webhook')
export class WebhookController {
constructor(@InjectQueue('webhookQueue') private webhookQueue: Queue) {}
@Post()
async handleWebhook(@Headers('x-github-event') event: string, @Body() payload: any) {
console.log(`📥 Received Webhook Event: ${event}`);
// 이벤트 큐에 추가하여 비동기 처리
await this.webhookQueue.add({ event, payload });
return { message: `Webhook event queued: ${event}` };
}
}
💡 Webhook 요청을 즉시 처리하는 것이 아니라, 큐에 저장한 후 WebhookProcessor에서 비동기 처리됩니다.
4. Webhook 이벤트 중복 처리 방지
GitHub에서 동일한 이벤트가 여러 번 발생할 경우 중복 요청을 방지해야 합니다.
🔹 4-1. 이벤트 ID를 기반으로 중복 요청 방지
📌 src/webhook/webhook.processor.ts
import { Process, Processor } from '@nestjs/bull';
import { Job } from 'bull';
import * as Redis from 'ioredis';
const redis = new Redis();
@Processor('webhookQueue')
export class WebhookProcessor {
@Process()
async handleWebhook(job: Job) {
const { event, payload } = job.data;
const eventId = payload.issue?.id || payload.pull_request?.id;
// Redis에서 기존 이벤트 ID 확인
const exists = await redis.get(`event:${eventId}`);
if (exists) {
console.log(`⚠️ Duplicate Event Ignored: ${eventId}`);
return;
}
// 이벤트 ID 저장 (10분 동안 유지)
await redis.setex(`event:${eventId}`, 600, 'processed');
console.log(`🔄 Processing Webhook Event: ${event}`);
}
}
💡 이벤트 ID를 Redis에 저장하여 중복 요청을 방지할 수 있습니다.
5. Webhook 요청 로그 저장 및 대시보드 구축
Webhook 요청 로그를 저장하면 이벤트 처리 상태를 추적할 수 있습니다.
🔹 5-1. PostgreSQL에 Webhook 로그 저장
📌 prisma/schema.prisma
model WebhookLog {
id String @id @default(uuid())
eventType String
payload Json
createdAt DateTime @default(now())
}
📌 src/webhook/webhook.service.ts
import { Injectable } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
@Injectable()
export class WebhookService {
constructor(private readonly prisma: PrismaService) {}
async saveWebhookLog(eventType: string, payload: any) {
return this.prisma.webhookLog.create({
data: { eventType, payload },
});
}
}
🔹 5-2. Webhook 요청 대시보드 구현 (Next.js)
📌 Webhook 요청 목록 조회 API (src/webhook/webhook.controller.ts)
import { Get, Controller } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
@Controller('webhook')
export class WebhookController {
constructor(private readonly prisma: PrismaService) {}
@Get()
async getWebhookLogs() {
return this.prisma.webhookLog.findMany({ orderBy: { createdAt: 'desc' } });
}
}
💡 Next.js를 활용하여 Webhook 요청 로그를 시각화하면 운영이 더욱 편리해집니다.
6. 마무리 및 다음 글 예고
이번 글에서는 Webhook 이벤트 최적화, 큐 기반 비동기 처리, 중복 요청 방지, 로깅 시스템 구축을 다뤘습니다.
다음 글에서는 Webhook 이벤트 보안 강화 및 배포 전략을 다룰 예정입니다! 🚀
'모음집 > git' 카테고리의 다른 글
GitHub Webhook 실전 적용 사례: 자동화된 팀 협업 시스템 구축 (0) | 2025.03.22 |
---|---|
GitHub Webhook 이벤트 보안 강화 및 배포 전략 (0) | 2025.03.21 |
GitHub Webhook을 활용한 GitHub Project 자동화 및 상태 관리 (0) | 2025.03.20 |
GitHub Webhook을 활용한 Issue 및 Pull Request 자동 관리 시스템 구축 (0) | 2025.03.19 |
GitHub Webhook을 활용한 CI/CD 자동화 시스템 구축 (0) | 2025.03.18 |
- Total
- Today
- Yesterday
- 웹개발
- 프론트엔드
- nextJS
- CI/CD
- AI 자동화
- 개발블로그
- Docker
- 관리자
- 스마트 컨트랙트
- App Router
- github
- rag
- SEO 최적화
- REACT
- 백엔드개발
- PostgreSQL
- nodejs
- kotlin
- Webpack
- fastapi
- Prisma
- SEO최적화
- AI챗봇
- LangChain
- llm
- Ktor
- NestJS
- Next.js
- seo 최적화 10개
- gatsbyjs
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |