BOUT

AI / OCR review / verification flow

커밋 기록에는 이전 GitHub 닉네임 beancan0325로 보일 수 있습니다.

BOUT — 영수증과 무상 AS 정보를 잃어버리지 않게 보관하는 앱

팀 프로젝트 | 2026.06 ~ 2026.08

BOUT는 전자·가전기기 영수증과 보증 정보를 한곳에 저장해, 나중에 수리·교환·환불이나 무상 AS 기간 확인이 필요할 때 바로 찾을 수 있게 돕는 앱입니다. 사용자는 영수증을 사진으로 올리고, 서비스는 구매일·제품명·가격·무상 AS 기간 후보를 OCR/AI로 추출합니다. 다만 인식 결과가 틀릴 수 있으므로, 제가 맡은 백엔드 흐름은 추출값을 바로 저장하지 않고 사용자가 확인한 값만 최종 기기/보증 기록으로 남기도록 나누는 데 초점을 뒀습니다.

담당 범위

OCR 후보값 흐름, 검수 후 저장 경계, 영수증/보증 데이터 구조, API 책임 분리를 정리했습니다.

판단

AI/OCR 결과는 사용자가 확인하기 전까지 최종 서비스 데이터가 아니라 임시 후보로 다뤄야 한다고 보았습니다.

검증

OCR 응답 예제와 API 테스트, 영수증 파일 참조 검증으로 추출 단계와 최종 저장 단계의 계약을 확인했습니다.

한계

서버는 사용자가 화면에서 검수를 끝냈는지 직접 증명하지 않습니다. 현재는 서로 다른 API 계약으로 책임을 분리했습니다.

Selected backend case

정상 형식이지만 틀린 OCR 결과를 최종 기록과 분리했습니다

AI가 만든 값은 JSON 형식이 맞아도 실제 영수증 내용과 다를 수 있습니다. 추출 성공을 저장 성공으로 취급하지 않고, 불확실성을 응답에 남긴 뒤 사용자가 확정한 값만 별도 저장 API가 받도록 경계를 나눴습니다.

1. 업로드

영수증 이미지와 OCR 요청을 받습니다.

2. 추출

구매일·금액·제품·분류 후보를 만듭니다.

3. 불확실성 표시

needs_review, warnings, null로 추측을 숨기지 않습니다.

4. 사용자 검수

사용자가 후보값을 확인하고 수정합니다.

5. 최종 저장

검수된 필드와 receipt_file_ids만 기록으로 확정합니다.

위험한 상태
잘못 인식한 구매일·가격·제품명이 그럴듯한 정상 응답으로 들어와 최종 데이터처럼 저장되는 상태
설계 결정
분류 후보는 Pydantic Literal로 제한하고 읽을 수 없는 선택 필드는 null로 반환했습니다. OCR 응답과 영수증 생성 요청은 서로 다른 스키마로 유지했습니다.
실제 코드
app/modules/ocr/infrastructure/receipt_ocr_client.py, app/modules/ocr/api/schemas.py, app/modules/receipts/api/schemas.py, app/modules/receipts/domain/value_objects.py
검증 근거
app/modules/ocr/tests/test_api.py에서 검수 필요 응답을 확인하고, app/modules/receipts/tests/test_api.py에서 파일 참조와 잘못된 저장 요청을 검증했습니다.
남은 한계
UI 검수 완료 여부를 서버가 직접 인증하지는 않습니다. OCR 전용 필드가 최종 저장 요청에 섞이지 못하도록 API 계약을 분리해 위험 범위를 제한했습니다.

결론: AI 정확도를 과장하기보다, 틀릴 수 있는 출력을 서비스 데이터로 승격시키는 경계를 백엔드 계약으로 통제했습니다.

1. 프로젝트 소개

무엇

영수증 원본, 구매 정보, 무상 AS 만료일을 한곳에 모아두는 전자·가전기기 아카이빙 서비스입니다.

종이 영수증을 잃어버리거나 AS 만료일을 놓치면 수리·교환·환불 때 증빙을 찾기 어렵기 때문입니다.

대상

전자제품, 생활가전, 디지털 기기처럼 구매 기록과 보증 기간을 나중에 다시 확인해야 하는 사용자입니다.

2. 설계

OCR 후보 생성

사진 속 영수증에서 제품명, 구매일, 가격, 무상 AS 기간 후보를 먼저 뽑아 입력 부담을 줄입니다.

사용자 확인 단계

OCR은 날짜·가격·상품명을 잘못 읽을 수 있어, 사용자가 확인한 값만 진짜 기록으로 저장합니다.

보증 기록 저장

확정된 구매 정보와 무상 AS 기간을 기준으로 제품별 보증 기록을 남기는 흐름입니다.

백엔드 책임 분리

OCR 후보 생성, 사용자 확인, 기기/보증 기록 저장 단계를 분리해 데이터가 섞이지 않게 정리했습니다.

3. 주요 기능

BOUT OCR 검수 흐름 대표 이미지
OCR 영수증 등록

영수증 이미지를 업로드하고 OCR 결과를 구조화된 데이터로 변환합니다.

BOUT 보증서 관리 대표 이미지
보증서 관리

구매일과 상품 정보를 바탕으로 보증 기록을 조회할 수 있게 저장합니다.

BOUT 제품 히스토리 대표 이미지
제품 히스토리 조회

확정된 구매 기록을 기준으로 제품별 이력을 다시 확인합니다.

4. 프로젝트별 문제-해결

OCR / AI 검수

OCR 결과를 바로 저장하면 잘못된 보증 기록이 될 수 있는 문제

문제

영수증 OCR 결과는 편리하지만 항목명, 가격, 날짜, 무상 AS 기간을 잘못 읽을 수 있습니다.

원인

AI가 추출한 값은 확률적 결과라서 DB에 바로 저장하면 틀린 구매/보증 기록이 남을 수 있습니다.

해결

OCR 결과를 임시 후보로 두고, JSON 구조와 필수 값을 확인한 뒤 사용자가 확정한 값만 저장합니다.

결과

AI 자동화의 속도는 유지하면서 최종 데이터 책임은 사용자 검수 흐름 안에서 설명할 수 있게 됐습니다.

Warranty Data

무상 AS 만료일을 나중에 찾기 어렵지 않게 구조화한 문제

문제

영수증 원본만 보관하면 사용자가 나중에 제품명, 구매일, 보증 기간을 다시 찾아야 합니다.

원인

이미지 파일과 실제 서비스에서 검색해야 하는 구매/보증 필드가 분리되어 있지 않으면 조회와 알림이 어렵습니다.

해결

영수증 원본과 별개로 제품명, 브랜드, 구매일, 가격, 무상 AS 기간 같은 구조화 필드를 저장 대상으로 나눴습니다.

결과

나중에 제품별 보증 기간 조회, AS 만료 알림, 영수증 원본 확인을 같은 기록에서 이어갈 수 있습니다.

5. 협업 프로세스

기능 단위 이슈

OCR, 영수증 저장, 보증서 조회처럼 기능 단위로 작업 범위를 나눠 진행했습니다.

Feature Branch

팀 저장소에서 기능 브랜치 기준으로 변경 범위를 분리하고 PR로 합치는 방식을 사용했습니다.

PR 리뷰

API 응답 구조, 데이터 저장 시점, 예외 처리 기준을 리뷰 가능한 단위로 남깁니다.

라벨/릴리즈 정리

bug, feature, documentation 같은 라벨과 버전 단위 릴리즈 기준으로 변경 범위를 정리합니다.