카테고리: 디스코드 봇 만들기

디스코드 봇 만들기#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 안에 버튼을 만들고, 눌렀을 때 실행할 함수를 연결

구조만 먼저 볼게요!

Python
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단계 - 확인/취소 버튼 만들기

실전에서 제일 많이 쓰는 확인/취소 패턴을 만들어보겠습니다.

Python
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와 합친 완성본입니다.

Python
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) 메뉴를 만들어볼 예정이에요. 기대해주세요 🙌

📚 디스코드 봇 만들기 시리즈

  1. Slash Command 완전 정복
  2. Slash Command에 옵션(Arguments) 추가하기
  3. Slash Command에 서브 커맨드 넣기
  4. Slash Command로 임베드 전송하기
  5. 버튼(Button) 상호작용 구현하기 ← 지금 이 글!

연재 · 32편 중 5번째

디스코드 봇 만들기

  1. #1디스코드 봇 만들기 - Slash Command 완전 정복!
  2. #2Slash Command에 옵션(Arguments) 추가하기!
  3. #3Slash Command에 서브 커맨드(Subcommand) 넣기!
  4. #4Slash Command로 임베드 전송하기!
  5. #5버튼(Button) 상호작용 구현하기!지금 읽는 글
  6. #6드롭다운(Select Menu) 메뉴 구현하기!
  7. #7모달(Modal)로 입력 받기 구현하기 (파이썬 예제)
  8. #8임베드(Embed) 이미지·필드로 꾸미기 (파이썬 예제)
  9. #9AI(Claude·ChatGPT API) 연동하기! (파이썬 예제)
  10. #10다국어(i18n) 지원하기! (파이썬 예제)
  11. #11플라스크(Flask)로 웹 대시보드 만들기! (파이썬 예제)
  12. #12명령어 쿨다운(Cooldown)·권한(Permission) 관리하기! (파이썬 예제)
  13. #13역할·채널 자동화로 서버 관리하기! (파이썬 예제)
  14. #14데이터 저장하기! JSON vs SQLite (파이썬 예제)
  15. #15슬래시 명령어 그룹(Group)으로 명령어 정리하기! (파이썬 예제)
  16. #16리마인더·알림 기능 만들기! 봇이 먼저 말 걸게 하기 (파이썬 예제)
  17. #17RAG로 문서 기반 답변봇 만들기! 우리 서버 전용 FAQ 봇 (파이썬 예제)
  18. #18투표(Poll) 기능 만들기! 다수결로 정하는 서버 규칙 (파이썬 예제)
  19. #19Cog로 코드 쪼개기! 1000줄 봇도 안 더러워지는 구조 (파이썬 예제)
  20. #20자동 환영 메시지·온보딩 만들기! 규칙 동의 버튼으로 자동 역할 부여 (파이썬 예제)
  21. #21키워드 자동응답·금지어 필터 만들기! 경고 누적으로 자동 제재까지 (파이썬 예제)
  22. #22슬래시 명령어 자동완성(Autocomplete) 만들기! 금지어를 골라서 추가·삭제 (파이썬 예제)
  23. #23aiosqlite로 비동기 DB 제대로 설계하기! JSON 탈출 (파이썬 예제)
  24. #24채널 난독화(Channel Obfuscation) 대응하기! 11/16부터 안 보이는 채널이 생겨요 (파이썬 예제)
  25. #25봇이 죽지 않게! 에러 핸들링·로깅 체계 잡기 (파이썬 예제)
  26. #26티켓(Ticket) 문의 시스템 만들기! 버튼 하나로 1:1 상담 채널 자동 생성 (파이썬 예제)
  27. #27티켓 담당자 배정·우선순위 만들기! 스태프가 여러 명이어도 안 꼬이게 (파이썬 예제)
  28. #28레벨·경험치(XP) 시스템 만들기! 채팅할수록 레벨업, 랭킹판까지 (파이썬 예제)
  29. #29화폐·상점(Economy) 시스템 만들기! 코인 벌어서 아이템 사기 (파이썬 예제)
  30. #30투표·설문(Poll) 봇 만들기! 네이티브 투표 + 버튼으로 실시간 집계까지 (파이썬 예제) 🗳️
  31. #32서버 로그·감사(Audit Log) 채널 만들기! 메시지 삭제·수정·입퇴장·추방까지 자동 기록 (파이썬 예제) 🕵️
  32. #33임시 음성방 확장, 파티방 만들기! 방장 위임·강퇴·초대 전용(비공개) 방 + 전용 채팅방 자동 생성 (파이썬 예제) 🎉
전체 32편 보기접기

글쓴이

Mojangcam

직접 코드를 짜고, 서버를 돌리고, 막힌 에러를 해결하며 배운 것들을 기록하는 개발·IT 실전 기록 블로그