
LINE Bot에 '대화 기억'과 'PUSH 문맥'을 부여하는 Google Apps Script 템플릿
요약
Google Apps Script와 Google Sheets를 활용하여 대화 기억 및 PUSH 문맥 관리 기능이 포함된 LINE Bot 템플릿을 소개합니다. 서버 구축 없이도 대화 로그 저장, 토큰 관리, PUSH 메시지 대응이 가능한 실용적인 개발 가이드를 제공합니다.
핵심 포인트
- Google Apps Script 기반의 서버리스 LINE Bot 구현
- PUSH 메시지에 대한 사용자 반응을 문맥으로 처리하는 기술
- Google Sheets를 활용한 대화 로그 및 벡터 DB 관리
- 토큰 집계 및 LINE 글자 수 제한에 따른 장문 분할 기능
LINE Bot을 만드는 기사나 샘플 코드는 이미 많이 있습니다.
하지만 실제로 일상에서 사용할 수 있는 Bot으로 만들려고 하면, 단순히 AI API로 요청을 보내고 응답을 받는 것만으로는 조금 부족합니다.
예를 들어,
- 과거의 대화를 어느 정도 기억해주길 원함
- 정기 PUSH를 보낸 후, 그 화제에 대해 답장이 오면 문맥(Context)으로 취급해주길 원함
- 하지만 PUSH 문구를 매번 대화 이력에 섞어서 Bot의 말투가 무너지는 것은 피하고 싶음
- LINE의 글자 수 제한이나 로그 저장, 토큰 집계도 한꺼번에 관리하고 싶음
- 가급적 서버를 구축하지 않고, Google Apps Script와 스프레드시트(Spreadsheet)만으로 운용하고 싶음
이러한 '실운용에서 은근히 필요해지는 부분'까지 포함된 템플릿은 의외로 적다고 느꼈습니다.
이 기사에서는 Google Apps Script, Google Sheets, LINE Messaging API, Chat Completions API를 사용하여,
대화 로그 저장 · 이력 참조 · PUSH 알림 · PUSH 답장 문맥 판정 · 장문 분할 답장 · 토큰 집계까지 정리된 LINE Bot 템플릿을 소개합니다.
특징은 PUSH 로그를 단순히 이력에 섞는 것이 아니라, 사용자가 직전의 PUSH에 반응하고 있을 때만 문맥으로 포함한다는 점입니다.
이를 통해 정기 메시지를 보낼 수 있는 Bot이면서도, 일반 대화에서는 PUSH 문구의 영향을 받기 어렵게 만들 수 있습니다.
또한 코드 내의 개인정보나 고유 설정은 모두 〓...〓 형식의 플레이스홀더(Placeholder)로 되어 있어, 필요한 부분을 교체하는 것만으로 자신만의 LINE AI Bot으로 테스트할 수 있는 구성으로 만들었습니다.
'일단 동작하는 AI 답장 Bot'에서 한 걸음 나아가, 대화 로그를 가지고 PUSH 흐름도 자연스럽게 다룰 수 있는 Bot을 만들고 싶은 분들을 위한 템플릿입니다.
이 템플릿은 LINE Messaging API, Google Apps Script, Google Sheets, OpenAI 호환 Chat Completions API를 조합한 LINE Bot용 샘플입니다.
공개용 템플릿으로 사용할 수 있도록 모델명, Bot 이름, 사용자 ID, PUSH 문구, 시트 이름, 에러 문구 등 이용자가 편집해야 할 값은 〓...〓로 감싸 두었습니다.
- LINE에서 멘션되었을 때만 답장함
- 대화 로그를 Google Sheets에 저장함
- 과거 로그를 대화 이력으로 이용함
- 키워드 검색으로 관련 로그를 참조함
- Embedding API가 설정되어 있는 경우 벡터 검색을 이용함
- 정기 PUSH 메시지를 전송할 수 있음
- PUSH 메시지에 대한 답장인지 여부를 판정하여, 필요한 경우에만 PUSH 문맥을 이력에 포함함
- LINE의 글자 수 제한에 맞춰 장문 답장을 분할함
- 입력 토큰 수, 출력 토큰 수, 합계 토큰 수를 저장함
LineAiBot.template.gs 내의 〓...〓를 환경에 맞춰 변경해 주세요.
| 플레이스홀더 | 내용 |
|---|---|
〓OWNER_DISPLAY_NAME〓 | |
| 멘션 대상으로 하고 싶은 소유자 이름 | |
〓BOT_DISPLAY_NAME〓 | |
| 멘션 대상으로 하고 싶은 Bot 이름 | |
〓CHAT_COMPLETIONS_URL〓 | |
| OpenAI 호환 Chat Completions API URL | |
〓CHAT_MODEL_NAME〓 | |
| 사용할 채팅 모델 이름 | |
〓EMBEDDING_MODEL_NAME〓 | |
| 사용할 Embedding 모델 이름 | |
〓CONVERSATION_LOG_SHEET_NAME〓 | |
| 대화 로그 저장 시트 이름 | |
〓VECTOR_DB_SHEET_NAME〓 | |
| 벡터 DB 저장 시트 이름 | |
〓DEFAULT_USER_MESSAGE〓 | |
| 멘션만 보내졌을 경우의 기본 입력 문구 | |
〓TARGET_LINE_USER_ID〓 | |
| PUSH 전송 대상 LINE 사용자 ID | |
〓ERROR_REPLY_MESSAGE〓 | |
| 예외 발생 시 LINE으로 보낼 문구 | |
〓MORNING_PUSH_TOPIC_1〓 | |
| 아침 PUSH용 화제 1 | |
〓MORNING_PUSH_TOPIC_2〓 | |
| 아침 PUSH용 화제 2 | |
〓MORNING_PUSH_TOPIC_3〓 | |
| 아침 PUSH용 화제 3 | |
〓EVENING_PUSH_TOPIC_1〓 | |
| 밤 PUSH용 화제 1 | |
〓EVENING_PUSH_TOPIC_2〓 | |
| 밤 PUSH용 화제 2 | |
〓EVENING_PUSH_TOPIC_3〓 | |
| 밤 PUSH용 화제 3 |
Apps Script의 「프로젝트 설정」 → 「스크립트 속성」에 다음을 등록합니다.
| 키 | 필수 | 내용 |
|---|---|---|
LINEAPI_TOKEN | 필수 | LINE Messaging API의 채널 액세스 토큰 |
LLM_API_KEY | 필수 | Chat Completions API의 API 키 |
GEMINI_API_KEY | 선택 | Embedding API 키 |
GEMINI_API | 선택 | GEMINI_API_KEY의 별칭 |
SPREADSHEET_ID | 조건부 | 저장할 스프레드시트 ID. 스프레드시트에 직접 연결된 Apps Script라면 생략 가능 |
API 키를 코드에 직접 작성하지 마세요.
CONFIG.SHEET_NAME
에 지정한 시트에 저장합니다.
| 열 | 이름 | 내용 |
|---|---|---|
| A | Date | 저장 일시 |
| B | UserId | LINE 사용자 ID |
| C | Mention | 반응한 멘션 이름 |
| D | UserMessage | 사용자 발언 |
| E | AIMessage | Bot 답변 |
| F | PromptTokens | 입력 토큰 수 |
| G | CompletionTokens | 출력 토큰 수 |
| H | UserName | LINE 표시 이름 |
| I | TotalTokens | F열과 G열의 합계 |
저장 위치는 A열의 날짜 로그를 기준으로 결정합니다.
I열에 계산식이나 집계식이 있는 경우에도, 추가 위치가 불필요하게 건너뛰어지지 않도록 설계되었습니다.
CONFIG.VECTOR_SHEET_NAME
에 지정한 시트에 저장합니다.
| 열 | 이름 | 내용 |
|---|---|---|
| A | Date | 저장 일시 |
| B | Query | 사용자 발언 |
| C | Answer | Bot 답변 |
| D | Vector | Embedding 벡터 JSON |
Embedding API 키가 설정되지 않은 경우, 벡터 검색 및 벡터 저장은 실질적으로 무효화됩니다.
다음 중 하나에 멘션되었을 때만 응답합니다.
CONFIG.OWNER_NAME
CONFIG.ASSISTANT_NAME
- LINE Webhook으로 이벤트를 받음
- 텍스트 메시지인지 확인
- 멘션 대상인지 확인
- 입력을 정형화
- 관련 로그를 검색
- PUSH 문맥인지 판정
- 이력을 가져옴
- Chat Completions API로 문의
- 대화 로그를 저장
- LINE으로 답변
- Embedding 벡터를 저장
사용자 입력을 분류하여 생성 파라미터(Generation Parameters)와 답변량의 기준을 변경합니다.
| 분류 | 기준 |
|---|---|
| 짧은 답변을 요구하는 입력 | 80~180자 정도 |
| ... |
템플릿 본체에는 고유한 말투 예시를 포함하지 않았습니다. 필요한 경우 사용자가 buildSystemPrompt()를 편집해 주세요.
TARGET_USERS에 LINE 사용자 ID를 설정합니다.
const TARGET_USERS = [
'〓TARGET_LINE_USER_ID〓',
];
Apps Script의 시간 기반 트리거(Time-driven Trigger)로 다음을 등록합니다.
sendMorningGreeting
sendEveningGreeting
다음 조건을 바탕으로 사용자 발언이 직전 PUSH에 대한 답장인지 판정합니다.
- 직전 PUSH로부터
CONFIG.PUSH_CONTEXT_MINUTES분 이내 - PUSH 본문과 사용자 입력에 공통 키워드가 있음
- 반응어(Reaction words)가 포함됨
- 입력이 짧음
PUSH와 관련이 있다고 판정된 경우에만 직전 PUSH를 대화 이력(Conversation History)에 추가합니다.
답변은 CONFIG.MAX_REPLY_CHARS 단위로 분할됩니다.
기본값:
MAX_REPLY_CHARS: 1900
MAX_REPLY_MESSAGES: 5
-
Google Sheets를 생성한다
-
Apps Script를 연다
-
LineAiBot.template.gs를 붙여넣는다 -
〓...〓로 둘러싸인 값을 편집한다 -
스크립트 속성(Script Properties)을 등록한다
-
trigger_authorization()을 실행하여 권한을 승인한다 -
웹 앱(Web App)으로 배포한다
-
LINE Developers의 Webhook URL에 웹 앱 URL을 설정한다
-
LINE에서 멘션하여 동작을 확인한다
-
필요하다면 시간 기반 트리거를 설정한다
-
실행 사용자: 나
-
액세스 권한이 있는 사용자: 모두
웹 앱을 업데이트한 경우, 새로운 버전으로 다시 배포해 주세요.
공개 템플릿에는 말투나 인격 설정을 포함하지 않았습니다.
필요한 경우 사용자가 직접 buildSystemPrompt()에 추가해 주세요.
다음 내용을 변경해 주세요.
CHAT_COMPLETIONS_URL: '〓CHAT_COMPLETIONS_URL〓',
MODEL: '〓CHAT_MODEL_NAME〓',
다음 내용을 변경해 주세요.
"〓MORNING_PUSH_TOPIC_1〓"
"〓EVENING_PUSH_TOPIC_1〓"
===========================================================
/**
* LINE AI Bot Template
*
...
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기