스마트폰으로 영수증 사진만 찍으면 사무실 컴퓨터 엑셀에 자동으로 품목별로 정리되는 시스템, 꿈만 같으셨죠? 파이썬과 구글의 최신 AI인 Gemini를 활용하면 누구나 직접 만들 수 있습니다.
초보자분들도 차근차근 따라 하실 수 있도록, ‘AI 영수증 자동 집계 시스템’ 제작 과정을 정리해 드립니다.
목차
사진 한 장으로 끝내는 스마트한 영수증 정산 시스템
매달 쌓이는 종이 영수증, 일일이 타이핑하며 엑셀에 입력하느라 고생하셨나요? 이제 텔레그램 봇에게 사진만 보내세요. AI가 상호명, 날짜, 금액은 물론 수십 개의 세부 품목까지 세로로 예쁘게 나열해 줍니다.
1. 준비물: 무엇이 필요한가요?
시작하기 전에 딱 세 가지만 준비해 주세요.
- 파이썬(Python): 우리 시스템의 두뇌 역할을 합니다.
- 구글 Gemini API 키: 사진을 읽고 글자로 해석해 줄 AI 전문가입니다. (AI Studio에서 무료 발급 가능)
- 텔레그램 봇 토큰: 사원들과 대화할 메신저 창구입니다. (@BotFather를 통해 생성)
2. 영수증 자동 집계 시스템의 3가지 핵심 포인트
이번 프로젝트에서 우리가 가장 신경 쓴 ‘똑똑한 기능’들입니다.
① 1품목 1행 세로 나열 (정리의 핵심!)
이 시스템은 영수증에 품목이 10개면 엑셀에도 10줄을 생성합니다. 덕분에 나중에 품목별로 합계를 내거나 필터링하기가 매우 편리합니다.
② AI 비용 절감 (중복 방지 필터)
똑같은 사진을 실수로 두 번 보낼 때마다 AI 비용이 나가면 아깝겠죠? 사진을 분석하기 전, 이미지 고유 ID를 먼저 대조하여 이미 처리된 사진은 AI를 호출하지 않고 즉시 차단합니다.
③ 누가 보냈는지 자동 기록
여러 명의 영업사원이 동시에 사용해도 괜찮습니다. 텔레그램 프로필 이름을 자동으로 가져와서 엑셀에 ‘전송자’를 기록해 주니, 누가 쓴 돈인지 일일이 확인할 필요가 없습니다.
3. 영수증 자동 집계 핵심 라이브러리 설치하기
파이썬(Python)에서 AI 영수증 자동 집계 시스템을 구동하기 위해 필요한 3가지 핵심 도구(라이브러리)를 설치하거나 최신 버전으로 업데이트하는 명령입니다.
각 도구의 역할은 다음과 같습니다.
1. google-generativeai
- 역할: 구글의 최신 AI 모델인 Gemini(제미나이)를 파이썬에서 사용할 수 있게 연결해주는 통로입니다.
- 기능: 영수증 사진을 분석하여 글자를 읽어내고(OCR), 상호명·날짜·품목·금액 등을 똑똑하게 분류하는 ‘두뇌’ 역할을 담당합니다.
2. pandas (판다스)
- 역할: 파이썬에서 데이터를 표(Table) 형태로 다루기 위한 가장 강력한 도구입니다.
- 기능: AI가 분석한 영수증 데이터를 엑셀처럼 행과 열로 정렬하고, 기존 데이터와 합치거나 가공하는 ‘데이터 관리자’ 역할을 합니다.
3. openpyxl
- 역할: 파이썬 프로그램이 엑셀(.xlsx) 파일을 직접 읽고 쓸 수 있게 해주는 엔진입니다.
- 기능: pandas가 정리한 영수증 내역을 실제 컴퓨터 하드디스크에 엑셀 파일 형태로 저장하거나, 이미 있는 엑셀 파일을 불러올 때 반드시 필요합니다.
pip install -U google-generativeai pandas openpyxl설치 확인 방법
설치가 제대로 끝났는지 확인하려면 아래 명령어를 입력했을 때 버전 정보가 나오면 성공입니다.
pip show google-generativeai설치가 완료되면 나중에 엑셀에서 품목별로 필터를 걸거나 합계를 내기도 훨씬 편해집니다. 이를 위해 데이터 저장 방식을 ‘1영수증 1행’에서 ‘1품목 1행’으로 작성했어요
1품목 1행(세로 나열) 저장 방식 코드
import logging
from telegram import Update
from telegram.ext import ApplicationBuilder, ContextTypes, MessageHandler, filters
from google import genai
import PIL.Image
import pandas as pd
import json
import io
import os
from datetime import datetime
GEMINI_API_KEY = "여기에_구글_API_키를_입력하세요"
TELEGRAM_BOT_TOKEN = "여기에_텔레그램_봇_토큰을_입력하세요"
MODEL_NAME = "gemini-2.0-flash-lite"
EXCEL_FILE = r"C:\영수증관리\영업비용_집계.xlsx"
client = genai.Client(api_key=GEMINI_API_KEY)
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO)
async def process_receipt(update: Update, context: ContextTypes.DEFAULT_TYPE):
try:
user_name = update.message.from_user.full_name
photo_info = update.message.photo[-1]
file_uid = photo_info.file_unique_id
if os.path.exists(EXCEL_FILE):
try:
df_temp = pd.read_excel(EXCEL_FILE)
if 'file_uid' in df_temp.columns and file_uid in df_temp['file_uid'].values:
await update.message.reply_text("⚠ 이미 등록된 영수증입니다. (중복 차단)")
return
except:
pass
photo = await photo_info.get_file()
photo_bytes = await photo.download_as_bytearray()
img = PIL.Image.open(io.BytesIO(photo_bytes))
await update.message.reply_text(f"[{user_name}]님, 영수증 품목을 세로로 나열하여 분석 중입니다...")
prompt = """
영수증 이미지를 분석해서 다음 항목을 추출해줘.
1. 상호명(store)
2. 날짜(date): YYYY-MM-DD 형식
3. 총금액(total_amount): 숫자만
4. 품목리스트(items): 각 품목별로 이름(name)과 가격(price)을 리스트 형태로 추출해.
결과는 반드시 순수한 JSON 형식으로만 응답해.
{"store": "상호명", "date": "YYYY-MM-DD", "total_amount": 10000, "items": [{"name": "품목1", "price": 5000}, {"name": "품목2", "price": 5000}]}
"""
response = client.models.generate_content(model=MODEL_NAME, contents=[prompt, img])
json_text = response.text.replace('```json', '').replace('```', '').strip()
data = json.loads(json_text)
rows = []
recorded_at = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
for item in data['items']:
rows.append({
'recorded_at': recorded_at,
'sender': user_name,
'date': data['date'],
'store': data['store'],
'item_name': item.get('name'),
'item_price': item.get('price'),
'total_receipt_amount': data['total_amount'],
'file_uid': file_uid
})
df_new = pd.DataFrame(rows)
os.makedirs(os.path.dirname(EXCEL_FILE), exist_ok=True)
if os.path.exists(EXCEL_FILE):
df_old = pd.read_excel(EXCEL_FILE)
df_final = pd.concat([df_old, df_new], ignore_index=True)
else:
df_final = df_new
columns = ['recorded_at', 'sender', 'date', 'store', 'item_name', 'item_price', 'total_receipt_amount', 'file_uid']
df_final = df_final[columns]
df_final.to_excel(EXCEL_FILE, index=False)
await update.message.reply_text(
f"엑셀 기록이 완료되었습니다!\n"
f"장소: {data['store']}\n"
f"품목수: {len(data['items'])}개\n"
f"총 금액: {data['total_amount']}원"
)
except Exception as e:
await update.message.reply_text(f"❌ 분석 중 오류가 발생했습니다: {e}")
if __name__ == '__main__':
application = ApplicationBuilder().token(TELEGRAM_BOT_TOKEN).build()
application.add_handler(MessageHandler(filters.PHOTO, process_receipt))
print("========================================")
print("영수증 자동 집계 봇이 정상적으로 실행되었습니다.")
print("========================================")
application.run_polling()저장된 엑셀 모습 (예시)

이제 엑셀을 열면 아래와 같이 품목별로 세로로 한 줄씩 들어갑니다.
| recorded_at | sender | date | store | item_name | item_price | total_receipt_amount |
|---|---|---|---|---|---|---|
| 17:40:01 | 홍길동 | 2026-03-04 | OO식당 | 백반 | 5500 | 25000 |
| 17:40:01 | 홍길동 | 2026-03-04 | OO마트 | A4용지 | 1950 | 25000 |
| 17:40:01 | 홍길동 | 2026-03-04 | OO마트 | 사무용품 | 2500 | 25000 |

이 시스템을 구축하면 사무실 직원은 더 이상 영수증과 씨름할 필요가 없습니다. 또한 개인적으로 가계부를 작성할 때 다른 어플을 설치하거나 별도의 작업을 하지 않고도 영수증만 있으면 매달 지불 경비를 집계할 수 있습니다.
활용 팁:
- 1:1 채팅 활용: 직원들에게 봇 아이디만 알려주면 각자 보낸 내역이 엑셀에 차곡차곡 쌓입니다.
- 엑셀 줄 바꿈: 품목이 길 경우 엑셀의 ‘텍스트 줄 바꿈’ 기능을 켜면 더욱 보기 좋습니다.

