Discord.js Components V2 사용 방법 (신형 임베드, 줄 나누기, 임베드 내에 버튼 등)

2025. 12. 6. 15:58·봇 개발 팁/Discord.js

1. Component V2 개요

기존 디스코드 봇 개발에서는 Embed(임베드)를 주로 사용했습니다. 하지만 임베드는 제목, 본문, 썸네일 등의 위치가 고정되어 있어 레이아웃을 마음대로 바꾸기 어려웠습니다.

 

Component V2는 이러한 제약 없이 개발자가 원하는 순서대로 텍스트, 버튼, 이미지 등을 배치할 수 있는 새로운 시스템입니다. Embed 대신 Container를 사용하며, 특히 텍스트 바로 옆에 버튼을 배치하는 등 더 자유로운 디자인이 가능합니다.

2. 필수 설정 (플래그)

V2 시스템을 사용하려면 코드를 작성할 때 반드시 플래그(Flag)를 설정해야 합니다. 이 설정이 없으면 코드가 정확해도 디스코드가 이를 V1(기존 방식)으로 인식하여 오류가 발생하거나 메시지가 보이지 않습니다.

필수 코드 패턴

메시지를 전송하는 옵션에 flags: MessageFlags.IsComponentsV2를 포함해야 합니다.

 

import { 
    Client, 
    MessageFlags, // [중요] V2 활성화를 위한 플래그
    InteractionReplyOptions,
    CommandInteraction
} from 'discord.js';

async function sendV2Message(interaction: CommandInteraction) {
    const payload: InteractionReplyOptions = {
        // 1. V2 모드 활성화 (필수)
        flags: MessageFlags.IsComponentsV2,

        // 2. 컴포넌트 배열
        // V2가 활성화되면 'content'나 'embeds' 필드는 사용할 수 없으며,
        // 오직 'components' 배열에만 내용을 담아야 합니다.
        components: [ /* 생성한 컴포넌트들을 이곳에 넣습니다 */ ]
    };

    return payload;
}

3. 핵심 컴포넌트 4가지

V2 레이아웃을 구성하는 주요 클래스들입니다.

  1. Container (컨테이너):
    • 기존의 Embed를 대체하는 최상위 컴포넌트입니다.
    • 이 안에 텍스트, 섹션, 구분선 등을 담아서 한 번에 보냅니다.
    • setAccentColor로 좌측의 색상 띠를 설정할 수 있습니다.
  2. TextDisplay (텍스트 디스플레이):
    • 화면에 글자를 표시하는 컴포넌트입니다.
    • # 제목, **굵게** 등 마크다운 문법을 지원합니다.
  3. Section (섹션):
    • 텍스트와 "액세서리(버튼 또는 썸네일)"를 가로 한 줄에 배치할 때 사용합니다.
    • 텍스트 우측에 바로 버튼을 둘 수 있어 공간 활용에 좋습니다.
  4. Separator (구분선):
    • 컴포넌트 사이에 가로선을 긋거나, 여백(공백)을 추가하여 간격을 조절합니다.

4. 실전 예제

예제 1: 기본 컨테이너 (기존 임베드 대체)

가장 기본적인 형태입니다. Container 안에 TextDisplay를 넣어 메시지를 만듭니다.

import { 
    ContainerBuilder, 
    TextDisplayBuilder, 
    MessageFlags 
} from 'discord.js';

export async function sendSimpleNotice(interaction: any) {
    // 1. 표시할 텍스트 생성
    const noticeText = new TextDisplayBuilder()
      .setContent("# 📢 공지사항\n이번 업데이트로 UI가 변경되었습니다.");

    // 2. 컨테이너 생성 및 텍스트 추가
    const container = new ContainerBuilder()
      .setAccentColor(0x0099FF) // 파란색 띠 설정
      .addTextDisplayComponents(noticeText); // 위에서 만든 텍스트를 컨테이너에 추가

    // 3. 전송
    await interaction.reply({
        components: [container],
        flags: MessageFlags.IsComponentsV2 // [필수] 플래그 설정
    });
}

예제 2: 섹션 활용 (텍스트 옆에 버튼 배치)

설명 텍스트 바로 오른쪽에 버튼을 배치하는 방법입니다. SectionBuilder를 사용합니다.

import { 
    ContainerBuilder, 
    SectionBuilder, 
    TextDisplayBuilder, 
    ButtonBuilder, 
    ButtonStyle, 
    MessageFlags 
} from 'discord.js';

export async function sendInlineButton(interaction: any) {
    // 1. 섹션 좌측에 들어갈 설명 텍스트
    const description = new TextDisplayBuilder()
      .setContent("**디스코드 봇 호스팅**\n월 5,000원에 이용해보세요.");

    // 2. 우측에 배치할 버튼
    const subscribeBtn = new ButtonBuilder()
      .setCustomId('sub_plan_basic')
      .setLabel('구독하기')
      .setStyle(ButtonStyle.Primary); // 보라색 버튼

    // 3. 섹션(Section) 생성 및 조합
    // 텍스트와 버튼을 하나의 '섹션'으로 묶습니다.
    const productSection = new SectionBuilder()
      .addTextDisplayComponents(description) // 텍스트 추가
      .setPrimaryButtonAccessory(subscribeBtn); // 버튼을 액세서리로 설정

    // 4. 컨테이너에 담기
    const container = new ContainerBuilder()
      .setAccentColor(0x5865F2)
      .addSectionComponents(productSection); // 텍스트 대신 섹션을 추가

    await interaction.reply({
        components: [container],
        flags: MessageFlags.IsComponentsV2
    });
}

예제 3: 복합 레이아웃 (드롭다운과 구분선)

여러 컴포넌트를 조합하는 방법입니다. 드롭다운 메뉴(Select Menu)는 Section 내부에 넣을 수 없으므로, 별도의 ActionRow에 담아 Container에 추가해야 합니다.

import { 
    ContainerBuilder, 
    TextDisplayBuilder, 
    SeparatorBuilder, 
    SeparatorSpacingSize,
    ActionRowBuilder,
    StringSelectMenuBuilder,
    MessageFlags 
} from 'discord.js';

export async function sendComplexLayout(interaction: any) {
    // 1. 제목 텍스트
    const title = new TextDisplayBuilder().setContent("### 🛠️ 설정 메뉴");

    // 2. 구분선 (실선)
    const line = new SeparatorBuilder()
      .setSpacing(SeparatorSpacingSize.Small) // 좁은 간격
      .setDivider(true); // true면 실선이 보임

    // 3. 드롭다운 메뉴 생성 (ActionRow 필요)
    const selectMenu = new StringSelectMenuBuilder()
      .setCustomId('config_menu')
      .setPlaceholder('변경할 설정을 선택하세요')
      .addOptions(
            { label: '알림 설정', value: 'noti' },
            { label: '언어 설정', value: 'lang' }
        );

    // 드롭다운은 ActionRow로 감싸야 컨테이너에 넣을 수 있습니다.
    const menuRow = new ActionRowBuilder().addComponents(selectMenu);

    // 4. 여백 (투명한 공백)
    const spacer = new SeparatorBuilder()
      .setSpacing(SeparatorSpacingSize.Large) // 넓은 간격
      .setDivider(false); // false면 선 없이 공백만 생김

    // 5. 바닥글 텍스트
    const footer = new TextDisplayBuilder()
      .setContent("설정은 즉시 저장됩니다.");

    // 6. 컨테이너에 순서대로 추가
    const container = new ContainerBuilder()
      .addTextDisplayComponents(title)       // 제목
      .addSeparatorComponents(line)          // 선
      .addActionRowComponents(menuRow)       // 드롭다운 메뉴
      .addSeparatorComponents(spacer)        // 공백
      .addTextDisplayComponents(footer);     // 바닥글

    await interaction.reply({
        components: [container],
        flags: MessageFlags.IsComponentsV2
    });
}

5. 자주 묻는 질문 (FAQ)

Q. 기존 EmbedBuilder는 사용할 수 없나요?

A. 네, flags: MessageFlags.IsComponentsV2를 사용하면 기존 embeds 필드는 무시됩니다. V2 레이아웃을 사용하려면 ContainerBuilder를 사용해야 합니다.

 

Q. 섹션(Section) 안에 드롭다운 메뉴도 넣을 수 있나요?

A. 불가능합니다. 섹션의 액세서리 자리에는 버튼과 **썸네일(작은 이미지)**만 배치할 수 있습니다. 드롭다운 메뉴는 ActionRow에 담아서 컨테이너에 별도로 추가해야 합니다.

 

Q. 큰 이미지는 어떻게 넣나요?

A. MediaGallery 컴포넌트를 사용합니다. 컨테이너의 addMediaGalleryComponents() 메서드를 사용하여 이미지 URL들을 배열로 추가하면 됩니다.

 

Q. 모바일 화면 호환성은 어떤가요?

A. PC에서는 Section 내부의 텍스트와 버튼이 가로로 나란히 보이지만, 화면이 좁은 모바일 기기에서는 텍스트 아래로 버튼이 줄바꿈 되어 표시될 수 있습니다.

'봇 개발 팁 > Discord.js' 카테고리의 다른 글

디스코드 봇 명령어, 길드 커맨드와 글로벌 커맨드 차이점, 사용 방법  (0) 2025.05.31
Sharding이란? 대규모 봇에서의 필수 구조 이해  (0) 2025.05.23
디스코드 봇에서 유저 포인트 시스템 구현하기  (0) 2025.05.22
디스코드 봇에 SQLite 연동하기 - Prisma로 쉽게 시작하기  (0) 2025.05.21
디스코드 봇 + OpenAI 연동하기 (ChatGPT API)  (0) 2025.05.20
'봇 개발 팁/Discord.js' 카테고리의 다른 글
  • 디스코드 봇 명령어, 길드 커맨드와 글로벌 커맨드 차이점, 사용 방법
  • Sharding이란? 대규모 봇에서의 필수 구조 이해
  • 디스코드 봇에서 유저 포인트 시스템 구현하기
  • 디스코드 봇에 SQLite 연동하기 - Prisma로 쉽게 시작하기
디스호스트
디스호스트
쉽고 안정적인 디스코드 봇 호스팅 서비스, 디스호스트의 기술 블로그입니다. 디스호스트는 24시간 구동되는 서버를 통해 디스코드 봇을 대신 구동시켜 드리는 서비스를 제공하고 있습니다.
  • 디스호스트
    디스호스트 기술 블로그
    디스호스트
  • 블로그 메뉴

    • 홈
    • 디스호스트 사용 가이드
    • 디스코드 봇 호스팅, 24시간 서버 구동
    • 분류 전체보기 (49) N
      • 디스코드 (10)
      • 디스호스트 가이드 (12)
      • 봇 개발 팁 (12) N
        • Discord.js (9) N
        • Discord.py (2) N
      • DiscordJS 개발 튜토리얼 (15)
  • 링크

    • 디스호스트
  • hELLO· Designed By정상우.v4.10.3
디스호스트
Discord.js Components V2 사용 방법 (신형 임베드, 줄 나누기, 임베드 내에 버튼 등)
상단으로

티스토리툴바