목차
- OpenAI Vision API에서 부딪힌 벽
- Gemini API — SDK가 두 개인 나라
- 신 SDK 설치부터 첫 호출까지
- 멀티모달 입력 — 리스트 하나로 끝나는 구조
- 구조화된 출력과 스트리밍
- Gemini API 비용 — 같은 작업에서 25배 차이
- Gemini API가 맞지 않는 경우
이미지를 포함한 멀티모달 요청에서 Gemini 2.0 Flash의 입력 비용은 GPT-4o의 약 1/25 수준이다. 사내 챗봇에 이미지 분석을 붙이면서 처음 비교해봤는데, 차이가 생각보다 컸다. 이미지 10장을 묶어서 분석하면 gpt-4o 기준 한 건에 약 15,000토큰, 하루 1,000건이면 월 $1,125다.
Gemini API로 갈아타는 게 숫자만 보면 명확해 보이지만, 실제 전환 과정에서 SDK 혼란, 모델 호환성, 한국어 성능 차이 같은 구멍이 있었다.
OpenAI Vision API에서 부딪힌 벽
OpenAI의 멀티모달 API는 메시지 배열 안에 이미지 URL이나 base64를 넣는 구조다. 방식 자체는 직관적이지만 실무에서 쓰다 보면 제약이 드러난다.
이미지 토큰 계산이 불투명하다. OpenAI는 이미지를 512×512 타일로 분할해서 각 타일마다 토큰을 매기는데, 실제 소모량은 API 응답의 usage 필드를 봐야 안다. 사전에 비용을 정확히 예측하기 어렵다. 파일 형식 지원 범위도 좁다. 이미지(PNG, JPEG, GIF, WebP)만 직접 입력 가능하고, PDF는 페이지별 이미지 변환을, 오디오는 Whisper API를 각각 거쳐야 한다. 파이프라인이 길어진다.
속도 문제도 있었다. 이미지 10장을 한 번에 넣으면 응답까지 체감상 8~12초가 걸렸다(Ubuntu 22.04, Python 3.12 환경 기준). 공식적으로 이미지 수 제한은 없다고 하지만, 토큰 급증에 따라 응답이 느려지는 건 사실상 제한이나 마찬가지다. "이미지 10장 비교 분석"을 매일 수천 건 처리하는 건 비용과 속도 양쪽에서 현실적이지 않았다.
Gemini API — SDK가 두 개인 나라
Gemini API를 처음 쓰려고 공식 문서(ai.google.dev)에 들어갔을 때, 가장 먼저 마주친 건 SDK 선택지가 두 개라는 사실이었다.
pip install google-generativeai # 구 SDK (v0.x 계열)
pip install google-genai # 신 SDK (v1.x 계열)
2024년까지는 google-generativeai가 공식이었다. 2025년 초부터 Google이 google-genai를 밀기 시작했고, 2026년 4월 현재 두 패키지가 공존하고 있다. 구글 공식 문서도 페이지마다 다른 SDK 예제를 보여준다. Stack Overflow 답변은 더 뒤섞여 있어서, 초기 진입자 입장에서는 어느 쪽을 따라야 하는지 판단이 어렵다.
처음에 구 SDK를 설치하고 퀵스타트 코드를 그대로 따라 했다. genai.configure(api_key=...) 호출 후 genai.GenerativeModel('gemini-2.0-flash')로 모델을 로드하려 했더니 에러가 떨어졌다.
404 models/gemini-2.0-flash is not found
구 SDK는 Gemini 1.5 시리즈까지만 안정적으로 지원하고, 2.0 이상 모델에서 호환성 문제가 간헐적으로 발생한다. 에러 메시지가 불친절해서 원인을 찾는 데 30분 정도 헤맸다. 모델명 오타인 줄 알고 gemini-2.0-flash-001, models/gemini-2.0-flash 등 변형을 이것저것 시도했는데, 문제는 모델명이 아니라 SDK 자체였다.
2026년 4월 기준, 신 SDK(google-genai)를 쓰는 게 맞다. 구 SDK는 유지보수 모드에 가깝고, Gemini 2.0/2.5의 신기능 — 코드 실행, 구조화된 출력, Grounding, 검색 연동 — 은 신 SDK에서만 제대로 동작한다. (출처: Google AI for Developers 공식 문서, 2026-04-04 확인)
신 SDK 설치부터 첫 호출까지
환경 설정
API 키는 Google AI Studio에서 발급한다. Google 계정 로그인 → "Get API Key" → 키 생성. GCP 프로젝트 연결 없이도 바로 만들 수 있다. 무료 티어가 Gemini 2.0 Flash 기준 분당 15회, 일일 1,500회를 제공하므로 프로토타이핑에는 충분하다.
pip install google-genai # 반드시 google-genai — 구 SDK(google-generativeai) 아님
export GEMINI_API_KEY="your-api-key" # .env 파일에 넣어두는 게 낫다
텍스트 생성 — 기본 형태
from google import genai
# 클라이언트 초기화
client = genai.Client(api_key="your-api-key")
# gemini-2.0-flash로 텍스트 생성
response = client.models.generate_content(
model="gemini-2.0-flash",
contents="Python의 GIL이 멀티스레딩에 미치는 영향을 설명해줘"
)
print(response.text)
print(response.usage_metadata) # prompt_token_count, candidates_token_count 확인
신 SDK는 OpenAI의 클라이언트 패턴과 구조가 비슷하다. Client를 만들고 client.models.generate_content()로 호출하는 2단계다. 구 SDK에서는 genai.configure() → GenerativeModel() → model.generate_content() 3단계를 거쳐야 했는데, 한 단계 줄었다.
response.usage_metadata를 찍으면 prompt_token_count, candidates_token_count, total_token_count가 나온다. 비용 추적이 필요하면 이 값을 요청마다 로깅해두는 게 좋다.
멀티모달 입력 — 리스트 하나로 끝나는 구조
Gemini API에서 텍스트, 이미지, PDF, 오디오를 한 번에 처리하는 방식은 단순하다. contents 파라미터에 리스트로 묶어 넣으면 된다. OpenAI는 메시지 객체 안에 image_url을 중첩해야 하는 반면, Gemini는 Part 객체를 리스트에 나열하는 것만으로 충분하다. 이게 두 API의 가장 큰 구조적 차이다.
이미지 분석
from google import genai
from pathlib import Path
client = genai.Client(api_key="your-api-key")
# 로컬 이미지를 바이트로 읽어서 바로 전달
image_bytes = Path("screenshot.png").read_bytes()
response = client.models.generate_content(
model="gemini-2.0-flash",
contents=[
"이 스크린샷에서 에러 메시지를 찾아 원인을 분석해줘",
genai.types.Part.from_bytes(
data=image_bytes,
mime_type="image/png"
)
]
)
print(response.text)
이미지 여러 장이 필요하면 Part를 리스트에 추가하면 그만이다. 화요일에 PM이 요청한 "이미지 10장 비교 분석"도 이 방식으로 해결했다. Part 10개를 리스트에 넣고 프롬프트를 앞에 붙이면 끝이었다. 응답 시간은 체감상 4~6초. OpenAI에서 8~12초 걸리던 것과 비교하면 의외로 큰 차이였다.
PDF와 오디오 — 전처리가 필요 없다
Gemini가 OpenAI 대비 확실히 편한 지점이 여기다. PDF를 이미지로 변환하지 않고 바이트 그대로 넣을 수 있다. mime_type을 application/pdf로 지정하면 된다. 오디오도 MP3, WAV, FLAC 등을 바이트로 읽어서 mime_type만 맞추면 바로 처리된다. Whisper 같은 별도 STT 파이프라인을 거칠 필요가 없어서 코드가 짧아진다.
다만 인라인 데이터는 20MB 제한이 있다. 그 이상의 파일은 File API를 통해 먼저 업로드하고, 반환된 URI를 Part.from_uri()로 참조하는 방식을 써야 한다. 큰 동영상 파일을 다룰 때 이 단계가 추가된다. 상세 내용은 공식 File API 가이드에 나와 있다.
구조화된 출력과 스트리밍
JSON 스키마를 강제하는 방법
LLM 응답을 후처리할 때 가장 골치 아픈 게 파싱 실패다. "JSON으로 답해줘"라고 프롬프트에 써도 마크다운 코드 블록으로 감싸거나 필드명을 임의로 바꿔버리는 경우가 있다. Gemini API는 response_schema에 Pydantic 모델을 넘기면 해당 스키마를 강제할 수 있다:
from pydantic import BaseModel
class BugReport(BaseModel):
severity: str # "critical" | "major" | "minor"
component: str # 영향받는 컴포넌트
description: str # 버그 설명
suggested_fix: str # 수정 제안
response = client.models.generate_content(
model="gemini-2.0-flash",
contents="다음 로그를 분석해서 버그 리포트를 작성해줘: [로그 내용]",
config=genai.types.GenerateContentConfig(
response_mime_type="application/json",
response_schema=BugReport # Pydantic 모델 직접 전달
)
)
import json
bug = json.loads(response.text)
# {"severity": "major", "component": "auth", "description": "...", "suggested_fix": "..."}
OpenAI의 response_format과 비슷한 개념이지만, Pydantic 모델을 바로 넘길 수 있다는 점이 다르다. JSON 스키마 딕셔너리를 수동으로 작성하지 않아도 된다. 이 기능은 구 SDK(google-generativeai)에서 불안정했고, 신 SDK v1.x에서 제대로 동작하기 시작한 기능 중 하나다.
스트리밍 응답
이건 간단하다. generate_content() 대신 generate_content_stream()을 호출하면 된다:
response = client.models.generate_content_stream(
model="gemini-2.0-flash",
contents="Python 비동기 프로그래밍의 핵심을 상세히 설명해줘"
)
for chunk in response:
print(chunk.text, end="", flush=True)
메서드 이름만 바뀌고 나머지는 동일하다. 긴 응답에서 TTFT(Time To First Token)가 체감상 크게 줄어든다. 비동기 환경이 필요하면 client.aio.models.generate_content_stream()을 쓰면 되고, FastAPI 같은 비동기 프레임워크의 StreamingResponse에 바로 연결할 수 있다.
Gemini API 비용 — 같은 작업에서 25배 차이
| 모델 | 입력 ($/1M 토큰) | 출력 ($/1M 토큰) | 컨텍스트 윈도우 | 용도 |
|---|---|---|---|---|
| Gemini 2.5 Pro | $1.25 ~ $2.50 | $10.00 ~ $15.00 | 1M | 복잡한 추론 |
| Gemini 2.0 Flash | $0.10 | $0.40 | 1M | 범용 가성비 |
| Gemini 2.0 Flash-Lite | $0.075 | $0.30 | 1M | 대량 배치 처리 |
| GPT-4o (참고) | $2.50 | $10.00 | 128K | 범용 |
(출처: Google AI 가격 페이지, OpenAI 가격 페이지, 2026-04-04 확인. Gemini 2.5 Pro는 200K 토큰 초과 시 단가가 올라간다.)
대부분의 용도에서 Gemini 2.0 Flash가 답이다. 이미지 분석 품질도 실무에서 쓸 만한 수준이었다. 2.5 Pro는 복잡한 코드 생성이나 수학적 추론에서 차이가 나지만, 이미지 설명이나 텍스트 요약 수준이면 Flash로 충분하다. 무료 티어(분당 15회, 일일 1,500회)도 사이드 프로젝트에서는 비용 0원으로 쓸 수 있어서 진입 장벽이 낮다.
Gemini API가 맞지 않는 경우
한국어 복합 조건 처리
Gemini 2.0 Flash에 한국어 프롬프트를 넣었을 때, 조건이 3개 이상 중첩되면 마지막 조건을 무시하는 경우가 종종 있었다. "~하되, ~는 제외하고, ~형식으로 출력해줘" 같은 구조에서 "~형식으로" 부분이 빠지는 식이다. 영어로 바꿔 넣으면 이 현상이 줄어든다. 2.5 Pro에서는 개선되었지만 그만큼 비용이 올라간다.
Function Calling 파라미터 타입 문제
도구 호출 기능에서 파라미터 타입을 가끔 틀린다. 정수를 기대하는 곳에 문자열 "3"을 넣는 식이다. 프롬프트에 타입을 명시적으로 강조하면 완화되지만, 프로덕션에서는 타입 검증 레이어를 따로 두는 게 안전하다. 이 부분은 OpenAI의 Function Calling이 좀 더 안정적이었다.
데이터 처리 리전
Gemini API의 데이터가 어느 리전에서 처리되는지 명시적으로 보장되지 않는다. 개인정보 요건이 까다로운 프로젝트에서는 Vertex AI를 통해 GCP 리전을 지정해야 하는데, 그러면 가격 체계와 SDK 사용법이 달라진다. 이쪽은 아직 직접 세팅해보지 못해서 이 글에서는 다루지 않는다.
당장 Gemini API를 돌려보려면 pip install google-genai로 신 SDK를 설치하고, Google AI Studio에서 키를 발급받은 뒤, 모델명은 gemini-2.0-flash로 시작하면 된다. 무료 티어 안에서 충분히 실험 가능하다. 신 SDK의 소스와 예제는 GitHub(google-gemini/generative-ai-python)에 올라와 있으니, Gemini API 관련 코드는 거기서 찾아 확장하는 게 가장 빠르다.
관련 글
- Claude API Python 연동 가이드 — 첫 호출부터 챗봇 구현까지 – Claude API를 Python에서 처음 연동하면서 겪은 시행착오를 기록했다. .env 파일의 따옴표 하나로 45분을 소모한 인증 에러,…
- 로컬 LLM 보안 운영 — Ollama로 사내 데이터 유출 없이 AI 쓰는 법 – 사내 외부 LLM API가 차단된 뒤 Ollama로 로컬 LLM 보안 운영 환경을 구축했다. 기본 설정의 보안 구멍부터 네트워크 격리, 접…
- Python으로 AI 에이전트 자동화 구축하기 — 작업 분해와 오류 복구 실전 기록 – 주간 리포트를 자동화하려고 Python으로 AI 에이전트 파이프라인을 처음 만들었다. 한 덩어리 스크립트에서 시작해 작업 분해 → 툴 연동…