티스토리 뷰

반응형

Python으로 공부하는 OpenAI 25편 — FastAPI + OpenAI 서비스, 출시 후 첫 30일 동안 무엇을 가장 먼저 봐야 할까?

앞으로도 글은 이렇게 가겠습니다.
질문형 제목으로 시작하고, 첫 문단에서 바로 답하고, 본문은 구조적으로 나누고, 중간에 실행 가능한 코드와 FAQ, 출처, 추천 태그까지 넣는 방식으로요. 올려주신 문서에서 말한 **“AI가 답변 재료로 가져가기 쉬운 글 구조”**를 계속 유지하겠습니다.

한 줄 요약

FastAPI + OpenAI 서비스를 출시한 뒤 첫 30일은 새 기능을 더 붙이는 시기가 아니라, 사용량(usage), 비용(cost), 지연(latency), 오류(error), 검색 품질(RAG), 반복 사용률을 집중해서 보는 시기입니다. OpenAI도 프로덕션 운영에서 비용 최적화, 지연 최적화, 평가 best practices, prompt caching, rate limits를 별도 주제로 안내하고 있고, 특히 운영 단계에서는 “잘 되냐”보다 “어디서 흔들리는지 빨리 보이게 만들라”는 흐름을 강조합니다. (OpenAI 개발자)


이 글에서 다루는 내용

  • 출시 후 첫 30일에 무엇을 봐야 하는지
  • 어떤 지표를 먼저 봐야 하는지
  • RAG 서비스라면 무엇이 추가로 중요한지
  • 그냥 감으로 운영하지 않게 해주는 로그 분석 코드
  • “이건 지금 고치고, 이건 나중에 고쳐도 되는 것”을 구분하는 법

왜 첫 30일이 중요한가?

솔직히 출시 직후엔 다 비슷합니다.
기분이 좀 들뜨고, “이제 사람들 쓰겠지?” 싶은데, 동시에 진짜 무서운 시기이기도 해요.

왜냐하면 이때부터는 코드가 아니라 사용 패턴이 답을 주기 시작하거든요.

예를 들면:

  • 내가 중요하다고 생각한 기능은 아무도 안 쓰고
  • 별생각 없이 넣은 작은 기능이 계속 호출되고
  • RAG chunk를 5개 넣는 게 좋을 줄 알았는데 비용만 커지고
  • 출력이 길수록 만족도가 높을 줄 알았는데 오히려 이탈이 늘고
  • 429는 거의 안 날 줄 알았는데 피크 시간에 몰려서 바로 튀고
  • prompt caching이 잘 먹을 줄 알았는데 prefix가 흔들려서 이점이 거의 없고

OpenAI는 운영 단계에서 production best practices, cost optimization, latency optimization, evaluation best practices, rate limits, prompt caching을 별도 문서로 다룹니다. 이 말은 결국, 출시 후엔 기능보다 운영 지표를 먼저 배우는 쪽이 맞다는 뜻에 가깝습니다. (OpenAI 개발자)


출시 후 첫 30일의 핵심 원칙

제가 제일 추천하는 원칙은 이겁니다.

출시 후 첫 30일은 “더 만들기”보다 “무슨 일이 일어나는지 보기”에 집중한다.

진짜로요.
이 시기엔 새로운 기능 3개 붙이는 것보다, 아래를 아는 게 훨씬 값집니다.

  • 누가 쓰는가
  • 언제 쓰는가
  • 어떤 질문이 많은가
  • 어떤 요청이 비싼가
  • 어디서 느려지는가
  • 어떤 실패가 반복되는가
  • 무엇이 진짜 가치 있는가

이걸 모르면, 다음 기능 우선순위도 거의 감으로 정하게 됩니다.


1. 제일 먼저 봐야 할 것: 요청 수보다 “반복 사용”입니다

처음엔 다들 요청 수를 먼저 봅니다.
물론 중요해요. 하지만 저는 그보다 반복 사용을 먼저 봐야 한다고 생각합니다.

왜냐하면 SaaS에서 진짜 의미 있는 신호는 “한 번 눌러본 사람”보다 다시 오는 사람이거든요.

출시 후 첫 30일에 먼저 볼 질문

  • 오늘 처음 들어온 사용자가 내일도 오는가
  • 같은 사용자가 같은 기능을 2번 이상 쓰는가
  • 결과를 실제로 복사/다운로드/저장하는가
  • 질문 유형이 반복되는가

이건 OpenAI 문서의 usage API가 직접 말하는 지표는 아니지만, 운영형 제품에서 가장 먼저 봐야 하는 제품 지표입니다. OpenAI 쪽 usage/cost 자료는 사용량과 비용을 정량적으로 추적하는 수단을 제공하고, 그 위에 제품 측정은 우리가 얹어야 합니다. (OpenAI 개발자)

좋은 신호

  • 10명이 썼는데 6명이 다시 옴
  • 같은 사용자가 같은 기능을 반복해서 씀
  • 특정 워크플로가 고정적으로 발생함

위험 신호

  • 트래픽은 있는데 다 1회성
  • 질문은 많은데 저장/복사/다운로드가 없음
  • 기능은 많은데 핵심 사용 흐름이 안 보임

2. 두 번째로 봐야 할 것: 어떤 요청이 비싼가

출시 후 한동안 가장 많이 드는 생각이 이겁니다.

“사람 많이 오면 좋지.”

맞는데, OpenAI 서비스는 사람이 많이 오는 것수익이 나는 것이 자동으로 같지 않습니다.

OpenAI pricing과 cost optimization 문서가 강조하는 것도 결국 이거예요. 비용은 모델 선택, 입력 길이, 출력 길이, cached input, batch/flex 전략에 따라 크게 달라집니다. prompt caching은 반복 prefix가 있을 때 비용과 latency를 줄일 수 있다고 설명합니다. (OpenAI 개발자)

출시 후 첫 30일엔 최소한 이건 알아야 합니다.

  • 어떤 endpoint가 가장 비싼가
  • 어떤 질문 유형이 output tokens를 길게 만드는가
  • RAG 요청이 일반 요청보다 얼마나 더 비싼가
  • cached input이 실제로 얼마나 잡히는가

실전 질문

  • /chat와 /rag-chat 중 어디가 더 비싼가
  • 긴 출력이 정말 사용자 만족도를 올리는가
  • top-k를 5에서 3으로 줄여도 품질이 유지되는가
  • system prompt가 너무 자주 바뀌어서 캐시를 깨고 있진 않은가

이건 그냥 “나중에 보자” 하면 안 됩니다.
첫 30일에 이걸 보면, 다음 달부터 구조를 더 싸게 만들 수 있습니다.


3. 세 번째로 봐야 할 것: latency는 평균보다 p95가 더 중요합니다

OpenAI latency optimization과 production best practices는 latency를 별도 주제로 다루고, 실제 체감 성능을 줄이기 위한 전략을 설명합니다. 운영에서는 평균 latency만 보면 꽤 자주 속습니다. 느린 요청 몇 개가 사용자 경험을 더 크게 망치기 때문이죠. (OpenAI 개발자)

왜 평균이 위험한가

예를 들어:

  • 90% 요청은 1.2초
  • 10% 요청은 8초

그러면 평균은 그럭저럭 괜찮아 보일 수 있습니다.
근데 사용자는 그 8초짜리만 기억합니다.

그래서 출시 후 첫 30일엔 이걸 보세요

  • p50 latency
  • p95 latency
  • endpoint별 latency
  • model별 latency
  • retrieval time / generation time 분리 가능 여부

특히 RAG나 멀티모달이 붙었다면 더 중요합니다.

  • 검색이 느린가
  • 업로드 저장이 느린가
  • 모델 호출이 느린가
  • 출력이 너무 길어서 느린가

이걸 나눠서 봐야 합니다.


4. 네 번째로 봐야 할 것: RAG는 “정답률”보다 “검색 상태”부터 봐야 합니다

RAG가 붙은 서비스는 진짜 자주 착각합니다.

“답이 별로네. 모델이 문제인가?”

근데 실제로는 검색이 먼저 흔들리는 경우가 정말 많습니다.

OpenAI evaluation best practices와 production best practices 흐름을 따라가 보면, 정확도 문제는 모델만이 아니라 입력 품질, retrieval 품질, representative eval set과 같이 봐야 합니다. prompt caching이나 rate limit처럼, 정확도도 별도 관리 대상입니다. (OpenAI 개발자)

출시 후 첫 30일에 RAG에서 먼저 볼 것

  • retrieved_chunk_count
  • source diversity
  •  
  • fallback 비율
  • source가 항상 같은 문서로만 치우치는지
  • “문서에 없음” 응답 비율
  • 검색 latency
반응형

위험 신호

  • retrieved chunk 수가 갑자기 줄거나 늘어남
  • 답변 source가 지나치게 한 파일에 몰림
  • 문서에 분명히 있는데 “모르겠다”가 많음
  • 문서와 무관한 일반론 답변이 늘어남

즉, RAG는 모델 output만 보면 늦습니다.
검색 단계가 지금 건강한지를 먼저 봐야 해요.


5. 다섯 번째로 봐야 할 것: 실패는 “몇 건 났는가”보다 “무슨 실패가 반복되는가”가 중요합니다

OpenAI rate limits 가이드는 429와 요청/토큰 제한을 설명하고, evaluation/production 문서들은 운영 단계에서 실패 패턴을 반복적으로 보고 개선하라고 유도합니다. 첫 30일엔 모든 에러를 똑같이 보면 안 됩니다. (OpenAI 개발자)

에러를 이렇게 나누면 편합니다

  • 401/403: 키/권한/환경 문제
  • 429: rate limit / burst traffic
  • 5xx/네트워크: 일시 장애
  • validation error: 입력 문제
  • tool call 실패: function schema / argument 문제
  • worker 실패: background job 구조 문제

출시 후 첫 30일 질문

  • 가장 많이 나는 에러 3개는 뭔가
  • 같은 에러가 특정 시간대에 몰리는가
  • 특정 endpoint에만 몰리는가
  • 복구 가능한 실패인가, 설계 문제인가

이걸 보면 바로 알 수 있습니다.
지금 필요한 게 “기능 추가”가 아니라 “재시도/backoff”인지, 아니면 “입력 검증 강화”인지요.


6. 여섯 번째로 봐야 할 것: prompt caching이 진짜 먹고 있는가

이건 생각보다 많이 놓칩니다.

OpenAI prompt caching 문서는 반복 prefix가 있을 때 캐시가 자동으로 동작하고, 입력 비용과 latency를 줄일 수 있다고 설명합니다. 하지만 prefix가 자주 흔들리면 이점이 줄어듭니다. (OpenAI 개발자)

첫 30일에 꼭 볼 질문

  • cached_input_tokens가 실제로 잡히는가
  • 특정 endpoint는 캐시 비율이 높은가
  • system prompt가 너무 자주 바뀌는가
  • request 앞부분에 timestamp 같은 가변 요소가 들어가지는 않는가

좋은 신호

  • 반복형 업무에서 cached input이 꾸준히 잡힘
  • 동일한 워크플로에서 input 비용이 안정적임

위험 신호

  • 매 요청이 거의 새 프롬프트처럼 처리됨
  • prompt version을 자주 바꾸며 캐시 이점을 깨뜨림

출시 후 첫 달엔 이걸 보면 좋습니다.
왜냐하면 같은 기능인데 더 싸게 돌릴 수 있는지가 바로 보이기 때문입니다.


7. 일주일 단위로 봐야 할 질문이 다릅니다

이건 되게 현실적인 운영 팁입니다.
첫 30일이라고 해도 매주 보는 포인트가 다릅니다.

1주차: 살아 있는가

  • 서버/worker가 안정적인가
  • 401/403/429가 반복되는가
  • usage 로그가 정상적으로 쌓이는가
  • 핵심 흐름이 실제로 호출되는가

2주차: 사람들이 뭘 쓰는가

  • 가장 많이 쓰는 endpoint는 무엇인가
  • 질문 유형은 무엇인가
  • 반복 사용자가 생기는가
  • RAG source가 어떤 문서로 몰리는가

3주차: 뭐가 비싼가

  • 어떤 요청이 비용을 잡아먹는가
  • output tokens가 과도한가
  • top-k, history length, output length를 줄일 포인트가 있는가
  • cached input이 실제로 먹는가

4주차: 무엇을 고정할 것인가

  • 살아남을 핵심 기능이 무엇인가
  • 없애도 되는 기능이 무엇인가
  • 다음 달 우선순위는 무엇인가
  • 유료화/제한 정책을 붙일 준비가 됐는가

이렇게 주 단위 질문을 바꾸면, 출시 직후 혼란이 훨씬 줄어듭니다.


8. 그냥 감으로 운영하지 않게 해주는 로그 분석 코드

이번 글에는 실행 가능한 코드도 꼭 넣겠습니다.
출시 후 첫 30일 로그를 아주 단순하게라도 분석해보는 스크립트입니다.

가정: JSON Lines 로그 파일이 있고, 각 줄에 아래 같은 데이터가 있다고 해보겠습니다.

  • endpoint
  • latency_ms
  • input_tokens
  • output_tokens
  • cached_input_tokens
  • status
  • rag_enabled
  • user_id

실행 가능한 예제 코드

import json
from collections import Counter, defaultdict
from pathlib import Path
from statistics import mean


def load_jsonl(path: str) -> list[dict]:
    rows: list[dict] = []
    for line in Path(path).read_text(encoding="utf-8").splitlines():
        line = line.strip()
        if not line:
            continue
        rows.append(json.loads(line))
    return rows


def p95(values: list[int]) -> int:
    if not values:
        return 0
    values = sorted(values)
    index = int(len(values) * 0.95) - 1
    index = max(0, min(index, len(values) - 1))
    return values[index]


def analyze(rows: list[dict]) -> None:
    by_endpoint: dict[str, list[dict]] = defaultdict(list)
    users_per_endpoint: dict[str, Counter] = defaultdict(Counter)

    for row in rows:
        endpoint = row.get("endpoint", "unknown")
        by_endpoint[endpoint].append(row)

        user_id = row.get("user_id")
        if user_id:
            users_per_endpoint[endpoint][user_id] += 1

    print("=== Endpoint Summary ===")
    for endpoint, items in by_endpoint.items():
        latencies = [int(i.get("latency_ms", 0)) for i in items]
        input_tokens = [int(i.get("input_tokens", 0)) for i in items]
        output_tokens = [int(i.get("output_tokens", 0)) for i in items]
        cached_tokens = [int(i.get("cached_input_tokens", 0)) for i in items]
        failures = [i for i in items if i.get("status") != "succeeded"]

        repeated_users = sum(1 for _, count in users_per_endpoint[endpoint].items() if count >= 2)

        print(f"\n[{endpoint}]")
        print(f"- requests: {len(items)}")
        print(f"- avg_latency_ms: {round(mean(latencies), 2) if latencies else 0}")
        print(f"- p95_latency_ms: {p95(latencies)}")
        print(f"- avg_input_tokens: {round(mean(input_tokens), 2) if input_tokens else 0}")
        print(f"- avg_output_tokens: {round(mean(output_tokens), 2) if output_tokens else 0}")
        print(f"- avg_cached_input_tokens: {round(mean(cached_tokens), 2) if cached_tokens else 0}")
        print(f"- failures: {len(failures)}")
        print(f"- repeated_users(2+): {repeated_users}")

    print("\n=== Top Error Types ===")
    error_counter = Counter()
    for row in rows:
        if row.get("status") != "succeeded":
            error_type = row.get("error_type", "unknown")
            error_counter[error_type] += 1

    for error_type, count in error_counter.most_common(10):
        print(f"- {error_type}: {count}")


if __name__ == "__main__":
    # 예: python post_launch_analysis.py
    rows = load_jsonl("openai_requests.jsonl")
    analyze(rows)

실행 방법

python post_launch_analysis.py

예상 결과

=== Endpoint Summary ===

[/chat]
- requests: 320
- avg_latency_ms: 1180.23
- p95_latency_ms: 2840
- avg_input_tokens: 215.42
- avg_output_tokens: 168.55
- avg_cached_input_tokens: 42.1
- failures: 3
- repeated_users(2+): 27

[/rag-chat]
- requests: 141
- avg_latency_ms: 2389.77
- p95_latency_ms: 6110
- avg_input_tokens: 1298.2
- avg_output_tokens: 201.4
- avg_cached_input_tokens: 15.3
- failures: 9
- repeated_users(2+): 11

=== Top Error Types ===
- RateLimitError: 6
- ValidationError: 3
- TimeoutError: 2

이 정도만 봐도 꽤 보입니다.

  • /rag-chat가 훨씬 비싸고 느리네
  • caching은 /chat에서만 좀 먹고 있네
  • repeated users는 /chat가 더 많네
  • 지금 먼저 고칠 건 /rag-chat의 latency와 429 대응이겠네

이게 바로 첫 30일에 필요한 감각입니다.


9. 첫 30일에 “고쳐야 할 것”과 “참아도 되는 것”을 나눠야 합니다

출시 후엔 문제를 많이 발견하게 됩니다.
문제는 그걸 다 바로 고치려 하면 또 우선순위가 무너진다는 거예요.

지금 바로 고쳐야 하는 것

  • 401/403 같은 키/권한 문제
  • 429가 반복되는 rate limit 문제
  • prod/staging 리소스 혼선
  • worker 적체
  • usage 로그 누락
  • docs/secret 노출 같은 보안 이슈

당장 참아도 되는 것

  • UI가 약간 덜 예쁜 것
  • 프롬프트 문구의 미세한 톤 차이
  • 드물게만 쓰는 기능의 작은 불편
  • 소수 edge case의 비핵심 오류

이 구분이 중요합니다.
출시 직후엔 “모든 문제를 고친다”보다
핵심 흐름을 안정화한다가 먼저입니다.


10. 첫 30일이 지나면 반드시 정리해야 할 문서

이건 기술보다 운영 습관에 가깝습니다.

출시 후 첫 달이 끝나면 최소한 이건 정리해두는 게 좋습니다.

  • 가장 많이 쓰는 endpoint
  • 가장 비싼 endpoint
  • 가장 자주 나는 에러
  • 가장 많이 쓰는 질문 유형
  • 대표 성공 사례
  • 대표 실패 사례
  • 다음 달 우선순위

이걸 문서로 남기면 훨씬 좋아집니다.
그다음부터는 감이 아니라 “지난달 데이터 기준”으로 이야기할 수 있으니까요.


FAQ

Q. 출시 후 첫 30일에 기능 추가를 아예 멈춰야 하나요?

완전히 멈출 필요는 없지만, 핵심 흐름 관찰이 우선입니다.
특히 첫 달엔 새 기능을 3개 붙이는 것보다 usage, latency, error pattern을 보는 편이 훨씬 값집니다.

Q. OpenAI 서비스는 첫 달에 비용을 어디서 가장 많이 줄일 수 있나요?

보통은 이 셋에서 먼저 보입니다.

  • output 길이
  • RAG chunk 수 / history 길이
  • prompt caching이 깨지는 구조

OpenAI cost optimization과 prompt caching 문서도 이 방향과 잘 맞습니다. (OpenAI 개발자)

Q. RAG 서비스는 출시 후 어떤 지표를 꼭 봐야 하나요?

최소한 아래는 추천합니다.

  • retrieved chunk 수
  • source 다양성
  • retrieval latency
  • fallback 비율
  • 반복 사용률
  • input tokens 증가 추세

Q. 아직 사용자가 적은데도 이런 걸 다 봐야 하나요?

네. 오히려 사용자가 적을 때 보는 게 더 좋습니다.
이때는 로그와 지표를 읽기가 쉽고, 구조를 바꾸기도 덜 아프기 때문입니다.


핵심 요약

  • 출시 후 첫 30일은 기능 추가보다 반복 사용, 비용, latency, 오류, RAG 검색 상태를 보는 시기입니다.
  • OpenAI는 운영 단계에서 production best practices, cost optimization, latency optimization, prompt caching, rate limits를 따로 다루고 있습니다. (OpenAI 개발자)
  • 첫 달엔 request 수보다 반복 사용률이 더 중요한 신호일 때가 많습니다.
  • 평균 latency보다 p95가 더 현실적인 운영 지표입니다.
  • RAG는 모델 output만 보지 말고 retrieval 상태를 먼저 봐야 합니다.
  • usage 로그가 없으면 운영은 거의 감으로 하게 됩니다.

출처

  • OpenAI Production best practices — 운영 단계에서 보안, 비용, 운영 구조를 함께 보라고 안내. (OpenAI 개발자)
  • OpenAI Cost optimization — 모델 선택, 토큰 구조, 비용 절감 방향 설명. (OpenAI 개발자)
  • OpenAI Latency optimization — latency 최적화 원칙 설명. (OpenAI 개발자)
  • OpenAI Evaluation best practices — representative 사례와 반복 평가 중요성 설명. (OpenAI 개발자)
  • OpenAI Prompt caching — 반복 prefix가 있을 때 비용과 latency를 줄이는 구조 설명. (OpenAI 개발자)
  • OpenAI Rate limits — 요청/토큰 제한과 rate limit 이해 가이드. (OpenAI 개발자)
  • 올려주신 “AI 검색에 잘 걸리는 글” 문서 스타일 참고.

Python, OpenAI, FastAPI, 출시 후 운영, OpenAI 운영 지표, usage logging, prompt caching, latency optimization, cost optimization, RAG 운영, rate limits, AI 백엔드 운영, 주니어 개발자, SaaS 초기 운영, OpenAI MVP

※ 이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/06   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함
반응형