01 소개 02 경력 03 작업 04 블로그 05 이력서 PDF
← 작업 목록
실무 AI 2026.04 · 설계 · 단독 구현

상품 이미지 마케팅 오버레이 자동 제거

커머스 상품 이미지에 후편집으로 얹힌 마케팅 오버레이(홍보 뱃지·인증 마크·가격 문구)를 Gemini 비전 모델로 감지하고 인페인팅으로 제거하는 API. 사람·상품 본체는 보존한 채 배경 위 요소만 지웁니다.

분류
실무
기간
2026.04
역할
설계 · 단독 구현
핵심 지표
Gemini 비전 · Cloud Run
PythonFastAPIGeminiCloud RunGCPDockerSecret Manager
// 01
문제
the problem

커머스 상품 이미지에는 촬영 원본 위에 '5팩'·'본사인증'·'1+1'·'50% 할인' 같은 마케팅 오버레이가 후편집으로 얹혀 있는 경우가 많다. 검색 결과·추천 영역·외부 채널처럼 깔끔한 상품 컷이 필요한 지면에서는 이 오버레이가 오히려 방해가 된다. 그렇다고 수만 장을 사람이 일일이 지우는 건 규모상 불가능하고, 단순 이미지 처리로는 '지워도 되는 것(배경 위 홍보 뱃지)'과 '절대 지우면 안 되는 것(사람, 상품 용기에 인쇄된 브랜드·라벨)'을 구분할 수 없었다.


// 02
접근
the approach

핵심은 '무엇을 지우지 말아야 하는가'였다. Gemini 비전 모델(나노바나나: gemini-3.1-flash-image)로 파이프라인을 2단계로 분리했다 — ① 감지: 후편집으로 배경 위에 추가된 요소만 오버레이로 판정하고, 사람과 상품 본체에 인쇄된 것은 절대 대상에서 제외하는 엄격한 룰을 시스템 프롬프트 최상단에 박았다. 폰트·그림자·상품 경계 초과 여부 등 2개 이상 근거가 맞을 때만 오버레이로 표시하고, 위치·타입·confidence를 JSON으로 반환한다. ② 제거: 감지된 대상 설명을 넣어 배경색과 자연스럽게 어우러지도록 인페인팅한다. 생성 모델이 종종 MALFORMED로 비정상 종료하므로, 실패 시 더 짧은 최소 프롬프트로 재시도하는 fallback을 뒀다. FastAPI로 감지 전용(`/detect`)·감지+제거(`/clean`, `/clean/base64`) 엔드포인트를 나눠 Cloud Run에 배포했고, GEMINI_API_KEY는 평문 환경변수가 아니라 Secret Manager로 주입했다. 스크립트로만 돌던 로직을 API로 감싸, 운영자가 별도 실행 환경 없이 관리자 화면에서 바로 이미지를 올려 오버레이를 감지·제거할 수 있게 했다.


// 03
결과
the result

상품 이미지에서 마케팅 오버레이를 API 호출 한 번으로 감지·제거하면서 사람과 상품 본체는 보존한다. 감지만 따로(`/detect`) 돌려 영향 범위를 먼저 확인하거나, 제거까지(`/clean`) 한 번에 처리할 수 있다. Cloud Run을 min-instances 0·요청 기반 과금으로 구성해 트래픽 없을 땐 비용이 들지 않고, CPU 2·메모리 2Gi·concurrency 10 기준 요청 100만 건에 약 $10~15 수준으로 유지된다. 스크립트를 API로 감싼 덕에 운영자가 관리자 화면에서 이미지를 올려 바로 정리할 수 있고, 여러 이미지를 일괄 처리하는 워크플로에도 그대로 얹을 수 있다.


// 04
배운 것
takeaways

파괴적 편집(제거)일수록 정확도의 관건은 '무엇을 지우느냐'가 아니라 '무엇을 절대 건드리지 않느냐'였다. 사람·상품 인쇄물 보존 룰을 프롬프트 최상단에 두고 감지와 제거를 분리하니 오제거가 크게 줄었다. 그리고 생성 모델은 결정적 API가 아니라 비정상 종료·파싱 실패가 일상이므로, 최소 프롬프트 재시도·JSON 파싱 실패 시 안전 기본값 같은 방어를 처음부터 깔아야 실서비스에 태울 수 있었다.

배경

커머스 상품 이미지는 촬영 원본 위에 마케팅 오버레이가 후편집으로 얹혀 있는 경우가 많습니다 — 5팩, 12개월분, 1+1, 본사인증, 50% 할인 같은 홍보 뱃지·인증 마크·가격 문구입니다. 검색 결과나 추천 영역, 외부 채널처럼 깔끔한 상품 컷이 필요한 지면에서는 이 오버레이가 방해가 됩니다. 수만 장을 사람이 지우는 건 불가능하고, 단순 이미지 처리로는 지워도 되는 것과 안 되는 것을 구분할 수 없었습니다.

핵심 — 무엇을 지우지 말 것인가

이 도구의 난이도는 ‘지우기’가 아니라 **‘보존’**에 있습니다. 절대 건드리면 안 되는 것을 시스템 프롬프트 최상단에 못박았습니다.

  • 사람(모델·얼굴) — 절대 제거 금지.
  • 상품 본체에 인쇄된 것 — 용기·포장지의 브랜드명·라벨·로고는 상품의 일부.
  • 배경 위 후편집 요소만 — 촬영 뒤 얹힌 뱃지·인증마크·워터마크·홍보 문구·장식 그래픽.

2단계 파이프라인

Gemini 비전 모델(나노바나나: gemini-3.1-flash-image)로 감지와 제거를 분리했습니다.

이미지 ─▶ ① /detect  감지 (JSON: 위치·타입·confidence)
           폰트·그림자·상품경계 초과 등 근거 2개↑ → 오버레이 판정
      ─▶ ② /clean   제거 (감지 대상 인페인팅 → 배경색과 자연스럽게)
  • 감지(/detect) — 오버레이만 판정, 이미지 변환 없이 근거 JSON 반환. 제거 전에 영향 범위를 먼저 볼 수 있습니다.
  • 제거(/clean, /clean/base64) — 감지 대상 설명을 프롬프트에 넣어 인페인팅. 파일 바이너리 또는 base64 JSON으로 응답.

생성 모델을 실서비스에 태우기

생성 모델은 결정적 API가 아닙니다. 그대로 쓰면 깨집니다.

  • 비정상 종료 방어 — 제거 호출이 MALFORMED_FUNCTION_CALL로 죽으면, 더 짧은 최소 프롬프트로 재시도.
  • 파싱 실패 안전값 — 감지 JSON 파싱이 실패하면 has_overlays:false로 떨어뜨려 오작동 대신 무변경.
  • 포맷 정규화 — JPEG/PNG/WEBP 외 입력은 PNG로 변환해 모델 입력을 안정화.

배포 · 비용

  • Cloud Runmin-instances 0으로 유휴 시 과금 $0, CPU 2·메모리 2Gi·concurrency 10. 요청 100만 건 ≈ $10~15.
  • 키 관리GEMINI_API_KEY를 평문 환경변수가 아니라 Secret Manager로 주입, 서비스 계정에 secretAccessor만 부여.
  • 엔드포인트 분리 — 감지 전용 / 감지+제거를 나눠, 필요에 따라 비용·부작용을 통제.

운영 활용

스크립트로만 돌던 로직을 API로 감쌌습니다. 덕분에 운영자는 별도 실행 환경이나 CLI 없이, 관리자 화면에서 이미지를 올려 바로 오버레이를 감지·제거할 수 있습니다. 감지 전용(/detect)으로 먼저 무엇이 지워질지 확인한 뒤 제거(/clean)를 태우는 식으로, 비개발 운영자도 안전하게 쓸 수 있게 흐름을 나눴습니다.