디스코드 봇 만들기#5버튼(Button) 상호작용 구현하기!
목차8개 항목
안녕하세요! Mojangcam입니다 😎
지난 #4편에서는 Slash Command로 임베드를 전송해봤죠? 이번에는 한 단계 더 나아가서, 메시지에 클릭할 수 있는 버튼(Button) 을 달아보겠습니다! 버튼을 누르면 봇이 반응하는, 진짜 "상호작용하는 봇"을 만들어봅시다.
완성되면 이런 것들이 가능해집니다:
- ✅ 확인 / ❌ 취소 버튼으로 유저에게 선택지 주기
- 🎫 티켓 생성, 역할 지급 같은 원클릭 기능
- 버튼을 누른 사람에게만 보이는 답장 보내기
📌 준비물
- Python 3.8 이상
- discord.py 2.x (버튼 기능은 2.0부터 지원됩니다!)
- 봇 토큰 + 서버에 봇 초대 완료 (1편 참고!)
pip install -U discord.py버전이 낮다면 꼭 업데이트해주세요. 버전 확인은 pip show discord.py 로 할 수 있습니다.
📌 1단계 - 버튼의 핵심, View 이해하기
discord.py에서 버튼은 단독으로 못 쓰고, View라는 컨테이너에 담아서 메시지와 함께 보냅니다.
discord.ui.View→ 버튼, 드롭다운 등을 담는 상자 📦discord.ui.button데코레이터 → View 안에 버튼을 만들고, 눌렀을 때 실행할 함수를 연결
구조만 먼저 볼게요!
import discord
class MyView(discord.ui.View):
@discord.ui.button(label="눌러봐!", style=discord.ButtonStyle.primary)
async def my_button(self, interaction: discord.Interaction, button: discord.ui.Button):
await interaction.response.send_message("버튼이 눌렸어요!")⚠️ 콜백 함수의 매개변수 순서는 (self, interaction, button) 입니다. 다른 라이브러리(pycord 등) 예제와 순서가 반대라서 헷갈리기 쉬우니 주의하세요!
📌 2단계 - 버튼 스타일 알아보기
style= 에 넣을 수 있는 버튼 색상은 5가지입니다.
| 스타일 | 색상 | 용도 예시 |
|---|---|---|
ButtonStyle.primary |
파란색 | 메인 동작 |
ButtonStyle.secondary |
회색 | 보조 동작 |
ButtonStyle.success |
초록색 | 확인/수락 |
ButtonStyle.danger |
빨간색 | 삭제/거절 |
ButtonStyle.link |
링크형 | URL 이동 (url= 필요, 콜백 없음) |
📌 3단계 - 확인/취소 버튼 만들기
실전에서 제일 많이 쓰는 확인/취소 패턴을 만들어보겠습니다.
class ConfirmView(discord.ui.View):
def __init__(self):
super().__init__(timeout=60) # 60초 뒤 버튼 비활성화
@discord.ui.button(label="확인", style=discord.ButtonStyle.success)
async def confirm(self, interaction: discord.Interaction, button: discord.ui.Button):
await interaction.response.edit_message(content="✅ 확인되었습니다!", view=None)
@discord.ui.button(label="취소", style=discord.ButtonStyle.danger)
async def cancel(self, interaction: discord.Interaction, button: discord.ui.Button):
await interaction.response.edit_message(content="❌ 취소되었습니다.", view=None)포인트 정리 💡
timeout=60: 60초가 지나면 버튼이 더 이상 동작하지 않습니다 (기본값은 180초)edit_message(..., view=None): 버튼을 누르면 원본 메시지를 수정하면서 버튼을 제거interaction.response는 3초 안에 딱 1번만 응답할 수 있습니다. 추가로 보내려면interaction.followup.send()를 사용하세요!
📌 4단계 - 전체 코드 (복붙 OK)
Slash Command와 합친 완성본입니다.
import discord
from discord.ext import commands
intents = discord.Intents.default()
bot = commands.Bot(command_prefix="/", intents=intents)
class ConfirmView(discord.ui.View):
def __init__(self):
super().__init__(timeout=60)
@discord.ui.button(label="확인", style=discord.ButtonStyle.success)
async def confirm(self, interaction: discord.Interaction, button: discord.ui.Button):
await interaction.response.edit_message(content="✅ 확인되었습니다!", view=None)
@discord.ui.button(label="취소", style=discord.ButtonStyle.danger)
async def cancel(self, interaction: discord.Interaction, button: discord.ui.Button):
await interaction.response.edit_message(content="❌ 취소되었습니다.", view=None)
@bot.event
async def on_ready():
await bot.tree.sync()
print(f"{bot.user} 봇이 준비되었습니다!")
@bot.tree.command(name="확인", description="확인/취소 버튼을 보냅니다")
async def confirm_command(interaction: discord.Interaction):
await interaction.response.send_message("진행할까요?", view=ConfirmView())
bot.run("Token")📌 결과 확인하기
봇을 실행하고 디스코드 채널에서 /확인 을 입력하면 "진행할까요?" 메시지와 함께 초록색 확인, 빨간색 취소 버튼이 나타납니다! 버튼을 누르면 메시지가 "✅ 확인되었습니다!" 로 바뀌면서 버튼이 사라져요.
📌 자주 나는 에러
1. 버튼을 눌렀는데 "상호작용 실패"라고 떠요
콜백에서 3초 안에 응답하지 않았을 때 발생합니다. 처리에 시간이 걸린다면 await interaction.response.defer() 를 먼저 호출해주세요.
2. TypeError: ... missing 1 required positional argument
콜백 매개변수 순서 문제입니다! discord.py 2.x는 (self, interaction, button) 순서예요. (self, button, interaction) 으로 쓰면 이 에러가 납니다.
3. 봇을 재시작하면 이전 메시지의 버튼이 안 눌러져요
View는 기본적으로 메모리에만 존재합니다. 재시작 후에도 동작하게 하려면 timeout=None + custom_id 를 지정한 persistent view를 만들고 bot.add_view() 로 등록해야 해요. (이건 나중에 심화편에서 다룰게요!)
📌 마무리
오늘은 discord.py의 View와 버튼으로 클릭 상호작용을 구현해봤습니다.
- 버튼은 View에 담아서 전송
- 스타일 5종 (primary/secondary/success/danger/link)
- 응답은 3초 안에, 1번만!
다음 편에서는 드롭다운(Select Menu) 메뉴를 만들어볼 예정이에요. 기대해주세요 🙌
📚 디스코드 봇 만들기 시리즈
- Slash Command 완전 정복
- Slash Command에 옵션(Arguments) 추가하기
- Slash Command에 서브 커맨드 넣기
- Slash Command로 임베드 전송하기
- 버튼(Button) 상호작용 구현하기 ← 지금 이 글!
연재 · 32편 중 5번째
디스코드 봇 만들기
- #1디스코드 봇 만들기 - Slash Command 완전 정복!
- #2Slash Command에 옵션(Arguments) 추가하기!
- #3Slash Command에 서브 커맨드(Subcommand) 넣기!
- #4Slash Command로 임베드 전송하기!
- #5버튼(Button) 상호작용 구현하기!지금 읽는 글
- #6드롭다운(Select Menu) 메뉴 구현하기!
- #7모달(Modal)로 입력 받기 구현하기 (파이썬 예제)
- #8임베드(Embed) 이미지·필드로 꾸미기 (파이썬 예제)
- #9AI(Claude·ChatGPT API) 연동하기! (파이썬 예제)
- #10다국어(i18n) 지원하기! (파이썬 예제)
- #11플라스크(Flask)로 웹 대시보드 만들기! (파이썬 예제)
- #12명령어 쿨다운(Cooldown)·권한(Permission) 관리하기! (파이썬 예제)
- #13역할·채널 자동화로 서버 관리하기! (파이썬 예제)
- #14데이터 저장하기! JSON vs SQLite (파이썬 예제)
- #15슬래시 명령어 그룹(Group)으로 명령어 정리하기! (파이썬 예제)
- #16리마인더·알림 기능 만들기! 봇이 먼저 말 걸게 하기 (파이썬 예제)
- #17RAG로 문서 기반 답변봇 만들기! 우리 서버 전용 FAQ 봇 (파이썬 예제)
- #18투표(Poll) 기능 만들기! 다수결로 정하는 서버 규칙 (파이썬 예제)
- #19Cog로 코드 쪼개기! 1000줄 봇도 안 더러워지는 구조 (파이썬 예제)
- #20자동 환영 메시지·온보딩 만들기! 규칙 동의 버튼으로 자동 역할 부여 (파이썬 예제)
- #21키워드 자동응답·금지어 필터 만들기! 경고 누적으로 자동 제재까지 (파이썬 예제)
- #22슬래시 명령어 자동완성(Autocomplete) 만들기! 금지어를 골라서 추가·삭제 (파이썬 예제)
- #23aiosqlite로 비동기 DB 제대로 설계하기! JSON 탈출 (파이썬 예제)
- #24채널 난독화(Channel Obfuscation) 대응하기! 11/16부터 안 보이는 채널이 생겨요 (파이썬 예제)
- #25봇이 죽지 않게! 에러 핸들링·로깅 체계 잡기 (파이썬 예제)
- #26티켓(Ticket) 문의 시스템 만들기! 버튼 하나로 1:1 상담 채널 자동 생성 (파이썬 예제)
- #27티켓 담당자 배정·우선순위 만들기! 스태프가 여러 명이어도 안 꼬이게 (파이썬 예제)
- #28레벨·경험치(XP) 시스템 만들기! 채팅할수록 레벨업, 랭킹판까지 (파이썬 예제)
- #29화폐·상점(Economy) 시스템 만들기! 코인 벌어서 아이템 사기 (파이썬 예제)
- #30투표·설문(Poll) 봇 만들기! 네이티브 투표 + 버튼으로 실시간 집계까지 (파이썬 예제) 🗳️
- #32서버 로그·감사(Audit Log) 채널 만들기! 메시지 삭제·수정·입퇴장·추방까지 자동 기록 (파이썬 예제) 🕵️
- #33임시 음성방 확장, 파티방 만들기! 방장 위임·강퇴·초대 전용(비공개) 방 + 전용 채팅방 자동 생성 (파이썬 예제) 🎉
