- 0
- 105 단어
안녕하세요 케이입니다.
앞에서는 텔레그램 봇에 /news 명령어를 만들고, 제가 원하는 검색어를 직접 입력해서 뉴스를 받아보는 기능까지 만들어봤습니다.
여기까지 오니까 이제 제법 쓸 만한 봇이 된 것 같았습니다.
그런데 실제로 몇 번 사용해보니 또 문제가 생겼습니다.
분명히 명령어도 맞게 입력했고 코드도 저장했는데, 어느 순간부터 봇이 아무 반응을 하지 않는 경우가 생겼습니다.
처음에는 제가 코드를 잘못 건드린 줄 알았습니다.
그래서 코드를 다시 보고 또 보고 했는데, 막상 원인은 코드가 아닌 경우도 있었습니다.
이번 글에서는 제가 텔레그램 봇을 만들면서
“왜 갑자기 아무 대답이 없지?”
라는 상황이 생겼을 때 실제로 어떤 순서로 확인했는지 정리해보겠습니다.
저처럼 코딩을 거의 모르는 입장에서는 어디부터 확인해야 할지조차 모르기 때문에, 이런 순서를 하나 정해놓는 게 생각보다 도움이 많이 됐습니다.
첫 번째로 확인한 건 명령어 오타였습니다
처음에는 너무 당연한 부분이라 생각해서 잘 확인하지 않았습니다.
예를 들어 제가 코드에
if (text == "/news") {
라고 만들어놨다면 텔레그램에서도 정확하게
/news
라고 입력해야 합니다.
그런데 제가 테스트하면서
news
라고 입력하거나
/new
처럼 한 글자를 빠뜨린 적도 있었습니다.
이 경우에는 코드 입장에서는 완전히 다른 글자로 인식합니다.
사람이 보기에는 비슷하지만 봇은 알아서 비슷한 명령어라고 판단해주지 않았습니다.
그래서 봇이 반응하지 않을 때는 일단 제가 입력한 명령어부터 다시 확인했습니다.
특히 영어 명령어를 여러 개 만들다 보면 생각보다 이런 실수가 자주 생겼습니다.
대문자와 소문자도 처음에는 헷갈렸습니다
이것도 직접 해보고 알게 된 부분입니다.
코드에
/news
라고 만들어놓고
/News
처럼 대문자를 섞어서 입력하면 제가 작성한 조건에서는 일치하지 않을 수 있습니다.
예를 들어
if (text == "/news")
라고 되어 있다면 /news와 /News는 서로 다른 값으로 취급될 수 있습니다.
처음에는 이런 것도 자동으로 알아서 처리해주는 줄 알았습니다.
하지만 제가 만든 간단한 코드에서는 그렇지 않았습니다.
그래서 명령어는 되도록 모두 소문자로 통일했습니다.
저처럼 처음 만드는 경우라면
/news
/help
/search
처럼 아예 처음부터 전부 소문자로 정해두는 게 편한 것 같습니다.
/news는 되는데 검색어를 입력하면 아무 반응이 없었습니다
제가 가장 오래 헤맸던 건 이 경우였습니다.
/news를 입력하면
“검색할 뉴스 키워드를 입력해주세요.”
라는 답장은 잘 왔습니다.
그런데 그다음에
인공지능
이라고 입력하면 아무 일도 일어나지 않는 경우가 있었습니다.
이때는 지난 글에서 만들었던 상태 저장 부분부터 확인했습니다.
제가 만든 방식에서는 /news를 입력하면
properties.setProperty("mode_" + chatId, "news");
라는 코드로
“지금 이 사용자는 뉴스 검색 중”
이라는 상태를 저장하도록 했습니다.
그리고 다음 메시지가 들어오면
var mode = properties.getProperty("mode_" + chatId);
를 통해 현재 상태를 가져옵니다.
그런데 이 부분에서 값이 제대로 저장되지 않거나, 상태를 확인하는 코드의 위치가 잘못되면 검색어가 일반 메시지처럼 처리될 수 있었습니다.
그래서 저는 이런 경우
/news 명령어 자체가 실행되는지
그다음 상태가 저장되는지
검색어 입력 후 상태를 읽는 부분이 실행되는지
순서대로 확인했습니다.
처음에는 코드 전체를 한꺼번에 보면서 어디가 문제인지 찾으려고 했는데 그렇게 하니까 더 헷갈렸습니다.
한 단계씩 나눠서 확인하는 게 훨씬 쉬웠습니다.
코드 위치 때문에 작동하지 않는 경우도 있었습니다
제가 처음 봇을 만들 때 가장 이해하기 어려웠던 것 중 하나입니다.
코드 내용이 맞더라도 위치가 잘못되면 원하는 대로 작동하지 않을 수 있었습니다.
예를 들어 코드가 이런 흐름이라고 해보겠습니다.
일반 메시지 처리
/news 명령어 처리
뉴스 검색 상태 확인
제가 삼성전자라는 검색어를 입력하면 뉴스 검색 상태를 확인하기도 전에 일반 메시지 처리 부분에서 끝나버릴 수 있습니다.
그래서 저는 코드를 대략 이런 순서로 정리했습니다.
/help 같은 명령어 확인
/news 같은 명령어 확인
현재 뉴스 검색 상태인지 확인
그 외 일반 메시지 처리
처음에는 코드라는 게 그냥 필요한 내용을 어디든 넣으면 되는 줄 알았습니다.
그런데 직접 만들어보니
무엇을 먼저 확인하는지
도 꽤 중요했습니다.
이 부분은 지금도 코드를 수정할 때 항상 먼저 확인하고 있습니다.
return이 어디 있는지도 확인했습니다
처음에는 return이라는 단어도 무슨 뜻인지 몰랐습니다.
지금은 아주 단순하게
여기서 이 작업은 끝
정도로 이해하고 있습니다.
예를 들어
if (text == "/help") {
sendMessage(chatId, "도움말입니다.");
return;
}
라고 하면 /help에 대한 답장을 보낸 뒤 그 아래 코드를 계속 실행하지 않고 끝냅니다.
그런데 제가 코드를 수정하다가 return의 위치를 이상하게 넣은 적이 있었습니다.
그랬더니 원래 실행돼야 할 코드가 그 아래까지 내려가지 못하고 중간에서 끝나버렸습니다.
반대로 return을 빼먹으면 명령어를 실행한 뒤 그 아래 일반 메시지 처리까지 같이 실행되는 경우도 있었습니다.
코딩을 잘 아는 분들에게는 기본적인 내용이겠지만 저는 직접 문제가 생겨보고 나서야 이해했습니다.
그래서 지금은 조건문 안에 return이 있으면
“여기서 끝나도 되는 상황인가?”
를 한 번씩 확인하고 있습니다.
코드를 수정했는데 텔레그램에서는 예전처럼 움직였습니다
이 문제도 몇 번 겪었습니다.
분명히 Google Apps Script에서 코드를 수정하고 저장했는데 텔레그램 봇은 수정 전과 똑같이 움직였습니다.
처음에는 저장이 안 된 줄 알고 계속 저장 버튼만 눌렀습니다.
그런데 Google Apps Script를 웹앱으로 사용하고 있다면 경우에 따라 배포된 버전을 다시 확인해야 했습니다.
제가 코드를 수정했다고 해서 항상 기존에 연결된 웹앱이 제가 생각한 방식으로 바로 바뀌는 건 아니었습니다.
그래서 코드 수정 후 이상하다 싶으면
Google Apps Script에서 코드 저장
웹앱 배포 상태 확인
현재 텔레그램 Webhook이 어느 URL에 연결되어 있는지 확인
이 순서도 같이 확인했습니다.
특히 예전에 Webhook 302 오류 때문에 계속 막혔던 경험이 있어서 이제는 봇이 갑자기 이상하면 Webhook도 한 번씩 확인하게 됐습니다.
Webhook이 제대로 연결되어 있는지도 확인했습니다
텔레그램에서 제가 봇에게 메시지를 보내면 그 내용이 Google Apps Script까지 전달되어야 합니다.
이 연결 역할을 하는 게 Webhook입니다.
쉽게 생각하면
텔레그램에서 온 메시지를 내 코드가 있는 곳으로 전달해주는 주소
정도로 이해하고 있습니다.
Webhook이 잘못 연결되어 있으면 제가 텔레그램에서 아무리 /news를 입력해도 코드 쪽에서는 메시지를 받을 수 없습니다.
저는 이런 경우 텔레그램의 getWebhookInfo를 통해 현재 상태를 확인했습니다.
여기에서 오류가 표시되거나 제가 사용 중인 Google Apps Script 주소가 아닌 다른 주소가 나오면 Webhook 설정부터 다시 확인했습니다.
특히 Apps Script를 다시 배포하면서 웹앱 주소를 바꿨는데 텔레그램에는 예전 주소가 남아있는 경우도 주의할 필요가 있었습니다.
Google Apps Script의 실행 기록도 봤습니다
처음에는 이런 메뉴가 있는지도 몰랐습니다.
Google Apps Script에는 코드가 실제로 실행됐는지 확인할 수 있는 실행 기록이 있습니다.
이게 초보자인 저한테는 생각보다 유용했습니다.
예를 들어 텔레그램에서 /news를 입력했는데 아무 답장이 없다면 두 가지 경우를 생각할 수 있습니다.
아예 Google Apps Script까지 메시지가 오지 않은 경우
메시지는 왔는데 코드 실행 중 오류가 난 경우
이 둘은 원인이 완전히 다릅니다.
실행 기록에 아무것도 없다면 Webhook이나 연결 문제를 먼저 의심할 수 있습니다.
반대로 실행 기록에는 뭔가 있는데 오류로 표시된다면 코드 쪽에서 문제가 발생했을 가능성이 높았습니다.
처음에는 오류 메시지를 봐도 무슨 뜻인지 거의 몰랐습니다.
그래도 최소한
“연결이 안 된 건지”
“코드에서 문제가 난 건지”
정도는 구분할 수 있었습니다.
이것만으로도 문제 찾기가 훨씬 쉬워졌습니다.
chatId가 제대로 들어오는지도 확인했습니다
텔레그램으로 답장을 보내려면 누구에게 메시지를 보낼 것인지 알아야 합니다.
여기에 사용하는 값이 chatId입니다.
제가 사용한 코드에서는 보통 들어온 메시지 안에서 chatId를 가져옵니다.
그런데 코드를 수정하다 보면 변수 이름을 잘못 쓰거나 다른 위치에서 chatId를 사용하면서 오류가 날 수도 있었습니다.
예를 들어
chatId
라고 만들어놓고 다른 곳에서는
chatID
처럼 입력하면 문제가 생길 수 있습니다.
사람이 보면 거의 같은 단어지만 코드에서는 다르게 처리될 수 있습니다.
이것도 제가 처음에는 잘 몰랐던 부분입니다.
그래서 오류 메시지에
not defined
같은 표현이 보이면 변수 이름이 정확한지도 확인했습니다.
봇 토큰도 다시 확인했습니다
제가 봇을 처음 만들었을 때 BotFather에서 토큰을 발급받았습니다.
이 토큰은 제가 만든 텔레그램 봇을 코드에서 사용할 수 있게 해주는 중요한 값입니다.
예를 들어 코드 어딘가에
var token = "내 봇 토큰";
처럼 사용하고 있다면 이 값이 잘못되었을 경우 메시지를 정상적으로 보내지 못할 수 있습니다.
특히 테스트하면서 봇을 새로 만들거나 토큰을 다시 발급받았다면 기존 코드에는 이전 토큰이 남아있을 수도 있습니다.
저도 여러 번 수정하다 보니
“혹시 토큰이 예전 건가?”
하고 확인했던 적이 있습니다.
다만 토큰은 다른 사람에게 공개하면 안 되는 값이라 블로그에 캡처를 올릴 때는 반드시 가리는 게 좋습니다.
저도 화면을 캡처할 때 토큰이 보이는 부분은 최대한 조심하고 있습니다.
결국 제가 정한 확인 순서
이것저것 문제를 겪다 보니 지금은 봇이 반응하지 않을 때 무작정 코드를 고치지 않습니다.
저는 대략 이런 순서로 확인하고 있습니다.
첫 번째는 제가 명령어를 제대로 입력했는지 확인합니다.
두 번째는 Google Apps Script 실행 기록에 실행된 흔적이 있는지 봅니다.
세 번째는 Webhook이 정상적으로 연결되어 있는지 확인합니다.
네 번째는 코드의 조건문 순서와 return 위치를 봅니다.
다섯 번째는 chatId나 변수 이름에 오타가 없는지 확인합니다.
여섯 번째는 봇 토큰이나 웹앱 주소가 현재 사용하는 값이 맞는지 확인합니다.
이 순서대로 보면 적어도 아무것도 모른 채 코드 전체를 들여다보는 상황은 많이 줄었습니다.
직접 해보니 오류가 꼭 나쁜 것만은 아니었습니다
처음 텔레그램 봇을 만들 때는 오류가 뜨면 굉장히 당황했습니다.
빨간 글씨가 나오거나 아무 답장이 없으면
“내가 잘못 건드렸나?”
싶어서 코드를 다시 원래대로 돌리고 싶었습니다.
그런데 계속 만들어보니 오히려 한 번씩 문제가 생겨야 그 기능이 어떻게 움직이는지 이해하게 되는 것 같습니다.
Webhook이 끊겨보니 Webhook 역할을 알게 됐고
검색어가 제대로 전달되지 않으면서 상태 저장이라는 개념을 알게 됐고
코드가 중간에서 멈추면서 return이 어떤 역할을 하는지도 알게 됐습니다.
물론 아직 오류 메시지를 보고 바로 원인을 알아내는 수준은 아닙니다.
그래도 예전처럼 무조건 처음부터 다시 만드는 일은 많이 줄었습니다.
지금은
“어디까지는 정상적으로 되고 어디부터 안 되는지”
하나씩 확인해보는 습관이 조금 생긴 것 같습니다.
다음에는 이렇게 만든 뉴스 검색 기능을 실제로 사용하면서 불편했던 부분을 하나 더 수정해보려고 합니다.
현재는 검색어를 입력하면 뉴스 결과가 너무 많이 나올 수 있는데요.
다음 글에서는 텔레그램으로 받아보는 뉴스 개수를 5개나 10개처럼 원하는 만큼 제한하는 방법을 직접 적용해보겠습니다.