Slack Bot: Claude Code 활용 가이드
slack bot: Claude Code 활용. 실용적인 팁과 코드 예시를 포함합니다.
Slack Bot개발をClaude Code로 효율화하기
Slack Botを使えば、チーム内の워크플로우を자동화し、業務効率を大幅に改善할 수 있습니다。Bolt SDK를 사용한개발は比較的간단합니다が、이벤트処理や모달구축には多くの보일러플레이트が필요합니다。Claude Codeを활용して、효율적으로Slack Botを구축합시다。
프로젝트のセットアップ
> Slack Botの프로젝트をBolt SDKで생성して。
> TypeScript、Socket Mode대응で。
npm init -y
npm install @slack/bolt @slack/web-api
npm install -D typescript @types/node tsx
// src/app.ts
import { App, LogLevel } from '@slack/bolt';
const app = new App({
token: process.env.SLACK_BOT_TOKEN!,
signingSecret: process.env.SLACK_SIGNING_SECRET!,
socketMode: true,
appToken: process.env.SLACK_APP_TOKEN!,
logLevel: LogLevel.INFO,
});
// ボットの起動
(async () => {
await app.start();
console.log('Slack Bot is running!');
})();
export default app;
スラッシュコマンドの구현
> /task コマンドで태스크관리する機能を作って。
> 추가、목록、완료の3つのサブコマンドに대응して。
// src/commands/task.ts
import { App } from '@slack/bolt';
interface Task {
id: string;
title: string;
assignee: string;
completed: boolean;
createdAt: string;
}
const tasks = new Map<string, Task[]>();
export function registerTaskCommand(app: App) {
app.command('/task', async ({ command, ack, respond }) => {
await ack();
const [action, ...args] = command.text.split(' ');
const channelId = command.channel_id;
switch (action) {
case 'add': {
const title = args.join(' ');
if (!title) {
await respond('タスク名を入力してください: `/task add タスク名`');
return;
}
const channelTasks = tasks.get(channelId) || [];
const newTask: Task = {
id: `task-${Date.now()}`,
title,
assignee: command.user_id,
completed: false,
createdAt: new Date().toISOString(),
};
channelTasks.push(newTask);
tasks.set(channelId, channelTasks);
await respond({
blocks: [
{
type: 'section',
text: {
type: 'mrkdwn',
text: `タスクを追加しました: *${title}*`,
},
},
],
});
break;
}
case 'list': {
const channelTasks = tasks.get(channelId) || [];
if (channelTasks.length === 0) {
await respond('タスクはありません');
return;
}
const taskList = channelTasks
.map((t, i) => {
const status = t.completed ? '~' : '';
const check = t.completed ? ':white_check_mark:' : ':black_square_button:';
return `${check} ${status}${t.title}${status}`;
})
.join('\n');
await respond({
blocks: [
{
type: 'section',
text: { type: 'mrkdwn', text: `*タスク一覧*\n${taskList}` },
},
],
});
break;
}
default:
await respond('使い方: `/task add タスク名` | `/task list`');
}
});
}
모달の구현
> フィードバック전송用の모달를 구현해줘。
> 폼の입력검증も含めて。
// src/views/feedback-modal.ts
import { App } from '@slack/bolt';
export function registerFeedbackModal(app: App) {
// 모달を開くショートカット
app.shortcut('open_feedback', async ({ shortcut, ack, client }) => {
await ack();
await client.views.open({
trigger_id: shortcut.trigger_id,
view: {
type: 'modal',
callback_id: 'feedback_submission',
title: { type: 'plain_text', text: 'フィードバック' },
submit: { type: 'plain_text', text: '送信' },
blocks: [
{
type: 'input',
block_id: 'category_block',
label: { type: 'plain_text', text: 'カテゴリ' },
element: {
type: 'static_select',
action_id: 'category',
options: [
{ text: { type: 'plain_text', text: 'バグ報告' }, value: 'bug' },
{ text: { type: 'plain_text', text: '機能要望' }, value: 'feature' },
{ text: { type: 'plain_text', text: 'その他' }, value: 'other' },
],
},
},
{
type: 'input',
block_id: 'description_block',
label: { type: 'plain_text', text: '詳細' },
element: {
type: 'plain_text_input',
action_id: 'description',
multiline: true,
min_length: 10,
max_length: 1000,
},
},
{
type: 'input',
block_id: 'priority_block',
label: { type: 'plain_text', text: '優先度' },
element: {
type: 'radio_buttons',
action_id: 'priority',
options: [
{ text: { type: 'plain_text', text: '高' }, value: 'high' },
{ text: { type: 'plain_text', text: '中' }, value: 'medium' },
{ text: { type: 'plain_text', text: '低' }, value: 'low' },
],
},
},
],
},
});
});
// 모달전송の処理
app.view('feedback_submission', async ({ ack, view, client, body }) => {
await ack();
const values = view.state.values;
const category = values.category_block.category.selected_option?.value;
const description = values.description_block.description.value;
const priority = values.priority_block.priority.selected_option?.value;
// フィードバックチャンネルに게시
await client.chat.postMessage({
channel: process.env.FEEDBACK_CHANNEL_ID!,
blocks: [
{
type: 'section',
text: {
type: 'mrkdwn',
text: `*新しいフィードバック*\n*カテゴリ:* ${category}\n*優先度:* ${priority}\n*内容:* ${description}\n*投稿者:* <@${body.user.id}>`,
},
},
],
});
});
}
이벤트リスナー
// src/events/index.ts
import { App } from '@slack/bolt';
export function registerEvents(app: App) {
// メンション대응
app.event('app_mention', async ({ event, say }) => {
await say({
text: `<@${event.user}> お呼びですか? \`/task\` コマンドで何かお手伝いします!`,
thread_ts: event.ts,
});
});
// 新メンバー参加時
app.event('member_joined_channel', async ({ event, client }) => {
await client.chat.postMessage({
channel: event.channel,
text: `<@${event.user}> さん、ようこそ!チャンネルガイドを確認してくださいね。`,
});
});
}
정리
Slack BotのBolt SDKとClaude Codeを組み合わせれば、チーム業務の자동화ツールを빠르게구축할 수 있습니다。チャットボット개발가이드やWebhook구현도 참고하세요.
Slack Bolt SDK의 상세 정보는Bolt for JavaScript공식 문서를 참고하세요.
무료 PDF: 5분 완성 Claude Code 치트시트
이메일 주소만 등록하시면 A4 한 장짜리 치트시트 PDF를 즉시 보내드립니다.
개인정보는 엄격하게 관리하며 스팸은 보내지 않습니다.
이 글을 작성한 사람
Masa
Claude Code를 적극 활용하는 엔지니어. 10개 언어, 2,000페이지 이상의 테크 미디어 claudecode-lab.com을 운영 중.
관련 글
Claude Code 다국어 글을 매일 발행하기 전에 확인할 7가지
누락된 언어, 깨진 CTA, 반영되지 않은 배포를 막기 위해 다국어 Claude Code 글을 매일 발행하기 전에 확인할 체크리스트입니다.
Codex Automations란? 잠자는 동안 AI가 콘텐츠 운영을 처리하게 하는 방법
Codex Automations로 트래픽 분석, 주제 선정, 글 작성, CTA 개선, 배포까지 자동화하는 실전 가이드.
Claude Code × GCP Cloud Functions 완전 가이드 | 서버리스 함수 초고속 개발
Claude Code로 GCP Cloud Functions를 효율화. HTTP/Pub/Sub/Firestore 트리거 구현부터 로컬 테스트·배포 자동화까지, Masa의 실무 경험을 토대로 실제 코드로 해설.