
React + Spring Boot로 만든 개인용 가계부 앱에 Gemini API를 사용하여 영수증 자동 입력 기능 구현해 보기
요약
React와 Spring Boot 환경에서 Gemini API를 활용해 영수증 이미지를 자동으로 분석하고 가계부에 입력하는 기능을 구현하는 방법을 소개합니다. OCR 라이브러리 대신 Gemini API를 사용하여 날짜, 상품, 금액, 카테고리를 JSON 형식으로 추출하는 전체 프로세스를 다룹니다.
핵심 포인트
- Gemini API를 활용한 영수증 데이터 자동 추출 구현
- Spring Boot와 React를 이용한 풀스택 아키텍처 설계
- 프롬프트에 DB 카테고리 목록을 동적으로 삽입하는 노하우
- Base64 인코딩을 통한 이미지 데이터 전송 방식
저 혼자 사용하는 가계부 앱을 개발하고 있는데, 매번 영수증을 보면서 "식비 몇 엔, 생필품 몇 엔..." 하고 수동으로 입력하는 것이 점점 귀찮아져서 기록을 게을리하게 되는 경우가 있었습니다.
그래서,
"영수증 이미지를 업로드하면, AI가 자동으로 날짜·상품·금액·카테고리를 판별해서 자동 입력해 주면 되잖아!"
라는 생각에 Gemini API를 가계부 내에 구현해 보았습니다. 그 구현 절차와 프롬프트(Prompt)의 노하우 등을 비망록으로서 이 기사에 남겨두고자 합니다.
OCR 라이브러리를 사용하는 것도 고려했지만, 구현이 번거롭기도 하고 애초에 AI가 알아서 다 해줄 것이라 생각하여 Gemini API를 사용했습니다.
또한, 개인용 가계부 앱이기 때문에 하루 영수증 읽기 횟수가 많지 않습니다.
상위 모델을 사용하지 않으면 기본적으로 무료로 이용할 수 있다는 점도 큽니다.
이번에는 gemini-2.5-flash를 사용했습니다. 레이트 리밋(Rate Limit)은 다음과 같습니다.
・분당 요청 수 (RPM): 5
・분당 토큰 수 (입력) (TPM): 250K
・일일 요청 수 (RPD): 20
충분합니다.
Gemini API를 사용하기 위해서는 Google AI Studio에 접속하여 API Key를 생성해야 합니다.
- Google AI Studio에 접속하여 로그인합니다.
- 화면 왼쪽 하단에 Get API key가 있으므로, 해당 부분을 클릭합니다.
- API 키 화면으로 이동하면 화면 오른쪽 상단에 API 키 생성 버튼이 있으므로, 해당 부분을 클릭합니다.
- 이후 화면의 지시에 따라 키 이름과 프로젝트를 선택하여 생성합니다.
코드에 API 키를 하드코딩하지 않기 위해, 환경 변수(Environment Variable)에서 읽어오도록 설정합니다.
이번 환경은 Windows이므로, 시스템 환경 변수에 설정했습니다.
- 변수명을
GEMINI_API_KEY로 지정 - 위에서 생성한 Gemini API 키를 변수 값으로 지정
처리 흐름은 다음과 같이 심플하게 설계했습니다.
- 프론트엔드 (React): 영수증 이미지를 드래그 앤 드롭으로 업로드한다.
- 백엔드 (Spring Boot/Java): 이미지를 받아 Base64 형식으로 인코딩한다. DB에서 현재 카테고리 목록을 가져온다.
- AI (Gemini API): 이미지와 카테고리 목록을 Gemini에 전달하여 JSON 형식으로 해석 데이터를 가져온다.
- 프론트엔드 (React): 해석 결과를 확인 및 수정할 수 있는 모달(Modal)을 표시하고, OK를 누르면 가계부에 등록한다.
API 키를 획득했다면, Spring Boot에서 영수증 이미지를 받아 Gemini API로 요청을 보내는 컨트롤러(Controller)를 구현합니다.
Gemini로부터 JSON 형식으로 결과를 받기 위해 데이터 구조(DTO)를 정의합니다.
// ReceiptScanItem.java (명세)
public class ReceiptScanItem {
private String category; // 카테고리명
...
Java 21의 HttpClient를 사용하여 gemini-2.5-flash 모델로 이미지 데이터와 텍스트 프롬프트(Prompt)를 전송합니다.
프롬프트에서는 DB에 등록되어 있는 카테고리 이름 목록을 동적으로 삽입하여, AI가 그중에서 분류하도록 합니다.
@RestController
@RequestMapping("/api/receipt")
public class ReceiptScannerController {
...
프론트엔드에서는 이미지를 업로드하는 드래그 앤 드롭 영역을 가진 모달 UI를 준비합니다.
API로부터의 반환값인 "스캔 결과(날짜·품목 리스트)"를 일단 폼(Form)에 반영시켜, 화면상에서 품목별로 미세 조정할 수 있도록 했습니다.
AI가 올바르게 인식하고 있는지 화면에서 품목별로 확인 및 편집할 수 있게 하면서, 등록 버튼을 누르는 시점에 프론트엔드 측에서 카테고리별로 자동으로 집계(합산)하여 등록합니다.
이를 통해 이력이 상품별로 잘게 쪼개지는 것을 방지하면서, 카테고리별로 정확한 가계부 데이터를 등록할 수 있습니다.
const handleRegister = async () => {
if (formItems.length === 0) return;
isSaving(true);
...
AI 스캔 버튼

영수증 업로드 초기 화면

영수증 업로드

AI 분석 중

분석 결과

내역에 반영

Google AI Studio의 Gemini API를 활용함으로써, 단 수십 줄의 프롬프트(Prompt)와 Java 표준 HttpClient만으로 실용적인 영수증 스캔 기능을 개인용 가계부에 구현할 수 있었습니다.
특히 세금 포함, 세금 제외, 할인이 복잡하게 얽힌 일본 영수증의 계산 오차를 "합계 금액과 일치시키기"라는 프롬프트의 기교만으로 해결할 수 있었던 점은 LLM (Large Language Model)의 영리함을 실감하게 했습니다.
AI 대단해
Gemini API 공식 문서
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기