Playground Studio (한국어)
Playground Studio는 /dashboard/playground를 단순한 Monaco 기반 편집기에서
모든 기능을 갖춘 테스트 워크스페이스로 전환합니다. 기존 page.tsx를 네 개의 탭과 공유 구성 창을 렌더링하는 PlaygroundStudio
셸로 대체합니다.
┌ Playground ──────────────────────────────────────────────────────────┐│ [💬 채팅] [⚖ 비교] [{} API] [🔧 빌드] 142↑ 38↓ · $0.002 </>│├──────────────────────────────────────────┬───────────────────────────┤│ {활성 탭 콘텐츠} │ ─ 구성 ││ │ 엔드포인트 [chat ∨] ││ │ 모델 [gpt-5.4 ∨] ││ │ 시스템 [텍스트 영역] ││ │ 온도 ▕▕▔▔ 0.7 ││ │ 프리셋 [▾ 불러오기][저장] ││ │ [✨ 프롬프트 개선] │└──────────────────────────────────────────┴───────────────────────────┘채팅 탭
섹션 제목: “채팅 탭”ChatPlayground.tsx를 멀티턴 스트리밍 워크벤치로 발전시킵니다.
MarkdownMessage.tsx를 통한 완전한 마크다운 렌더링(코드 블록, 표, 목록, 링크).- 공유 구성 창에서 시스템 프롬프트를 가져옵니다.
- 메시지별 토큰/비용(프롬프트 + 완성 토큰).
- 마지막 응답 다시 생성.
- SSE 스트리밍을 사용하여
POST /v1/chat/completions로 전송합니다.
비교 탭
섹션 제목: “비교 탭”프록시의 핵심 차별점: 하나의 프롬프트를 최대 4개 모델에서 병렬로 실행합니다.
- 최대 4개의 열에서 각각
/v1/chat/completions의 응답을 독립적으로 스트리밍합니다. - 열을 추가하는
+ 모델 추가버튼(Cmd+K 단축키). 모두 실행 ▶은Promise.all과 열별AbortController를 통해 모든 스트림을 동시에 시작합니다.- 전역 모두 취소는 진행 중인 모든 스트림을 중단합니다.
- 열별
ProviderMetrics는 TTFT, TPS, 토큰 및 예상 비용을 실시간으로 표시합니다. - 메트릭에는 “클라이언트 측 추정치”(D12)라는 레이블이 지정되며, 첫 번째 SSE 청크부터 측정됩니다.
API 탭
섹션 제목: “API 탭”고급 사용자를 위해 기존 Monaco 편집기의 기능을 100% 유지합니다(D14).
- 10개 엔드포인트: 채팅 완성, 완성, 임베딩, 이미지, 오디오, 음성, 전사, 조정, 재순위 지정, 검색.
- 멀티모달 파일 업로드.
- 실시간 출력을 지원하는 SSE 스트리밍.
ApiTab.tsx로 래핑됩니다(지연 로드,ssr: false).
빌드 탭
섹션 제목: “빌드 탭”도구/함수 호출 및 구조화된 출력 UI:
ToolsBuilder.tsx— 도구별 JSON 스키마 편집기를 사용하여tools[]를 추가/편집/제거합니다.ToolDefinitionSchema(Zod)를 통해 매개변수를 검증합니다.StructuredOutputEditor.tsx— JSON 모드 및 JSON 스키마 편집기를 전환합니다.StructuredOutputSchema(Zod)를 통해 응답이 스키마를 준수하는지 검증합니다.tools[]및/또는response_format과 함께 요청을/v1/chat/completions로 전송합니다.
구성 창(공유)
섹션 제목: “구성 창(공유)”StudioConfigPane.tsx — 항상 표시되며 접을 수 있습니다.
| 필드 | 컴포넌트 | 참고 |
|---|---|---|
| 엔드포인트 | <select> |
PlaygroundEndpoint와 일치하는 10개 옵션 |
| 모델 | <input> |
자유 텍스트(예: openai/gpt-4o) |
| 시스템 프롬프트 | <textarea> |
모든 탭에 전달됨 |
| 매개변수 | ParamSliders |
temperature, max_tokens, top_p, presence/frequency penalty, seed, stop |
| 프리셋 | PresetPicker |
이름이 지정된 구성 스냅샷 불러오기/저장하기(DB에 영구 저장) |
| 프롬프트 개선 | ImprovePromptButton |
할당량 경고 모달을 열고 /api/playground/improve-prompt 호출 |
상태는 PlaygroundStudio.tsx로 끌어올려져 모든 탭에 전달됩니다. 탭을 전환해도
구성 상태가 유지됩니다.
상단 바
섹션 제목: “상단 바”StudioTopBar.tsx:
- 탭 전환기(role=“tablist”).
TokenCostCounter— 실시간 토큰(↑/↓) 및 예상 비용 표시.- 코드 내보내기 버튼(
</>) —ExportCodeModal을 엽니다.
코드 내보내기 모달
섹션 제목: “코드 내보내기 모달”ExportCodeModal.tsx는 codeExport.ts를 사용하여 현재 PlaygroundState에서 curl / Python / TypeScript 스니펫을
생성합니다. API 키 자리표시자는 항상 $OMNIROUTE_API_KEY입니다(D11).
프롬프트 개선기
섹션 제목: “프롬프트 개선기”ImprovePromptButton.tsx → useImprovePrompt.ts → POST /api/playground/improve-prompt:
- 모달에서 “할당량을 소모합니다”라고 경고합니다.
- 확인하면
{ system, prompt, model, tone }을 라우트로 전송합니다. - 라우트는 내부적으로
promptImprover.META_SYSTEM_PROMPT와 함께/v1/chat/completions를 호출합니다. { improvedSystem?, improvedPrompt?, tokensIn, tokensOut }을 반환합니다.- UI는 구성 창의 시스템 프롬프트와 채팅 탭의 사용자 프롬프트를 패치합니다.
프리셋
섹션 제목: “프리셋”PresetPicker.tsx → usePresets.ts → /api/playground/presets/*:
playground_presetsSQLite 테이블에 저장됩니다(마이그레이션084_playground_presets.sql).- 각 프리셋은
name,endpoint,model,system,params_json,created_at을 저장합니다. - CRUD:
GET목록 조회,POST생성,GET /:id,PUT /:id,DELETE /:id.
스트림 메트릭
섹션 제목: “스트림 메트릭”useStreamMetrics.ts + streamMetrics.ts(순수 함수):
start()— 요청 시작 시간을 기록합니다.onFirstChunk()— TTFT를 기록합니다.onChunk(n)— 완료 토큰 수를 누적합니다.finish(usage?)— 최종 메트릭인ttftMs,totalMs,tps,tokensIn,tokensOut,costUsd를 계산합니다.- 가격 정보는
src/lib/playground/types.ts의 정적 테이블에서 가져옵니다(“estimated”로 표시 — D13).
백엔드 라우트
섹션 제목: “백엔드 라우트”| 메서드 | 경로 | 핸들러 |
|---|---|---|
POST |
/api/playground/improve-prompt |
ImprovePromptRequestSchema으로 Zod 검증 후 메타 프롬프트와 함께 /v1/chat/completions 호출 |
GET |
/api/playground/presets |
{ presets: PlaygroundPresetListItem[] } 반환 |
POST |
/api/playground/presets |
프리셋 생성, PlaygroundPresetCreateSchema 검증 |
GET |
/api/playground/presets/:id |
프리셋 하나 또는 404 반환 |
PUT |
/api/playground/presets/:id |
부분 업데이트 |
DELETE |
/api/playground/presets/:id |
204 |
인증: 선택 사항(REQUIRE_API_KEY). 오류는 buildErrorBody()를 통해 처리합니다(엄격 규칙 #12).
주요 파일
섹션 제목: “주요 파일”| 경로 | 용도 |
|---|---|
src/app/(dashboard)/dashboard/playground/PlaygroundStudio.tsx |
셸 컴포넌트, 탭 오케스트레이터 |
src/app/(dashboard)/dashboard/playground/components/StudioTopBar.tsx |
탭 + 카운터 + 내보내기 버튼 |
src/app/(dashboard)/dashboard/playground/components/StudioConfigPane.tsx |
공통 설정 패널 |
src/app/(dashboard)/dashboard/playground/components/tabs/ChatTab.tsx |
채팅 워크벤치 |
src/app/(dashboard)/dashboard/playground/components/tabs/CompareTab.tsx |
다중 모델 비교 |
src/app/(dashboard)/dashboard/playground/components/tabs/ApiTab.tsx |
Monaco 편집기(유지) |
src/app/(dashboard)/dashboard/playground/components/tabs/BuildTab.tsx |
도구 + 구조화된 출력 |
src/app/(dashboard)/dashboard/playground/components/ExportCodeModal.tsx |
코드 내보내기 모달 |
src/app/(dashboard)/dashboard/playground/components/CompareColumn.tsx |
개별 비교 열 |
src/app/(dashboard)/dashboard/playground/components/ProviderMetrics.tsx |
TTFT/TPS 표시 |
src/app/(dashboard)/dashboard/playground/hooks/useStreamMetrics.ts |
클라이언트 측 메트릭 훅 |
src/app/(dashboard)/dashboard/playground/hooks/usePresets.ts |
프리셋 CRUD 훅 |
src/app/(dashboard)/dashboard/playground/hooks/useImprovePrompt.ts |
프롬프트 개선 훅 |
src/lib/playground/codeExport.ts |
curl/Python/TS 생성기(Search Tools와 공유) |
src/lib/playground/promptImprover.ts |
메타 프롬프트 빌더 |
src/lib/playground/streamMetrics.ts |
순수 메트릭 계산 |
src/lib/db/playgroundPresets.ts |
DB 모듈(CRUD) |
src/app/api/playground/improve-prompt/route.ts |
프롬프트 개선 REST 라우트 |
src/app/api/playground/presets/route.ts |
프리셋 목록 조회 + 생성 |
src/app/api/playground/presets/[id]/route.ts |
프리셋 조회/업데이트/삭제 |
src/lib/db/migrations/084_playground_presets.sql |
DB 마이그레이션 |
문제 해결
섹션 제목: “문제 해결”| 증상 | 원인 | 해결 방법 |
|---|---|---|
| API 탭에서 Monaco 편집기가 렌더링되지 않음 | SSR에서 Monaco를 로드함 | ApiTab이 dynamic(..., { ssr: false })를 사용하는지 확인 |
| 비교 스트림이 순차적으로 실행됨 | 잘못된 Promise.all 사용 |
모든 스트림 시작 작업을 하나의 Promise.all 호출에서 디스패치해야 함 |
메트릭에 null TTFT가 표시됨 |
첫 번째 청크 핸들러가 연결되지 않음 | SSE 리더 루프에서 useStreamMetrics.onFirstChunk()가 호출되는지 확인 |
| 프리셋이 유지되지 않음 | DB 마이그레이션이 실행되지 않음 | npm run db:migrate를 실행하거나 서버를 재시작(시작 시 마이그레이션이 자동 실행됨) |
| 프롬프트 개선 시 502가 반환됨 | Config에서 모델이 설정되지 않음 | 개선하기 전에 사용자가 Config 창에 모델 이름을 입력해야 함 |
내보낸 코드에 MISSING_API_KEY가 표시됨 |
자리표시자가 삽입되지 않음 | codeExport.ts는 항상 API_KEY_PLACEHOLDER = "$OMNIROUTE_API_KEY"를 사용 |
참고 자료
섹션 제목: “참고 자료”- 마스터 계획:
_tasks/features-v3.8.6/refactorpages/_orchestration/master-plan-group-C.md - 기능 계획:
_tasks/features-v3.8.6/refactorpages/17-playground-studio-redesign.plan.md - 코드 내보내기:
src/lib/playground/codeExport.ts - 프롬프트 개선기:
src/lib/playground/promptImprover.ts - Search Tools Studio:
docs/frameworks/SEARCH_TOOLS_STUDIO.md
HagiCode
HagiCode는 구조화된 워크플로, 다중 에이전트 실행, Hero Dungeon 뷰를 갖춘 에이전트 코딩 작업 공간입니다.
더 스마트하고 빠르며 즐거운 에이전트 워크플로로 유용한 소프트웨어를 만드세요.

- Smart구조화된 워크플로는 의도를 아이디어부터 배포까지 실행 가능한 경로로 바꿉니다.
- Efficient다중 에이전트 워크플로로 조사, 구현, 검토를 병렬로 진행합니다.
- FunHero Dungeon은 긴 코딩 세션을 시각적이고 협업적인 경험으로 만듭니다.