임베드와 버튼을 같이 쓰다가 메시지가 '답장 형태'로 표시되어 깔끔하지 않게 보일 때 해결한 방법을 정리했다. 버튼은 임베드 내부 요소가 아니라 메시지 컴포넌트라는 점과, 임시 응답(또는 reply)을 만들면서 생기는 부작용을 피하는 방식으로 처리한다.
증상
임베드와 버튼을 함께 띄우면 의도치 않게 "답장처럼 보이는" 추가 표시가 생긴다. 규칙 같은 임베드를 만들었는데, 본문은 정상인데 위쪽에 원치 않는 답글 표시나 임시 메시지가 같이 붙는다.
원인
버튼은 임베드(Embed) 내부에 들어가는 요소가 아니다. 버튼은 메시지 컴포넌트(Message Component)로 메시지 레벨에서 처리된다.
대개 다음 두 가지 이유로 답장 형태가 발생한다.
- 명시적으로
replyAPI(또는 라이브러리의message.reply()등)를 사용해 메시지에 참조를 남긴 경우. 이 경우 Discord가 “누구에게 답장” 형태로 표시함. - 인터랙션 처리 과정에서 임시 응답(예: 바로 메시지를 보내기 전에 만든 placeholder 메시지)을 남기고, 그 메시스가 그대로 보이는 경우. 이럴 때 임시 메시지를 삭제하지 않거나 수정하지 않으면 원치 않는 흔적이 남는다.
또한 일부 고급 구현(예: 컴포넌트 v2를 직접 호출하는 경우)은 저수준 API 호출로 구현해야 해서, 초기에 임시 메시지를 띄우는 방식으로 우회하면서 이런 흔적이 생기기도 한다.
해결 방법
1단계: 버튼은 임베드가 아니라 컴포넌트로 취급하기
버튼을 임베드 안에 직접 넣을 수 없고, components(액션 로우 + 버튼)로 메시지와 함께 전송해야 한다. 컴포넌트 버전(예: 컴포넌트 v2)을 사용해야 할 경우 낮은 레벨의 API 요청이 필요할 수 있다.
2단계: reply 대신 채널 메시지 전송 또는 편집 사용
답장형 표시를 없애려면 다음 중 하나를 선택한다.
reply()대신channel.send()사용: 참조(reply)로 보내지 않으므로 답장 헤더가 붙지 않는다.- 인터랙션을 사용한다면
defer()(또는deferReply())로 응답을 지연하고, 이후에 원래 응답을 편집(editReply())하거나 일반 채널에send()로 메시지를 보낸다. 임시 메시지를 삭제하는 방법도 가능하지만, 편집해서 하나의 메시지로 관리하면 깔끔하다.
아래는 discord.js(예시)에서 안전하게 처리하는 패턴이다.
// discord.js 예시
const { ActionRowBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder } = require('discord.js');
await interaction.deferReply(); // 응답 지연 (버퍼 확보)
const embed = new EmbedBuilder()
.setTitle('규칙')
.setDescription('서버 규칙을 여기에 적습니다.')
.setColor('#2f3136');
const buttons = new ActionRowBuilder().addComponents(
new ButtonBuilder().setCustomId('accept').setLabel('동의').setStyle(ButtonStyle.Primary),
new ButtonBuilder().setCustomId('close').setLabel('닫기').setStyle(ButtonStyle.Secondary)
);
// 편집해서 하나의 메시지로 마무리 (reply 형태 흔적 없음)
await interaction.editReply({ embeds: [embed], components: [buttons], fetchReply: false });
또는 interaction 객체 대신 채널에 바로 보낼 때:
// channel.send를 사용하면 reply 헤더 없음
await interaction.deferReply({ fetchReply: false });
await interaction.channel.send({ embeds: [embed], components: [buttons] });
3단계: 임시 메시지 삭제 또는 메시지 수정
이미 임시로 올라간 메시지가 있다면 그 메시지를 삭제하거나, 그 메시지를 수정해서 최종 임베드 + 버튼을 넣어두면 UI가 깔끔해진다. 메시지를 삭제하는 코드는 사용하는 라이브러리에 맞춰 실행하면 된다.
마무리
임베드와 버튼을 함께 쓸 때는 버튼이 임베드 내부가 아니라 메시지 컴포넌트라는 점을 항상 염두에 두고, reply() 대신 채널 전송이나 defer() → editReply() 패턴을 사용하면 불필요한 답장 표시를 제거할 수 있다. 디스코드 봇을 운영하면서 호스팅 환경(예: 디스호스트)에 배포한 뒤에도 동일한 방식으로 처리하면 깔끔한 규칙 임베드를 유지할 수 있다.