⸻
1. 개요: 채널 하나로 끝내는 운영·개발 자동화
ChatOps는 실시간 채팅 인터페이스(Slack)를 통해 사람과 봇이 협업하며, 봇이 복잡한 CI/CD·인프라 명령을 대신 실행하게 하는 패러다임입니다.
• 컨텍스트 일원화: 이슈·PR·배포·모니터링 모두 한 채널에서
• 자동화 확장성: Slash Command·Interactive 버튼·Webhook으로 모든 시스템 연결
• 투명한 감사 로그: 누가 언제 무슨 명령을 내렸는지 채널 기록으로 보존
이 가이드에서는 Slack App 설정부터 Hubot 스크립팅, GitHub Webhook 연동, CI/CD 트리거, 고급 패턴까지 ‘끝판왕’ 수준으로 심층 정리합니다.
⸻
2. 전체 아키텍처
┌──────────┐ ┌───────────────┐ ┌─────────────────┐
│ Slack │◀──▶│ Hubot │◀──▶│ GitHub Webhook │
│ Workspace│ │ (Node.js Bot) │ │ Endpoint │
└──────────┘ └───────────────┘ └─────────────────┘
▲ ▲ ▲
│ Slash, Action │ CI/CD API 호출 │ GitHub PR·Issue 이벤트
│ Events │ (Jenkins, GHA) │
▼ ▼ ▼
┌─────────────────────────────────────────────────────────┐
│ 종합 ChatOps Bot: Slash Command, Dialog, Buttons, REST │
└─────────────────────────────────────────────────────────┘
1. Slack App: Slash Command & Interactive Components
2. Hubot: Slack Adapter + Express 서버로 Webhook/Action 처리
3. GitHub Webhook: PR·Issue 이벤트 → Hubot 라우터
4. CI/CD 연동: Hubot이 Jenkins/GitHub Actions/ArgoCD API 호출
⸻
3. Slack App & OAuth 설정
3.1 OAuth & Permissions
• Bot Token Scopes
• commands, chat:write, chat:write.public
• channels:read, groups:read, users:read
• incoming-webhook (옵션)
• OAuth Redirect:
• 설치형 앱 사용 시 /slack/oauth_redirect 엔드포인트 구현
• Signing Secret:
• 모든 요청에서 X-Slack-Signature 검증
3.2 Slash Command & Interactivity
• Slash Command 설정:
• /deploy, /status, /rollback 등 Command 당 Request URL
• Usage Hint에 예제 작성(예: /deploy web-app staging)
• Interactive Components
• 버튼, 메뉴 선택, 모달(Dialog)
• Request URL: /hubot/slack/actions
⸻
4. Hubot 설치 & 기본 구조
4.1 프로젝트 초기화
npm init -y
npm install hubot hubot-slack express body-parser @slack/events-api
yo hubot --adapter slack
4.2 파일 구조
hubot/
├── bin/ # hubot 실행 스크립트
├── external-scripts.json
├── Procfile # Heroku 등 배포용
├── scripts/
│ ├── deploy.js
│ ├── status.js
│ ├── github.js
│ └── utils.js
└── server.js # Express 서버 + Hubot 통합
4.3 server.js: Hubot + Express 결합
const Hubot = require('hubot');
const { createEventAdapter } = require('@slack/events-api');
const express = require('express');
const bodyParser = require('body-parser');
const slackSigningSecret = process.env.SLACK_SIGNING_SECRET;
const slackEvents = createEventAdapter(slackSigningSecret);
const app = express();
app.use('/hubot/slack/events', slackEvents.expressMiddleware());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.post('/hubot/slack/commands', require('./scripts/deploy').commandHandler);
app.post('/hubot/slack/actions', require('./scripts/actions').actionHandler);
app.post('/hubot/github', require('./scripts/github').webhookHandler);
// initialize Hubot
const robot = Hubot.Robot.run({
adapter: 'slack',
name: 'hubot',
slackToken: process.env.SLACK_BOT_TOKEN,
});
robot.loadFile(__dirname, 'scripts/utils.js');
robot.loadFile(__dirname, 'scripts/deploy.js');
robot.loadFile(__dirname, 'scripts/status.js');
robot.loadFile(__dirname, 'scripts/github.js');
⸻
5. Hubot 스크립팅: 주요 예제
5.1 Slash Command: /deploy
// scripts/deploy.js
module.exports.commandHandler = (req, res) => {
const text = req.body.text; // "web-app staging"
const [service, env] = text.split(/\s+/);
// 즉시 응답(200 OK)
res.json({ text: `🚀 배포 요청: *${service}* → *${env}* 처리 중...`, response_type: 'in_channel' });
// 백그라운드 명령 수행
const robot = req.robot;
robot.emit('deploy:start', { service, env, channel: req.body.channel_id });
};
// 로컬 이벤트 핸들러
module.exports = (robot) => {
robot.on('deploy:start', async (msg) => {
const { service, env, channel } = msg;
try {
const result = await utils.triggerBuild(service, env);
robot.adapter.client.chat.postMessage({ channel, text: `✅ 배포 성공: ${result.buildId}` });
} catch (e) {
robot.adapter.client.chat.postMessage({ channel, text: `❌ 배포 실패: ${e.message}` });
}
});
};
5.2 Interactive Button: 승인 프로세스
// scripts/actions.js
module.exports.actionHandler = (req, res) => {
const payload = JSON.parse(req.body.payload);
const action = payload.actions[0];
if (action.name === 'approve') {
res.send({ text: `👍 승인 완료: ${action.value}`, replace_original: false });
req.robot.emit('deploy:approve', { service: action.value, user: payload.user.id });
} else {
res.sendStatus(200);
}
};
// events in deploy.js
robot.on('deploy:needsApproval', ({ service, channel }) => {
robot.adapter.client.chat.postMessage({
channel,
text: `배포 승인 필요: ${service}`,
attachments: [{
text: "지금 승인하시겠습니까?",
fallback: "Approve deployment",
callback_id: "deploy_approve",
actions: [
{ name: "approve", text: "승인", type: "button", value: service }
]
}]
});
});
⸻
6. GitHub Webhook 처리
6.1 시그니처 검증 미들웨어
// scripts/github.js
const crypto = require('crypto');
function verifySignature(req) {
const signature = req.headers['x-hub-signature-256'];
const hmac = crypto.createHmac('sha256', process.env.GITHUB_WEBHOOK_SECRET);
hmac.update(JSON.stringify(req.body));
return signature === `sha256=${hmac.digest('hex')}`;
}
module.exports.webhookHandler = (req, res) => {
if (!verifySignature(req)) return res.sendStatus(400);
const event = req.headers['x-github-event'], payload = req.body;
if (event === 'pull_request' && payload.action === 'opened') {
const channel = 'dev-team';
const msg = `🔔 새 PR by *${payload.sender.login}*:\n>*${payload.pull_request.title}*\n${payload.pull_request.html_url}`;
req.robot.adapter.client.chat.postMessage({ channel, text: msg });
}
res.sendStatus(200);
};
⸻
7. CI/CD 연동
7.1 Jenkins 빌드 트리거
// scripts/utils.js
const axios = require('axios');
async function triggerBuild(service, env) {
const resp = await axios.post(process.env.JENKINS_URL, null, {
params: { token: process.env.JENKINS_TOKEN, SERVICE: service, ENV: env }
});
return { buildId: resp.headers['x-jenkins-build-number'] };
}
module.exports = { triggerBuild };
7.2 GitHub Actions 호출
async function triggerGHA(service, env) {
await axios.post(
`https://api.github.com/repos/${process.env.GH_REPO}/actions/workflows/deploy.yml/dispatches`,
{ ref: 'main', inputs: { service, env } },
{ headers: { Authorization: `token ${process.env.GH_TOKEN}` } }
);
}
⸻
8. 고급 패턴 & 팁
1. Ephemeral Response
res.json({ response_type: 'ephemeral', text: '개인 DM: 처리 중...' });
2. Command Queueing
• async.queue로 동시성 제어: 서비스별 최대 1개 큐
3. Rate Limiting
• express-rate-limit 미들웨어로 슬래시 커맨드 남용 방지
4. OAuth Installed App
• 사용자 액션 별 권한 분리: /deploy는 Admin만 가능
5. Metrics & Tracing
• prom-client 로 명령 처리 시간·성공률 집계 → Grafana 대시보드
• OpenTelemetry Node SDK로 분산 트레이싱 연동
6. Self-Healing
• 실패시 자동 재시도(retry 로직) + 알림
7. Dynamic Help
robot.respond(/help/i, (res) => {
const cmds = ['/deploy', '/status', '/rollback'];
res.send(`사용 명령: ${cmds.join(', ')}`);
});
⸻
9. 보안 고려사항
• Slack Signing Secret: 모든 요청 검증
• GitHub Webhook Secret: sha256 시그니처 체크
• 환경변수 관리: Vault·KMS·Kubernetes Secrets
• HTTPS 강제: 봇 서버와 Slack/GitHub 통신 암호화
⸻
10. 결론
• Slack App: Slash + Interactive
• Hubot: 스크립팅 + Express + Adapter
• GitHub Webhook: 이벤트 수신 + 서명 검증
• CI/CD API: Jenkins·GitHub Actions 등 호출
• 고급 패턴: Rate Limit, OAuth, Metrics, Self-Healing
“교과서론 절대 알려주지 않는, 실리콘밸리·심천 IT기업 최정예 개발자급 ChatOps”을 직접 구현해 보세요. Slack 하나로 모든 작업이 실행되는 혁신적 생산성 향상을 경험할 수 있습니다!
'IT & Tech 정보' 카테고리의 다른 글
Chaos Engineering 통합 끝판왕 가이드: Chaos Mesh & LitmusChaos CI 파이프라인 (0) | 2025.05.26 |
---|---|
AI 기반 테스트 우선순위화 끝판왕 가이드: ML 모델로 Test Suite 최적화 (0) | 2025.05.26 |
ChatOps 워크플로우 끝판왕 가이드 Slack · Hubot · GitHub Webhook 자동화 (0) | 2025.05.26 |
DB 마이그레이션 자동화 끝판왕 가이드 (0) | 2025.05.26 |
CI 비밀 관리 끝판왕 가이드: Vault & Kubernetes External Secrets 동적 주입 (0) | 2025.05.26 |