Tencent Cloud AIGC API를 한 곳에서: MPaaS AIGC Playground 구축기
Tencent Cloud MPaaS AIGC API의 LLM Chat, 이미지 생성, 영상 생성을 단일 웹앱에서 테스트하고, LiteLLM 기반으로 토큰별 사용량을 추적하는 데모 도구의 설계와 구현을 정리합니다.
왜 만들었나
Tencent Cloud MPaaS가 제공하는 AIGC API는 텍스트(LLM Chat), 이미지 생성, 영상 생성까지 폭넓은 모달리티를 지원합니다. 그런데 실제로 이 API들을 팀에서 평가하거나 데모로 보여주려면, 매번 curl을 치거나 Postman 컬렉션을 돌려가며 쓰는 방식이 반복됐습니다.
특히 이런 점들이 불편했습니다.
- 키 관리가 번거롭다 — Tencent SecretKey와 AIGC API Token을 개발자마다 로컬에 들고 있다 보니, 누가 어떤 키로 얼마나 호출했는지 파악할 방법이 없었습니다.
- 멀티모달 테스트가 파편화돼 있다 — 텍스트는 OpenAI-compatible endpoint, 이미지·영상은 MPS API인데 인증 방식도 달라서, 하나로 묶어 비교할 수 있는 도구가 없었습니다.
- 비용 감이 안 잡힌다 — 어떤 모델에, 어떤 사용자가, 얼마나 토큰을 소비했는지 한눈에 보고 싶었습니다.
그래서 브라우저 하나면 LLM Chat · 이미지 생성 · 영상 생성을 다 테스트할 수 있고, 토큰별 사용량까지 자동으로 기록하는 "AIGC Playground"를 직접 만들게 됐습니다.
전체 아키텍처
┌──────────────────────────────────────────────────────────────┐
│ Browser (Static Frontend) │
│ ┌──────────┐ ┌───────────────┐ ┌───────────────────────┐ │
│ │ LLM Chat │ │ Image Gen │ │ Video Gen │ │
│ │ │ │ │ │ │ │
│ └────┬─────┘ └──────┬────────┘ └──────────┬────────────┘ │
│ │ │ │ │
│ └───────────────┼──────────────────────┘ │
│ │ /api/* │
└───────────────────────┼─────────────────────────────────────┘
▼
┌──────────────────────────────────────────────────────────────┐
│ FastAPI Backend (app.py) │
│ │
│ ┌─────────────────┐ ┌──────────────┐ ┌────────────────┐ │
│ │ Token Admin │ │ Usage Stats │ │ COS Bucket │ │
│ │ CRUD + Registry │ │ SQLite │ │ Selection │ │
│ └────────┬────────┘ └──────┬───────┘ └───────┬────────┘ │
│ │ │ │ │
└───────────┼──────────────────┼───────────────────┼───────────┘
│ │ │
▼ ▼ ▼
┌────────────────┐ ┌──────────────┐ ┌──────────────────────┐
│ Tencent VOD │ │ Tencent MPS │ │ Tencent COS │
│ AIGC Token API │ │ Image/Video │ │ Output Storage │
│ Text AIGC EP │ │ Task API │ │ │
└────────────────┘ └──────────────┘ └──────────────────────┘
설계할 때 잡은 원칙은 세 가지입니다.
첫째, 프론트엔드에 비밀 키를 절대 노출하지 않는다. 모든 Tencent API 호출은 FastAPI 백엔드를 경유합니다. 브라우저에는 SecretKey도, AIGC API Token도 내려가지 않습니다.
둘째, 프론트엔드는 100% 정적 파일로 배포 가능하게 한다. public/ 디렉토리를 그대로 S3(또는 COS)에 올리면 프론트가 동작하고, /api/* 경로만 백엔드 origin으로 프록시하면 됩니다. EdgeOne + COS 조합이면 CDN 배포도 간단합니다.
셋째, 호출 한 건마다 누가, 어떤 모델로, 얼마나 썼는지를 기록한다. SQLite 하나로 가볍게, 대신 빠짐없이.
멀티모달 AIGC 통합: 하나의 UI, 세 가지 모달리티
LLM Chat — OpenAI & Claude Compatible
Tencent Cloud MPaaS의 텍스트 AIGC는 두 가지 호환 endpoint를 제공합니다.
| Endpoint | 호환 형식 | 용도 |
|---|---|---|
/v1/chat/completions |
OpenAI-compatible | GPT 계열 모델 호출 |
/v1/messages |
Claude-compatible | Claude 계열 모델 호출 |
백엔드의 /api/chat/completions가 프론트에서 선택한 모델 타입에 따라 적절한 Tencent endpoint로 라우팅하는 구조입니다. 사용자는 모델만 고르면 됩니다.
Image Generation — 비동기 태스크 패턴
이미지 생성은 Tencent MPS의 CreateAigcImageTask → DescribeAigcImageTask 흐름을 따릅니다. 요청을 보내면 TaskId가 반환되고, 폴링으로 결과를 확인하는 비동기 패턴입니다. 프론트에서 이 폴링을 자동 처리하기 때문에, 사용자 입장에서는 프롬프트만 입력하고 결과 이미지를 기다리면 됩니다.
Video Generation — 동일한 비동기 패턴
영상 생성도 CreateAigcVideoTask → DescribeAigcVideoTask로 같은 패턴입니다. 이미지 생성보다 시간이 더 걸리지만, UI 흐름은 동일하게 가져갔습니다.
COS Storage 연동
이미지/영상 생성 결과물을 Tencent COS Bucket에 저장하는 옵션도 넣었습니다. StoreCosParam을 요청에 포함하면 결과물이 지정된 버킷 경로(/aigc-output/images/ 또는 /aigc-output/videos/)에 자동 저장됩니다. 선택하지 않으면 광저우 리전 임시 스토리지에 보관되는데, 데모 용도라면 그것으로 충분합니다.
토큰 관리와 사용량 추적
이 프로젝트에서 가장 공을 들인 부분이 토큰별 사용량 추적입니다.
Token Admin
Tencent의 AIGC API Token 관리 API(CreateAigcApiToken, DescribeAigcApiTokens, DeleteAigcApiToken)를 래핑해서, UI에서 토큰을 생성·조회·삭제할 수 있게 만들었습니다.
한 가지 아쉬운 점은, Tencent의 토큰 목록 API가 username 필드를 반환하지 않는다는 것입니다. 그래서 로컬에 aigc_token_registry.json을 두고 username ↔ api_token 매핑을 직접 관리하는 방식으로 풀었습니다. 토큰 생성 시 username을 입력받아 이 레지스트리에 기록해두고, 이후 사용량 기록에서 해당 username으로 귀속시킵니다.
Usage Stats — SQLite 기반 경량 추적
모든 API 호출 결과를 aigc_usage.sqlite3에 기록합니다. 저장 항목은 다음과 같습니다.
- username — 어떤 사용자의 호출인지
- token preview — 어떤 토큰으로 호출했는지 (전체 토큰은 저장하지 않음)
- modality —
llm,image,video중 어느 모달리티인지 - model — 어떤 모델을 사용했는지
- success / status code — 성공 여부
- latency — 응답 시간
- token usage — LLM의 경우 input/output 토큰 수
- timestamp — 호출 시각
이 데이터를 바탕으로 /api/usage/summary에서는 사용자별·모달리티별 요약을, /api/usage/events에서는 개별 호출 이력을 확인할 수 있습니다.
LLM Chat의 경우에는 LiteLLM을 활용해 토큰 사용량을 파싱합니다. LiteLLM이 OpenAI-compatible 응답에서 prompt_tokens, completion_tokens 등을 추출해주기 때문에, 이걸 SQLite에 기록하면 어떤 사용자가 어떤 모델로 하루에 몇 토큰을 썼는지 바로 확인할 수 있습니다.
보안 설계: 프론트엔드에 키를 노출하지 않기
데모용 도구라도 키 관리에서는 타협하지 않았습니다.
문제: Tencent API를 호출하려면 SecretId/SecretKey(TC3 인증)와 AIGC API Token(Bearer 인증)이 필요합니다. 이걸 프론트에서 직접 쓰면 브라우저 DevTools만 열어도 키가 노출됩니다.
해결: 모든 Tencent API 호출을 FastAPI 백엔드를 통해 프록시하는 구조로 잡았습니다.
- LLM Chat: 프론트에서
/api/chat/completions를 호출하면, 백엔드가 Active User Token을 Bearer로 달아서 Tencent text-aigc endpoint에 전달합니다. - Image/Video 생성: MPS API는 TC3 서명 인증을 쓰는데, 서명 생성은 전부 백엔드에서 처리합니다.
- COS Bucket 조회: COS API 호출에 필요한 서명도 백엔드가 생성합니다.
결과적으로 프론트는 순수하게 /api/*만 호출하고, 실제 Tencent 인증 정보는 서버의 .env에만 존재합니다.
배포 구조
프론트와 백엔드를 분리 배포할 수 있도록 설계했습니다.
https://demo.example.com/ → EdgeOne / COS (정적 프론트)
https://demo.example.com/api/* → FastAPI backend origin
정적 프론트: public/ 디렉토리의 index.html, app.js, styles.css를 그대로 COS에 올리면 됩니다. CDN(EdgeOne) 뒤에 두면 글로벌 서빙도 가능합니다.
백엔드: FastAPI 서버를 별도로 띄우고, /api/* 경로만 프록시하면 됩니다. uvicorn app:app --host 0.0.0.0 --port 8080으로 실행하면 끝입니다.
로컬 개발할 때는 FastAPI가 public/까지 서빙하기 때문에 http://127.0.0.1:8080 하나로 전부 동작합니다.
개발하면서 배운 것들
1. Tencent TC3 서명은 생각보다 까다롭다
AWS Signature V4와 비슷한 구조인데, 세부 포맷이 미묘하게 다릅니다. 특히 X-TC-Action, X-TC-Timestamp 같은 커스텀 헤더를 정확히 맞춰야 하는데, 한 글자라도 틀리면 AuthFailure.SignatureFailure가 돌아옵니다. 디버깅이 힘들어서 Debug View에 Request/Response를 누적으로 보여주는 기능을 넣었는데, 서명 문제를 잡는 데 꽤 도움이 됐습니다.
2. 비동기 태스크의 폴링 UX
이미지·영상 생성은 비동기 태스크 방식이라 결과를 받으려면 DescribeAigcImageTask를 반복 호출해야 합니다. 처음에는 단순한 setInterval로 구현했지만, 태스크가 실패하거나 오래 걸리는 경우에 대한 처리가 필요했습니다. 최종적으로는 최대 폴링 횟수 제한 + 지수 백오프 + 상태 표시를 조합하는 방식으로 정리했습니다.
3. 토큰 레지스트리의 한계와 트레이드오프
Tencent API가 username을 반환하지 않는 이상 로컬 레지스트리에 의존할 수밖에 없습니다. 이 파일이 유실되면 토큰-사용자 매핑이 깨지는 문제가 있는데, 프로덕션이라면 DB에 넣겠지만 데모 도구의 범위에서는 JSON 파일로 충분하다고 판단했습니다.
마무리
이 프로젝트의 핵심 가치는 세 가지로 정리됩니다.
멀티모달 통합 — 텍스트, 이미지, 영상 생성을 하나의 UI에서 테스트하고 비교할 수 있습니다. API 호출 방식이 각각 다르지만 사용자 경험은 통일했습니다.
사용량 가시성 — 누가, 어떤 모델로, 얼마나 사용했는지를 토큰 단위로 추적합니다. 팀 내 비용 관리나 사용 패턴 분석의 기초 데이터가 됩니다.
보안과 편의의 균형 — 데모 도구이지만 키 노출은 원천 차단했고, 정적 프론트 + API 백엔드 분리로 배포 유연성도 확보했습니다.
전체 코드가 FastAPI 백엔드 하나와 정적 프론트엔드 파일 몇 개로 구성돼 있으니, 비슷한 AIGC API Playground를 만들어보려는 분들께 참고가 됐으면 합니다.
이 글에서 다루는 코드는 데모 목적으로 작성되었으며, 프로덕션 환경에서는 추가적인 인증·인가, 에러 핸들링, 스케일링 고려가 필요합니다.