Java로 텔레그램 인라인 버튼 봇 만들기: TelegramBots API 실전 예제
텔레그램 봇으로 메뉴 버튼을 띄우고, 버튼 클릭 이벤트(CallbackQuery)를 처리하는 예제입니다.
사용자가 1을 입력하면 인라인 키보드 버튼이 표시되고, 버튼을 클릭하면
콜백 데이터와 메시지 ID를 다시 보내주는 구조입니다.
1. 예제 기능 개요
이 텔레그램 봇 예제는 TelegramBots Java 라이브러리를 사용합니다. 주요 기능은 다음과 같습니다.
- 사용자가 채팅 창에
1을 입력하면 “메뉴를 선택하세요”라는 메시지와 함께 인라인 버튼 출력 - 버튼 텍스트: “버튼”, callbackData: “CheckBtn”
- 버튼 클릭 시 콜백 데이터(callData) + 메시지 ID를 채팅으로 다시 전송
즉, 인라인 키보드(InlineKeyboardMarkup)와 CallbackQuery 처리를 한 번에 이해할 수 있는 기본 구조입니다.
2. 텔레그램 인라인 버튼 봇 전체 코드
아래는 질문에 포함된 코드를 보기 좋게 정리한 버전입니다.
import org.telegram.telegrambots.ApiContextInitializer;
import org.telegram.telegrambots.TelegramBotsApi;
import org.telegram.telegrambots.bots.TelegramLongPollingBot;
import org.telegram.telegrambots.meta.TelegramBotsApiException;
import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
import org.telegram.telegrambots.meta.api.objects.Update;
import org.telegram.telegrambots.meta.api.objects.CallbackQuery;
import org.telegram.telegrambots.meta.api.objects.Message;
import org.telegram.telegrambots.meta.api.objects.replykeyboard.InlineKeyboardMarkup;
import org.telegram.telegrambots.meta.api.objects.replykeyboard.buttons.InlineKeyboardButton;
import java.util.ArrayList;
import java.util.List;
public class TelegramV2 {
public static void main(String[] args) {
// (구버전 라이브러리 기준) 텔레그램 컨텍스트 초기화
ApiContextInitializer.init();
TelegramBotsApi api = new TelegramBotsApi();
// 익명 클래스 형태의 LongPollingBot 구현
TelegramLongPollingBot bot = new TelegramLongPollingBot() {
@Override
public void onUpdatesReceived(List<Update> updates) {
// 필요시 여러 Update를 한 번에 처리할 때 사용
super.onUpdatesReceived(updates);
}
@Override
public void onUpdateReceived(Update update) {
// 1) 일반 메시지 처리
if (update.hasMessage() && update.getMessage().hasText()) {
Message message = update.getMessage();
String text = message.getText();
// 사용자가 1을 입력한 경우 인라인 버튼 표시
if ("1".equals(text)) {
long chatId = message.getChatId();
// 인라인 키보드 생성
List<List<InlineKeyboardButton>> keyboard = new ArrayList<>();
List<InlineKeyboardButton> row = new ArrayList<>();
// "버튼" 텍스트, callbackData는 "CheckBtn"
row.add(new InlineKeyboardButton()
.setText("버튼")
.setCallbackData("CheckBtn"));
keyboard.add(row);
InlineKeyboardMarkup keyboardMarkup = new InlineKeyboardMarkup();
keyboardMarkup.setKeyboard(keyboard);
// 전송할 메시지 구성
SendMessage msg = new SendMessage()
.setChatId(chatId)
.setText("메뉴를 선택하세요")
.setReplyMarkup(keyboardMarkup);
try {
execute(msg);
} catch (TelegramApiException e) {
e.printStackTrace();
}
}
// 2) 버튼 클릭(CallbackQuery) 처리
} else if (update.hasCallbackQuery()) {
CallbackQuery callbackQuery = update.getCallbackQuery();
long chatId = callbackQuery.getMessage().getChatId();
String callData = callbackQuery.getData(); // "CheckBtn"
int messageId = callbackQuery.getMessage().getMessageId();
try {
// 콜백 데이터와 메시지 ID를 그대로 사용자에게 회신
execute(new SendMessage()
.setChatId(chatId)
.setText(callData + " // " + messageId));
} catch (TelegramApiException e) {
e.printStackTrace();
}
System.out.println("callData = " + callData);
}
}
@Override
public String getBotUsername() {
// 텔레그램 BotFather에서 설정한 봇 이름
return "YOUR_BOT_USERNAME";
}
@Override
public String getBotToken() {
// BotFather에서 발급받은 토큰
return "YOUR_BOT_TOKEN";
}
};
try {
// 봇 등록
api.registerBot(bot);
// 시작 시 초기 메시지 보내고 싶을 때 사용 가능 (채팅 ID 직접 지정)
// bot.execute(new SendMessage("CHAT_ID", "봇이 시작되었습니다."));
} catch (TelegramApiException e) {
e.printStackTrace();
}
}
}
위 코드에서 YOUR_BOT_USERNAME, YOUR_BOT_TOKEN 부분은
BotFather에게서 발급받은 값으로 직접 교체해야 합니다.
3. onUpdateReceived() 로직 상세 설명
텔레그램의 LongPolling 방식에서는 새로운 메시지나 버튼 클릭이 발생할 때마다
onUpdateReceived(Update update)가 호출됩니다.
이 예제에서는 크게 두 가지 경우를 처리합니다.
3-1. 사용자가 “1”이라고 입력했을 때
update.hasMessage() && update.getMessage().hasText()조건으로 텍스트 메시지인지 확인message.getText().equals("1")인 경우에만 인라인 키보드 생성InlineKeyboardButton의setCallbackData("CheckBtn")에 콜백용 키값 할당InlineKeyboardMarkup에 키보드 리스트를 세팅 후SendMessage에 연결execute(msg)호출로 사용자에게 버튼이 포함된 메시지 전송
즉, 이 부분은 “조건에 맞으면 메뉴 버튼을 띄우는 역할”입니다.
4. CallbackQuery 처리와 버튼 동작 방식
인라인 키보드 버튼이 눌리면, 텔레그램 서버는 메시지가 아니라 CallbackQuery를 보내줍니다.
이때 update.hasCallbackQuery()가 true로 들어오게 됩니다.
4-1. 콜백 데이터·메시지 ID 추출
} else if (update.hasCallbackQuery()) {
CallbackQuery callbackQuery = update.getCallbackQuery();
long chatId = callbackQuery.getMessage().getChatId();
String callData = callbackQuery.getData(); // "CheckBtn"
int messageId = callbackQuery.getMessage().getMessageId();
try {
execute(new SendMessage()
.setChatId(chatId)
.setText(callData + " // " + messageId));
} catch (TelegramApiException e) {
e.printStackTrace();
}
System.out.println("callData = " + callData);
}
getData(): 버튼 만들 때setCallbackData()에 넣은 값 (여기서는"CheckBtn")getMessage().getChatId(): 콜백이 발생한 메시지가 속한 채팅 IDgetMessage().getMessageId(): 어떤 메시지에 붙어 있던 버튼인지 구분할 때 사용 가능
이 구조를 확장하면 다음과 같이 구현할 수 있습니다.
- callData 값에 따라 메뉴 분기 – 예:
"MENU_1","MENU_2","BACK"등 - 특정 메시지에 대한 상태 관리 – messageId를 이용해 어느 화면에서 온 콜백인지 판별
- 추가로 메시지 편집(EditMessageText)를 사용하면, 화면을 깔끔하게 유지하면서 메뉴 교체 가능
5. 실무에서 쓸 때 고려할 점
5-1. Bot Token/Username 보안
- 코드에 직접 토큰을 하드코딩하지 않고 환경변수, 설정 파일에서 불러오는 것을 추천
- 깃허브에 올릴 때 토큰이 노출되지 않도록
application.properties,.env등 사용
5-2. 구조 개선
- 익명 클래스로 봇을 구현하기보다, 별도의 클래스로 분리해 가독성을 높이는 편이 좋습니다.
- 콜백 처리 부분도 if-else 대신 callData → 핸들러 매핑 구조로 리팩토링하면 유지보수가 편해집니다.
5-3. 라이브러리 버전
- 예제는 구버전 스타일(ApiContextInitializer)에 맞춰져 있으므로,
최신 버전에서는
TelegramBotsApi생성 방법이 조금 달라질 수 있습니다. - 실제 프로젝트에서는 사용하는 telegrambots 라이브러리 버전에 맞는 초기화 코드를 확인하세요.
댓글
댓글 쓰기