소개
시도하고자 했던 것과 그 이유를 알려주세요.
다양한 이미지 및 동영상 생성 AI 모델(Gemini
nanobanana2,veo3.1, OpenAIgpt-image-2등)을 API로 연동하여 서비스하는 플랫폼을 개발하고 있습니다.서비스 규모가 커지면서 두 가지 병목이 발생했습니다.
첫째, 프로바이더마다 API 문서(Docs) 양식과 파라미터 규격이 제각각이라 명확한 스펙을 파악하고 관리하기가 너무 어려웠습니다.
둘째, 모델과 옵션의 조합이 기하급수적으로 늘어나다 보니 일일이 모든 케이스를 수동으로 테스트하는 비용과 시간 부담이 감당할 수 없을 정도로 커졌습니다.
이런 부분은 모델 적용 후 사용자들에게 불편을 주게 되며 규모가 커질수록 중첩되며 큰 부담감으로 다가왔습니다.여러 AI 이미지 생성 API 문서(OpenAI gpt-image-2, Gemini nanobanana2 등)를 분석하고, 분석된 사양을 기반으로 프론트엔드 동적 입력 폼을 실시간으로 렌더링하며, 사용자가 값을 입력했을 때 백엔드 Zod 엔진을 통해 즉각 매개변수 유효성을 가상 검증하는 무비용(Zero-Cost) 파이프라인을 구축을 구축하고 싶어서 이번 실험을 시도했습니다.
진행 방법
어떤 도구를 사용했고, 어떻게 활용하셨나요?
React 19 (TypeScript), Vite, Express (Node.js), Zod, Gemini 2.5 Flash API
Tip: 사용한 프롬프트 전문을 꼭 포함하고, 내용을 짧게 소개해 주세요.
너는 입력된 AI 모델의 API 레퍼런스 문서를 분석해 프론트엔드 동적 폼 생성용 메타데이터를 출력하는 오케스트레이터다. 마크다운 같은 부가 설명 없이 오직 아래 지정된 순수 JSON 포맷으로만 응답해라.
[요구사항]
1. 이미지 생성에 필요한 필수 옵션인 경우 required: true로 지정하고, 선택 옵션은 required: false로 지정해라.
2. 각 필드의 데이터 성격에 따라 type을 지정하되, 선택지가 고정된 경우 enum 타입과 options 배열을 제공해라.
3. type은 반드시 'string' | 'number' | 'boolean' | 'enum' 중 하나여야 한다.
4. description은 해당 필드에 대한 한글 설명을 명확하게 작성해라.
[출력 JSON 포맷]
{
"fields": {
"필드명": {
"type": "string" | "number" | "boolean" | "enum",
"required": true | false,
"options": ["enum일 경우에만 가용한 문자열 배열 제공"],
"description": "해당 필드에 대한 한글 설명"
}
}
}
Tip: 활용 이미지나 캡처 화면을 꼭 남겨주세요.
모바일 장치의 설정 스크린샷
Tip: 코드 전문은 코드블록에 감싸서 작성해주세요. ( / 을 눌러 '코드 블록'을 선택)
동적 Zod 빌드 구현 핵심 코드
// server/src/registry.ts 중 일부
public register(modelName: string, fields: Record<string, FieldMeta>): void {
const zodShape: Record<string, any> = {};
for (const [key, info] of Object.entries(fields)) {
let baseType: any;
switch (info.type) {
case 'number':
baseType = z.number({
invalid_type_error: `${key} must be a number`,
required_error: `${key} is required`
});
break;
case 'boolean':
baseType = z.boolean({
invalid_type_error: `${key} must be a boolean`,
required_error: `${key} is required`
});
break;
case 'enum':
if (info.options && info.options.length > 0) {
const [first, ...rest] = info.options;
baseType = z.enum([first, ...rest] as [string, ...string[]], {
invalid_type_error: `${key} must be one of: ${info.options.join(', ')}`,
required_error: `${key} is required`
});
} else {
baseType = z.string({ required_error: `${key} is required` });
}
break;
case 'string':
default:
baseType = z.string({
invalid_type_error: `${key} must be a string`,
required_error: `${key} is required`
});
if (info.required) {
baseType = baseType.min(1, { message: `${key} is required` });
}
break;
}
zodShape[key] = info.required
? baseType
: baseType.optional().nullable();
}
this.registry[modelName] = {
schema: z.object(zodShape),
meta: fields
};
}
결과와 배운 점
배운 점과 나만의 꿀팁을 알려주세요.
Zod의 발견: 컴파일 타임을 넘어 런타임 방어선 구축
외부 프로바이더의 파편화된 규격에 우리 서비스 로직이 종속되지 않도록, 들어오는 길목에 Zod라는 독립적인 검문소 레이어를 두는 설계 방식이 아키텍처 안정성을 확보하는 것.Zod의 기능: 비용 0원의 완벽한 가상 테스트 엔진
실제 이미지 생성 API를 단 한 번도 호출하지 않고도 데이터 구조 단계에서 오류를 즉시 잡아내어, 잘못된 요청으로 인한 외부 인프라 비용 결제를 원천 차단하는 강력한 방어선 역할
과정 중에 어떤 시행착오를 겪었나요?
모델명 불일치 해소: 커스텀 모델(예: gpt-image-2)을 추가해도 내장 프리셋에 정의된 옵션(dall-e-3, dall-e-2)이 강제로 주입되던 오류가 있었습니다. 백엔드 취합 로직에서 modelName을 매개변수로 수신하여, 스펙 내의 model ENUM 필드에 생성한 모델 이름을 검증 대상 목록 최상단에 자동으로 넣어주도록 보강했습니다. 다만 AI와의 대화로 수정된 거라.. ^^
도움이 필요한 부분이 있나요?
한 가지의 모델을 주로 질답 형식으로 진행을 하고 있는데, 여러 모델이 상화보완(티키타카)하면서 한 번의 질의나 계획 문서에 대해서 각 모델들이 구현하는 부분과 혹시 이런 경우 오픈클로 또는 헤르메스을 활용하는 방법이 있을까요?
앞 으로의 계획이 있다면 들려주세요.
단순 이미지 생성 파라미터 외에도 비디오 생성 API 문서, 멀티모달 텍스트 생성 API의 JSON 규격 분석으로 영역을 확장해 나가며 만능 zero-cost 유효성 검증 플랫폼으로 스케일업할 예정입니다.
도움 받은 글 (옵션)
Zod Schema dynamic shape creation 공식 레퍼런스 가이드