이전 시간에 제미나이 API를 이용한 엑셀에서 구동할 수 있는 채팅 시스템의 뼈대를 완성했습니다. 오늘은 제미나이 채팅 시스템의 기능을 구현할 모듈 코드를 작성하고 작동 원리를 자세히 알아보겠습니다. 이전 시간에 작성했던 엑셀의 사용자폼 작성법은 아래 링크를 확인해보세요.
1. 채팅기능 구현하기
이전 포스팅에서 채팅 시스템의 채팅 표시창, 프롬프트(Prompt) 입력창, 대화 저장버튼, API Key 입력창, 저장버튼 등의 이벤트에 대한 코드와 외형을 구성했는데요. 이제 내부에서 기능을 담당하는 모듈에 세부 코드를 작성하겠습니다. Alt + F11을 눌러 Visual basic editor을 실행하고 모듈을 추가합니다. 모듈에 추가할 기능은 아래와 같습니다.
① 대화 기록 초기화 : 작성된 대화 내용을 모두 지우고 새로 시작
② API 호출 및 응답 처리 : 사용자가 입력한 메시지와 이전 대화 기록을 함께 Gemini API에 보내고, 받은 응답을 정리해 대화 기록에 추가합니다. 이 기능을 통해 대화 맥락을 유지할 수 있습니다.
③ JSON 데이터 작성 및 정리 : 제미나이 API에 대화 내용을 보내기 위해 대화 내용을 JSON 형식으로 만들고, 특수문자들을 올바르게 처리합니다.
④ JSON 응답 파싱 : Gemini API의 응답에서 필요한 텍스트를 추출하고, 불필요한 마크다운 문법을 제거해 깔끔하게 만듭니다.
⑤ 대화 기록 저장 및 불러오기 : 대화 내용을 텍스트 파일로 저장하거나, 저장된 파일을 불러와 대화 내역을 복원할 수 있습니다.

1) XMLHTTP 객체 생성
▼ HTTP 요청을 보내기 위해 MSXML2.XMLHTTP 객체를 생성합니다. 이 객체는 HTTP 통신(POST, GET 등)을 처리하는 데 사용됩니다.
Dim httpRequest As Object
Set httpRequest = CreateObject("MSXML2.XMLHTTP")
2) API URL 구성
▼ 상수 GEMINI_API_URL에 API 엔드포인트가 정의되어 있으며, 여기에 사용자가 입력한 apiKey를 추가하여 최종 호출 URL을 만듭니다. 제미나이 2.0 Flash를 사용하기 위한 API 엔드 포인트는 아래 코드에서 확인하시기 바랍니다.
' Gemini 2.0 Flash 모델 API 호출 URL (API 호출용)
Private Const GEMINI_API_URL As String = "https://generativelanguage.googleapis.com/v1/models/gemini-2.0-flash:generateContent"
.
.
.
.
Dim apiUrl As String
apiUrl = GEMINI_API_URL & "?key=" & apiKey
3) 전체 프롬프트 구성
- 기존 대화 내역(conversationHistory)이 있으면 이를 포함하여 전체 프롬프트를 구성합니다.
- 이전에 저장된 대화 내역이 있다면, 그 내용을 줄바꿈(vbCrLf)으로 구분하여 새로운 프롬프트와 합칩니다.
- 대화 내역이 없다면, 단순히 사용자가 입력한 프롬프트만을 사용합니다.
Dim fullPrompt As String
If conversationHistory <> "" Then
fullPrompt = conversationHistory & vbCrLf & prompt
Else
fullPrompt = prompt
End If
4) JSON 요청 본문 생성
▼ 전체 프롬프트(fullPrompt)를 JSON 문자열로 변환하는 과정은 CreateJSONRequest 함수에서 이루어집니다. 이때 JsonEscape 함수를 사용하여 특수문자(역슬래시, 큰따옴표 등)를 처리합니다. 최종적으로 처리된 본문 JSON 문자열은 다음과 같은 형식을 갖습니다.
Dim requestBody As String
requestBody = CreateJSONRequest(fullPrompt)
▼ 작성된 JSON 파일 형식
json 형식
{
"contents": {
"role": "user",
"parts": [
{ "text": "정리된 프롬프트" }
]
}
}
5) HTTP POST 요청 설정 및 전송
- Open “POST”, apiUrl, False: POST 방식으로 요청을 초기화합니다.
- apiUrl은 Gemini API 엔드포인트에 사용자의 API 키를 포함시킨 URL입니다.
- SetRequestHeader “Content-Type”, “application/json” – 서버가 JSON 형식의 데이터를 받도록 요청 헤더를 설정합니다.
- Send requestBody – 생성한 JSON 요청 본문을 서버로 전송합니다.
- JSON 요청 본문은 Gemini API에서 요구하는 형식을 따르며, 내부에 “contents”라는 객체 아래 “role”과 “parts” 배열에 사용자가 입력한 텍스트(prompt)가 포함됩니다.
With httpRequest
.Open "POST", apiUrl, False
.SetRequestHeader "Content-Type", "application/json"
.Send requestBody
End With
이러한 요청 방식을 통해서 Gemini API를 호출했을 때 대화 맥락을 유지할 수 있고, 보다 정확한 응답을 생성하는 데 도움을 줍니다. 다만 너무 긴 대화는 입력/출력 토큰을 초과할 수 있으니 주의가 필요합니다. 제미나이 API 사용제한에 대해서는 이전에 다룬 포스팅을 참고하세요.
6) 응답 처리
- 서버로부터의 응답 상태 코드를 확인하여, 200(성공)이면 ParseGeminiResponse 함수가 작동해 JSON 응답에서 텍스트를 추출하고, BeautifyResponse 함수를 통해 불필요한 내용을 제거합니다.
- 최종적으로 대화 내역(conversationHistory)에 사용자 프롬프트와 Gemini – API 응답이 추가되어 텍스트를 반환합니다.
- 만일 응답 상태가 200이 아닐 땐 오류 메시지를 반환합니다.
- CallGeminiAPI 함수는 HTTP POST 요청을 설정하고, JSON 형식의 요청 텍스트를 생성합니다. 또한 Gemini API에 프롬프트를 전송하고 응답을 받아 파싱 및 가공하여 최종 텍스트를 반환하는 역할을 수행합니다.
If .Status = 200 Then
Dim assistantResponse As String
assistantResponse = ParseGeminiResponse(responseText)
assistantResponse = BeautifyResponse(assistantResponse)
' 대화 내역 업데이트
conversationHistory = conversationHistory & vbCrLf & _
"User: " & prompt & vbCrLf & _
"Assistant: " & vbCrLf & assistantResponse
CallGeminiAPI = assistantResponse
Else
CallGeminiAPI = "API 오류: " & .Status & " - " & responseText
End If

2. 저장 기능 (SaveConversationAsAPI)
제미나이 API 호출을 통해 채팅창에 표시된 대화 내용을 사용자가 지정한 위치에 텍스트 파일로 저장합니다. 파일이름은 연, 월, 일 형식이 기본으로 설정되어 있지만 사용자가 원하는 이름으로 변경할 수 있습니다.
- 파일 번호 할당 : FreeFile 함수를 사용해 현재 사용 가능한 파일 번호(YYYY-MM-DD)를 가져옵니다.
- 파일 열기 : 주어진 경로(filePath)에 대해 해당 파일 번호를 사용하여 파일을 새로 생성하거나 기존 파일을 덮어쓰기 합니다.
- 대화 내용 기록 : 전역 변수 conversationHistory에 저장된 대화 내용을 파일에 기록합니다.
- 파일 닫기 : 파일 작업을 마친 후, 열린 파일을 닫아 저장을 완료합니다.
Public Sub SaveConversationAsAPI(filePath As String)
Dim fileNum As Integer
fileNum = FreeFile
Open filePath For Output As #fileNum
Print #fileNum, conversationHistory
Close #fileNum
End Sub
3. 로드 기능 (LoadConversationFromAPI)
저장된 텍스트 파일을 열어 이전 대화 내역을 읽어오고, 이를 conversationHistory 변수에 할당합니다. 로드된 대화내용과 새로 입력한 프롬프트를 포함하여 Gemini – API에 요청합니다. 이를 통해 대화 맥락을 유지하여 보다 정확한 결과를 얻을 수 있습니다.
Public Sub LoadConversationFromAPI(filePath As String)
Dim fileNum As Integer
fileNum = FreeFile
Dim lineContent As String
Dim fileContent As String
Open filePath For Input As #fileNum
Do While Not EOF(fileNum)
Line Input #fileNum, lineContent
fileContent = fileContent & lineContent & vbCrLf
Loop
Close #fileNum
conversationHistory = fileContent
End Sub
- FreeFile 함수를 사용하여 파일을 읽기 위한 파일 번호를 가져옵니다.
- Open 구문으로 지정된 경로(filePath)를 Input 모드(읽기 모드)로 엽니다.
- Do While Not EOF(fileNum) 루프를 사용하여 파일의 끝(EOF)에 도달할 때까지 한줄씩 읽어옵니다.
- Line Input은 파일에서 한줄씩 읽어 문자열 변수 lineContent에 저장합니다.
- 각 줄마다 vbCrLf(줄바꿈)와 함께 누적하여 fileContent 변수에 전체 내용을 저장합니다.
- 파일을 모두 읽은 후 Close 구문으로 파일을 닫습니다.
- 최종적으로 누적된 파일 내용을 conversationHistory 변수에 할당합니다.
4. API 키 저장 / 불러오기
▼ 사용자가 API 키 입력란에 값을 입력한 후 “API 키 저장” 버튼을 클릭하면, 아래와 같이 사용자폼(Userform)에 있는 코드가 실행됩니다.
Private Sub btnSaveAPIKey_Click()
SaveSetting "GeminiChat", "Settings", "APIKey", txtAPIKey.Text
MsgBox "API Key가 저장되었습니다.", vbInformation
End Sub
1) API 키 저장하기
SaveSetting 함수는 VBA에서 간단한 설정 정보를 Windows 레지스트리에 저장합니다. 실제 API Key가 저장되는 Windows 레지스트리의 경로는 아래와 같습니다. 저장된 Gemini API 키는 다시 입력할 필요가 없지만, 여러 사람이 사용하는 공용 PC에서는 API Key가 노출될 수 있으니 주의하세요. Gemini API 키를 저장하지 않으려면 키를 입력하고 “SAVE API Key” 누르지 않고 사용하시기 바랍니다.
HKEY_CURRENT_USER\Software\VB and VBA Program Settings\GeminiChat\Settings\APIKey

2) 저장된 API 키 불러오기
UserForm이 초기화될 때, UserForm_Initialize 이벤트에서 레지스트리에 저장된 API 키를 자동으로 불러옵니다. 매개변수는 SaveSetting과 동일한 순서로 전달되며, 마지막 매개변수는 값이 없을 경우 빈 문자열 “”을 반환합니다.
Private Sub UserForm_Initialize()
' ...
txtAPIKey.Text = GetSetting("GeminiChat", "Settings", "APIKey", "")
' ...
End Sub
5. 실행하기
엑셀 파일인 Gemini_Chat.xlsm을 실행하면 “제미나이 API 채팅 시스템” 버튼을 확인할 수 있습니다. 해당 버튼을 누르면 채팅창이 실행됩니다. 채팅창이 실행되기 전에 먼저 Gemini API key를 입력해야 합니다. 공용 PC가 아니라면 API key를 저장할 수 있으며, 이렇게 저장하면 다음 실행 시 API key를 다시 입력할 필요가 없습니다. 이후 채팅 입력창에 프롬프트를 입력하면 구글 제미나이가 그에 따른 답변을 생성합니다.

1) 한계점
① 모델 호출 제한
해당 코드는 엑셀에서 VBA를 이용하여 작성되었으며, Gemini 2.0 Flash 모델을 호출하도록 구현되어 있습니다. 그러나 새로 업데이트된 제미나이 추론 모델이나 Pro 버전을 사용할 수 없는데요. 그 이유는 새로운 모델의 Endpoint로 변경하더라도, 응답 및 호출에 사용되는 JSON 파일의 구조가 달라져 오류가 발생할 수 있습니다.
② 최신 정보 반영 문제
또한 최신 정보가 반영되지 않아 실시간으로 변경되는 정보를 얻을 수 없습니다. 하지만 데이터 분석, 코드 작성, 내용 요약 등의 기능을 수행하는 데 유용합니다.