디스코드 봇 만들기#20자동 환영 메시지·온보딩 만들기! 규칙 동의 버튼으로 자동 역할 부여 (파이썬 예제)
목차12개 항목
안녕하세요! Mojangcam입니다 😎
지난 #19편에서는 길어진 bot.py를 확장(Extension)과 Cog 구조로 쪼개고, !reload로 재시작 없이 코드를 다시 불러오는 것까지 만들었죠. 오늘부터가 진짜 재미있는 부분이에요. 그 구조 위에 기능 파일을 하나씩 얹어갑니다 🏗️
첫 번째 부품은 온보딩(Onboarding)이에요. 새 멤버가 서버에 들어오면 봇이 알아서 환영 카드를 띄우고, 규칙 동의 버튼을 누르면 자동으로 역할을 부여하는 기능입니다.
이번 편에서 배울 것
- 새 멤버 입장을 감지하는 on_member_join 이벤트
- 특권 인텐트(Privileged Intent) members 켜는 법
- 프로필 사진·가입일이 들어간 환영 카드 임베드 만들기
- 봇을 껐다 켜도 살아있는 영구 뷰(Persistent View) 버튼
- 버튼 클릭 → 역할 자동 부여 (add_roles)
- 떠날 때 남기는 이탈 메시지
서버 관리자분들이 봇에게 제일 먼저 시키고 싶어하는 기능이 바로 이거예요. 사람이 잘 때도 봇은 24시간 새 멤버를 맞아주니까요 🌙

🧠 왜 "버튼 동의" 방식으로 만들까요?
입장하자마자 역할을 그냥 줘버릴 수도 있어요. 그런데 실제로 서버를 굴려보면 이 방식이 훨씬 낫습니다.
- 자동 가입 봇(셀프봇) 차단 — 광고 봇은 버튼을 누르지 않아요. 입장만 하고 DM 광고를 뿌리고 나가죠. 버튼 한 단계가 있으면 대부분 걸러집니다
- 규칙을 읽었다는 기록 — 나중에 제재할 때 "동의 버튼 누르셨잖아요"가 됩니다
- 채널을 깔끔하게 — 동의 전에는 규칙 채널만 보이고, 동의 후에 나머지 채널이 열리게 만들 수 있어요
마지막 항목이 핵심이에요. @everyone 역할에서는 채널 보기 권한을 끄고, 동의하면 받는 역할에만 권한을 열어두면 자동 잠금 서버가 완성됩니다 🔒
📌 준비물
- Python 3.8+
- discord.py 2.x (2026년 8월 기준 최신 2.x 버전)
- python-dotenv — 토큰·ID를 코드에 박지 않기 위해 필수!
- #19편에서 만든 server-bot/ 폴더 (오늘 여기에 파일 하나를 추가해요)
pip install -U discord.py python-dotenv버전 확인은 이렇게 해요.
python -c "import discord; print(discord.__version__)".env 파일에는 이번 편에서 쓸 ID들을 추가합니다.
DISCORD_TOKEN=여기에_봇_토큰_붙여넣기
GUILD_ID=테스트용_서버_ID
WELCOME_CHANNEL_ID=환영_메시지_보낼_채널_ID
GOODBYE_CHANNEL_ID=이탈_메시지_보낼_채널_ID
MEMBER_ROLE_ID=동의하면_줄_역할_ID💡 채널·역할 ID는 디스코드 사용자 설정 → 고급 → 개발자 모드를 켜면 우클릭 → "ID 복사"로 얻을 수 있어요. 그리고 .env는 꼭 .gitignore에 넣으세요! 깃허브에 토큰이 올라가면 디스코드가 감지해서 바로 폐기해버립니다.
📌 1단계 - 특권 인텐트(members) 켜기
on_member_join은 그냥 켜지지 않아요. 멤버 정보는 개인정보라서 디스코드가 따로 잠가둔 특권 인텐트(Privileged Gateway Intents)거든요. 두 군데를 다 켜야 합니다.
① 개발자 포털에서 켜기
디스코드 개발자 포털 → 내 앱 → Bot → Privileged Gateway Intents → SERVER MEMBERS INTENT를 켜고 저장하세요.
② 코드에서 켜기 — #19편 bot.py에 이미 넣어뒀어요.
intents = discord.Intents.default()
intents.message_content = True
intents.members = True # ← 오늘 실제로 쓰는 인텐트!
intents.polls = True하나씩 뜯어볼게요 💡
- intents.members : 멤버 입장·퇴장·정보 변경 이벤트를 받게 해줘요. 이게 꺼져 있으면 on_member_join이 에러 없이 그냥 조용히 안 불립니다. 제일 헷갈리는 함정이에요 😵
- 포털 + 코드 둘 다 필요 : 하나만 켜면 안 돼요. 포털만 켜면 라이브러리가 요청을 안 하고, 코드만 켜면 디스코드가 로그인을 거부(PrivilegedIntentsRequired)합니다
- 참고 : 서버 100개가 넘어가면 이 인텐트는 디스코드 심사를 받아야 해요. 개인 서버 규모에서는 그냥 켜면 됩니다

📌 2단계 - 환영 카드 임베드 만들기
새 멤버가 들어오면 보낼 카드를 먼저 만들어볼게요. 그냥 "환영합니다" 한 줄보다 임베드가 훨씬 예쁘죠 🎨
def build_welcome_embed(self, member: discord.Member) -> discord.Embed:
embed = discord.Embed(
title=f"{member.display_name}님, 환영해요! 🎉",
description=(
f"{member.mention} 님이 서버에 들어왔어요.\n"
"규칙 채널에서 **동의 버튼**을 누르면 바로 활동할 수 있어요!"
),
color=discord.Color.from_str("#5865F2"),
timestamp=discord.utils.utcnow(),
)
embed.set_thumbnail(url=member.display_avatar.url)
embed.add_field(
name="계정 생성일",
value=discord.utils.format_dt(member.created_at, "D"),
inline=True,
)
embed.add_field(name="지금 멤버 수", value=f"{member.guild.member_count}명", inline=True)
embed.set_footer(text=f"ID: {member.id}")
return embed하나씩 뜯어볼게요 💡
- member.display_avatar : 프로필 사진이에요. avatar가 아니라 display_avatar를 쓰세요. 프사를 안 넣은 유저는 avatar가 None이라 에러가 나는데, display_avatar는 기본 아바타를 대신 돌려줍니다
- discord.utils.format_dt(날짜, "D") : 디스코드가 보는 사람의 시간대로 자동 변환해주는 타임스탬프예요. 서식 문자는 t(시각) D(날짜) F(전체) R(상대시간, "3일 전") 이 있어요
- member.created_at : 계정을 만든 날이에요. 서버에 들어온 날(joined_at)이 아닙니다. 계정 생성 며칠 안 된 유저는 스팸 계정일 확률이 높아서 관리자에게 유용한 정보예요 🕵️
- discord.Color.from_str("#5865F2") : 디스코드 브랜드 색(블러플)이에요. discord.Color.blurple()로도 쓸 수 있어요
- member.mention : @닉네임 형태로 실제 멘션돼요. title에는 멘션이 안 먹히니까 description에 넣어야 알림이 갑니다
📌 3단계 - 입장·퇴장 이벤트 받기
이제 이벤트 리스너를 붙일 차례예요. Cog 안이니까 @commands.Cog.listener()를 씁니다 (#19편에서 배웠죠!).
@commands.Cog.listener()
async def on_member_join(self, member: discord.Member):
if member.bot:
return
channel = member.guild.get_channel(WELCOME_CHANNEL_ID) or member.guild.system_channel
if channel is None:
print("[Onboarding] 환영 채널을 못 찾았어요!")
return
await channel.send(embed=self.build_welcome_embed(member))
@commands.Cog.listener()
async def on_member_remove(self, member: discord.Member):
if member.bot:
return
channel = member.guild.get_channel(GOODBYE_CHANNEL_ID) or member.guild.system_channel
if channel is None:
return
await channel.send(
f"👋 **{member.display_name}** 님이 서버를 떠났어요. "
f"(남은 인원 {member.guild.member_count}명)"
)하나씩 뜯어볼게요 💡
- if member.bot: return : 다른 봇을 초대했을 때 환영 카드가 뜨는 걸 막아요. 있어야 자연스러워요
- or member.guild.system_channel : .env에 채널 ID를 안 넣었거나 채널이 삭제됐을 때를 대비한 보험이에요. 서버 설정의 "시스템 메시지 채널"로 대신 보냅니다
- on_member_remove : 자발적 퇴장·킥·밴을 전부 여기서 받아요. 셋을 구분하고 싶다면 on_member_ban을 따로 쓰거나 감사 로그(Audit Log)를 봐야 하는데, 그건 #24 로그 편에서 다룰게요
- member_count : 이벤트가 처리되는 시점 기준이라 입장 직후엔 이미 +1 된 값이에요
📌 4단계 - 규칙 동의 버튼 만들기 (영구 뷰!)
오늘의 하이라이트예요. discord.ui.View로 만든 버튼은 기본적으로 180초 뒤에 죽어요. 봇을 재시작하면 그냥 먹통이 되고요. 규칙 패널은 몇 달씩 채널에 붙어 있어야 하는데 이러면 곤란하죠 😅
그래서 영구 뷰(Persistent View)로 만듭니다. 조건은 딱 세 가지예요.
- timeout=None
- 모든 버튼·선택지에 custom_id 지정
- 봇 시작 시 bot.add_view(...)로 다시 등록
class RuleAgreeView(discord.ui.View):
"""규칙 동의 버튼 패널 (영구 뷰)"""
def __init__(self):
super().__init__(timeout=None) # ① 시간 제한 없음
@discord.ui.button(
label="규칙에 동의합니다",
style=discord.ButtonStyle.success,
emoji="✅",
custom_id="onboarding:agree", # ② 고정 ID
)
async def agree(self, interaction: discord.Interaction, button: discord.ui.Button):
role = interaction.guild.get_role(MEMBER_ROLE_ID)
if role is None:
await interaction.response.send_message(
"역할 설정이 잘못됐어요. 관리자에게 알려주세요 🙏", ephemeral=True
)
return
if role in interaction.user.roles:
await interaction.response.send_message("이미 동의하셨어요! 😊", ephemeral=True)
return
try:
await interaction.user.add_roles(role, reason="규칙 동의 버튼 클릭")
except discord.Forbidden:
await interaction.response.send_message(
"권한이 부족해서 역할을 드리지 못했어요 😢", ephemeral=True
)
return
await interaction.response.send_message(
f"환영해요! **{role.name}** 역할을 드렸어요 🎉", ephemeral=True
)그리고 Cog가 올라올 때 뷰를 다시 등록해요.
async def cog_load(self):
self.bot.add_view(RuleAgreeView()) # ③ 재등록
print("[Onboarding] 규칙 동의 패널 등록 완료!")하나씩 뜯어볼게요 💡
- timeout=None : 이걸 안 넣으면 3분 뒤 버튼이 회색으로 죽어요. 영구 뷰의 1번 조건입니다
- custom_id="onboarding:agree" : 봇이 재시작한 뒤 "아, 이 버튼은 내 담당이구나"를 알아보는 이름표예요. 안 주면 discord.py가 매번 랜덤 ID를 붙여서 재시작 후 매칭이 안 됩니다. 콜론(:)으로 구분해두면 나중에 기능이 늘어도 안 헷갈려요
- bot.add_view(...) : 봇이 켜질 때마다 "이 버튼들 내가 처리할게" 하고 등록하는 절차예요. cog_load나 setup_hook에서 해주면 됩니다. 이걸 빼먹으면 재시작 후 버튼이 "상호작용 실패"만 뱉어요 ❌
- ephemeral=True : 나만 보이는 답장이에요. 100명이 버튼을 눌러도 채널이 도배되지 않아요
- add_roles(role, reason=...) : reason은 서버 감사 로그에 남습니다. 나중에 "이 역할 누가 줬지?" 할 때 유용해요
- role in interaction.user.roles : 이미 가진 사람이 또 눌렀을 때 처리예요. 없어도 동작은 하지만 API 호출이 낭비돼요
⚠️ 역할 순서 함정! 봇은 자기 역할보다 아래에 있는 역할만 부여할 수 있어요. 서버 설정 → 역할에서 봇 역할을 위로 끌어올려두세요. 이걸 놓쳐서 Forbidden 에러 나는 경우가 정말 많아요 😅
📌 전체 코드 (복붙 OK)
1) cogs/onboarding.py
# discord.py 2.x / Python 3.8+
# 디스코드 봇 만들기 #20 - 자동 환영 메시지·온보딩
import os
import discord
from discord import app_commands
from discord.ext import commands
from dotenv import load_dotenv
load_dotenv()
WELCOME_CHANNEL_ID = int(os.getenv("WELCOME_CHANNEL_ID", "0"))
GOODBYE_CHANNEL_ID = int(os.getenv("GOODBYE_CHANNEL_ID", "0"))
MEMBER_ROLE_ID = int(os.getenv("MEMBER_ROLE_ID", "0"))
BRAND_COLOR = discord.Color.from_str("#5865F2")
RULES_TEXT = (
"**1.** 서로 존중해주세요. 욕설·비방은 즉시 제재돼요\n"
"**2.** 광고·도배·스팸 링크 금지\n"
"**3.** 채널 주제에 맞게 대화해주세요\n"
"**4.** 디스코드 이용약관을 지켜주세요\n\n"
"다 읽으셨다면 아래 버튼을 눌러주세요! 👇"
)
class RuleAgreeView(discord.ui.View):
"""규칙 동의 버튼 패널 (영구 뷰)"""
def __init__(self):
super().__init__(timeout=None)
@discord.ui.button(
label="규칙에 동의합니다",
style=discord.ButtonStyle.success,
emoji="✅",
custom_id="onboarding:agree",
)
async def agree(self, interaction: discord.Interaction, button: discord.ui.Button):
role = interaction.guild.get_role(MEMBER_ROLE_ID)
if role is None:
await interaction.response.send_message(
"역할 설정이 잘못됐어요. 관리자에게 알려주세요 🙏", ephemeral=True
)
return
if role in interaction.user.roles:
await interaction.response.send_message("이미 동의하셨어요! 😊", ephemeral=True)
return
try:
await interaction.user.add_roles(role, reason="규칙 동의 버튼 클릭")
except discord.Forbidden:
await interaction.response.send_message(
"권한이 부족해서 역할을 드리지 못했어요 😢 (봇 역할 순서를 확인해주세요)",
ephemeral=True,
)
return
await interaction.response.send_message(
f"환영해요! **{role.name}** 역할을 드렸어요 🎉", ephemeral=True
)
class Onboarding(commands.Cog):
"""새 멤버 환영·자동 역할 부여"""
def __init__(self, bot: commands.Bot):
self.bot = bot
async def cog_load(self):
self.bot.add_view(RuleAgreeView())
print("[Onboarding] 규칙 동의 패널 등록 완료!")
def build_welcome_embed(self, member: discord.Member) -> discord.Embed:
embed = discord.Embed(
title=f"{member.display_name}님, 환영해요! 🎉",
description=(
f"{member.mention} 님이 서버에 들어왔어요.\n"
"규칙 채널에서 **동의 버튼**을 누르면 바로 활동할 수 있어요!"
),
color=BRAND_COLOR,
timestamp=discord.utils.utcnow(),
)
embed.set_thumbnail(url=member.display_avatar.url)
embed.add_field(
name="계정 생성일",
value=discord.utils.format_dt(member.created_at, "D"),
inline=True,
)
embed.add_field(
name="지금 멤버 수", value=f"{member.guild.member_count}명", inline=True
)
embed.set_footer(text=f"ID: {member.id}")
return embed
def pick_channel(self, guild: discord.Guild, channel_id: int):
return guild.get_channel(channel_id) or guild.system_channel
@commands.Cog.listener()
async def on_member_join(self, member: discord.Member):
if member.bot:
return
channel = self.pick_channel(member.guild, WELCOME_CHANNEL_ID)
if channel is None:
print("[Onboarding] 환영 채널을 못 찾았어요!")
return
await channel.send(embed=self.build_welcome_embed(member))
@commands.Cog.listener()
async def on_member_remove(self, member: discord.Member):
if member.bot:
return
channel = self.pick_channel(member.guild, GOODBYE_CHANNEL_ID)
if channel is None:
return
await channel.send(
f"👋 **{member.display_name}** 님이 서버를 떠났어요. "
f"(남은 인원 {member.guild.member_count}명)"
)
@app_commands.command(name="규칙패널", description="규칙 동의 버튼 패널을 이 채널에 설치해요")
@app_commands.checks.has_permissions(manage_guild=True)
async def setup_panel(self, interaction: discord.Interaction):
embed = discord.Embed(
title="📜 서버 규칙",
description=RULES_TEXT,
color=BRAND_COLOR,
)
await interaction.channel.send(embed=embed, view=RuleAgreeView())
await interaction.response.send_message("규칙 패널을 설치했어요! ✅", ephemeral=True)
@setup_panel.error
async def setup_panel_error(self, interaction: discord.Interaction, error):
if isinstance(error, app_commands.MissingPermissions):
await interaction.response.send_message(
"이 명령어는 **서버 관리** 권한이 있어야 쓸 수 있어요 🔒", ephemeral=True
)
async def setup(bot: commands.Bot):
await bot.add_cog(Onboarding(bot))2) bot.py는 손댈 게 없어요!
#19편에서 만든 bot.py는 cogs/ 폴더의 .py 파일을 전부 자동으로 불러오게 짜뒀죠. 그래서 오늘은 파일만 넣으면 끝이에요 😎
server-bot/
├─ .env
├─ .gitignore
├─ bot.py
└─ cogs/
├─ admin.py
├─ poll.py # #18 투표
└─ onboarding.py # ← 오늘 추가!intents.members = True도 #19편에서 이미 넣어뒀으니 그대로 두시면 됩니다.
📌 실행 결과
python bot.py로 실행하면 터미널에 이렇게 찍혀요.
[Onboarding] 규칙 동의 패널 등록 완료!
[Poll] 준비 완료!
✅ cogs.admin 불러옴
✅ cogs.onboarding 불러옴
✅ cogs.poll 불러옴
MojangBot#1234 로그인 성공! (Cog 3개)먼저 규칙 채널에서 !sync를 한 번 실행해 슬래시 명령어를 동기화한 뒤, /규칙패널을 쳐보세요. 규칙 임베드와 초록색 동의 버튼이 설치됩니다.

버튼을 누르면 나만 보이는 답장과 함께 역할이 붙어요.
환영해요! 멤버 역할을 드렸어요 🎉그리고 다른 계정으로 서버에 들어가보면 환영 채널에 카드가 뜹니다.
마지막으로 봇을 껐다가 다시 켠 뒤 아까 그 버튼을 눌러보세요. 그대로 동작하면 영구 뷰가 제대로 등록된 거예요 👏
📌 자주 나는 에러
1. on_member_join이 아예 안 불려요 (에러도 없음)
- 원인 : members 인텐트가 꺼져 있어요. 가장 흔한 케이스입니다
- 해결 : 코드의 intents.members = True 그리고 개발자 포털 → Bot → SERVER MEMBERS INTENT를 둘 다 켜세요. 포털에서 켠 뒤에는 봇을 재시작해야 반영돼요
2. discord.errors.PrivilegedIntentsRequired
- 원인 : 코드에서는 특권 인텐트를 요청했는데 포털에서 안 켰어요
- 해결 : 개발자 포털에서 해당 인텐트를 켜고 저장하세요. 1번과 짝꿍인 에러예요
3. discord.errors.Forbidden: 403 Forbidden (error code: 50013): Missing Permissions
- 원인 : ① 봇에게 역할 관리(Manage Roles) 권한이 없거나 ② 주려는 역할이 봇 역할보다 위에 있어요
- 해결 : 서버 설정 → 역할에서 봇 역할에 "역할 관리" 권한을 주고, 봇 역할을 멤버 역할보다 위로 드래그하세요
4. 봇 재시작 후 버튼을 누르면 "이 상호작용에 실패했습니다"
- 원인 : 영구 뷰를 다시 등록하지 않았어요
- 해결 : cog_load(또는 setup_hook)에서 bot.add_view(RuleAgreeView())를 호출하세요. timeout=None과 custom_id도 같이 확인하고요. 셋 중 하나라도 빠지면 안 됩니다
5. /규칙패널 명령어가 목록에 안 보여요
- 원인 : 슬래시 명령어가 디스코드에 동기화되지 않았어요
- 해결 : #19편에서 만든 !sync를 한 번 실행하세요. 전역 동기화는 반영이 느릴 수 있어서 테스트 서버 동기화가 빠릅니다
6. AttributeError: 'NoneType' object has no attribute 'url'
- 원인 : member.avatar.url을 썼는데 프로필 사진을 설정하지 않은 유저였어요
- 해결 : member.display_avatar.url로 바꾸세요. 기본 아바타를 대신 돌려줍니다
7. 환영 메시지가 아무 데도 안 떠요
- 원인 : .env의 WELCOME_CHANNEL_ID가 비었거나 오타예요. int("")가 안 되도록 기본값 "0"을 넣어뒀는데, 0은 존재하지 않는 채널이라 조용히 넘어갑니다
- 해결 : 개발자 모드를 켜고 채널 우클릭 → "ID 복사"로 다시 넣으세요. 서버 설정에 시스템 메시지 채널이 지정돼 있으면 그쪽으로 대체 발송됩니다
8. 봇이 들어와도 환영 카드가 안 떠요
- 원인 : 에러가 아니라 의도된 동작이에요. if member.bot: return 때문입니다
- 해결 : 봇도 환영하고 싶다면 그 두 줄을 지우면 돼요 🙂
📌 마무리
오늘은 #19편에서 잡은 구조 위에 첫 기능 파일 cogs/onboarding.py를 올려봤어요 🙌
오늘의 요약
- on_member_join을 쓰려면 members 특권 인텐트를 코드·포털 양쪽에서 켜기
- 환영 카드는 display_avatar + format_dt 조합이 예쁘고 안전해요
- 영구 뷰 3종 세트 : timeout=None + custom_id + bot.add_view()
- 역할 부여는 add_roles(role, reason=...), 봇 역할이 위에 있어야 해요
- 채널을 못 찾으면 system_channel로 대체하는 보험 넣기
다음 #21편에서는 키워드 자동응답과 금지어 필터를 만듭니다. on_message로 채팅을 읽어서 특정 단어에 자동으로 답하고, 광고·욕설은 자동 삭제하고 경고를 누적하는 cogs/automod.py예요. 봇이 스스로 무한루프에 빠지는 걸 막는 법도 같이 짚을게요. 기대해주세요! 🙌
💬 오늘 만든 onboarding.py는 #27 최종 프로젝트 "커뮤니티 통합 관리 봇"의 신규 유저 온보딩 모듈이 됩니다. 폴더째 잘 보관해두세요!
📚 디스코드 봇 만들기 시리즈
- #1 ~ #16 — 봇 만들기 기초부터 리마인더·알림까지
- #17 RAG로 문서 기반 답변봇 만들기
- #18 투표(Poll) 기능 만들기
- #19 Cog로 코드 쪼개기
- #20 자동 환영 메시지·온보딩 ← 지금 이 글!
- #21 키워드 자동응답·금지어 필터 (예정)
연재 · 32편 중 20번째
디스코드 봇 만들기
- #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임시 음성방 확장, 파티방 만들기! 방장 위임·강퇴·초대 전용(비공개) 방 + 전용 채팅방 자동 생성 (파이썬 예제) 🎉
