AI로 30초 만에 어떤 퀴즈든 만들기 — 그리고 이를 출시하기까지 걸린 세 번의 시도
요약
작성자는 자녀의 퀴즈 요청을 ChatGPT로 해결하며 AI를 활용한 서비스 'Quizzy'의 아이디어를 얻었습니다. 하지만 API 비용 문제를 해결하기 위해 사용자가 직접 자신의 AI를 활용하는 'BYO-AI(Bring Your Own AI)' 모델을 시도하며 겪은 시행착오를 다룹니다.
핵심 포인트
- AI를 활용한 서비스 구축 시 API 호출 비용은 서비스의 확장성을 저해하는 주요 요인임
- 사용자에게 직접 프롬프트를 제공하고 결과(JSON)를 다시 입력받는 'BYO-AI' 방식의 경제적 이점
- 기술적 구현(JSON 파싱 등)이 일반 사용자에게는 높은 진입장벽이 될 수 있다는 사용자 경험(UX)의 중요성
파자마 파티
토요일 오후였습니다. 제 아들은 그날 밤 친구들과 파자마 파티(sleepover)를 하기로 되어 있었고, 퀴즈를 진행하고 싶어 했습니다. 저는 아들에게 퀴즈를 만드는 것을 도와주겠다고 말했었죠. 또한 파트너에게는 오후 5시까지 다른 일을 끝내겠다고 말한 상태였습니다. 이 두 가지 약속은 양립할 수 없었습니다. (전형적인 변명이라는 건 저도 압니다.) 저는 노트북 앞에 앉아 생각했습니다. '그냥 AI에게 물어보자.' 저는 ChatGPT를 열고 다음과 같이 입력했습니다: 'Minecraft 테마로 8세 아이들을 위한 10문제짜리 퀴즈를 만들어줘. 숙련된 Minecraft 플레이어만이 100점을 맞을 수 있어야 해. 어렵게 만들어줘.' 20초 후, 저는 퀴즈를 얻었습니다. 제 아들은 의심스러운 눈초리로 제 어깨 너머로 질문들을 읽고 있었습니다. "하지만 하지만 하지만 아빠 — AI가 내가 원하는 걸 어떻게 알아요?" 아들은 여덟 살이었지만, 결국 모든 프로덕트 매니저(Product Manager)가 던지게 되는 질문을 이미 던지고 있었습니다: '여기서 요구사항(requirements)을 관리하는 주체는 누구인가?' 저는 아들에게 프롬프트(prompt)를 보여주었습니다. 저는 'Minecraft'를 'Pokemon'으로 바꾸고 다시 실행했습니다. 아들은 새로운 퀴즈가 나타나는 것을 지켜보았습니다. 그는 아무 말도 하지 않았지만, 어떤 것이 마법인지 아닌지 다시 생각할 때 하는 특유의 방식으로 고개를 까딱였습니다. 그 순간 저는 생각했습니다: '이것은 Quizzy의 기능이 되어야 한다.'
비용의 벽
순진한 버전의 접근 방식은 이틀 오후 동안 작업하는 것입니다. 페이지에 양식을 만들고, 사용자의 입력을 LLM(대규모 언어 모델)으로 보내고, 결과를 렌더링(render)하는 것이죠. 문제는 청구서입니다. 만약 모든 사용자 뒤에 저의 OpenAI 키를 배치한다면, 저는 Quizzy.earth의 모든 퀴즈에 대해 비용을 지불하게 됩니다. 모든 동작이 유료 API를 호출하는 무료 제품의 경제학은 예측 가능한 방식으로 나쁩니다: 성공할수록 비용이 더 많이 듭니다. '대박이 났다'는 상황이 '나는 파산했다'는 상황이 되지 않는 버전은 없습니다. Quizzy는 이것에 대해 비용을 청구하지 않습니다. 저도 그러길 원하지 않습니다. 그래서 질문은 '어떻게 AI를 추가할 것인가?'가 아니라, '어떻게 사용자의 AI가 작업을 수행하게 하는 방식으로 AI를 추가할 것인가?'였습니다. 그것이 어려운 부분이었습니다. 저는 세 가지를 시도했습니다.
시도 1: BYO-AI 양식
첫 번째 아이디어는 당연한 것이었습니다. 주제, 난이도, 언어를 입력하는 작은 양식을 만드는 것이었습니다. 버튼을 누르면, 앱이 복사할 수 있는 프롬프트를 구성해 줍니다.
그 프롬프트를 이미 사용 중인 어떤 AI에든 붙여넣기만 하면 됩니다. ChatGPT, Claude, Gemini, 무엇이든 상관없습니다. 그러면 AI가 JSON을 내뱉습니다. 그 JSON을 다시 Quizzy에 붙여넣으면, 앱이 이를 파싱(Parsing)하여 퀴즈로 변환합니다. 이론적으로는 우아합니다. 사용자는 자신의 토큰(Token) 비용을 지불하고, 저는 아무것도 내지 않습니다. 모두가 승리하는 구조죠. 하지만 실제로는, 지구상에서 이것을 사용할 수 있는 사람은 저뿐이었습니다. 첫 번째 문제는 대부분의 사람들이 JSON이 무엇인지 모른다는 것이었습니다. 저는 사용자가 직렬화 형식(Serialization format)을 이해해야만 하는 흐름을 만들어 놓았고, 대부분의 사람은 이를 이해하지 못할 것이었습니다. 저는 그 부분을 설명하면 될 거라고 생각했습니다. 두 번째 문제는 제가 예상치 못했던 것이었으며, 제 아들이 그것을 찾아냈습니다. 저는 아들에게 노트북을 건네주며 시도해 보라고 했습니다. 아이는 Quizzy에 주제를 입력하고, 생성된 프롬프트를 복사하여 ChatGPT에 붙여넣었습니다. 그리고 AI가 타이핑을 시작하는 순간, 아이는 절반쯤 작성된 답변을 선택해 Quizzy에 다시 붙여넣었습니다. 아이는 스트리밍(Streaming)이 끝날 때까지 기다리지 않았습니다. 왜 기다려야 하죠? 아이가 사용하는 다른 모든 앱에서는 텍스트가 나타나면 작업이 완료된 것이니까요. 아이는 절반만 완성된 JSON 객체를 붙여넣고 '퀴즈 생성(Create quiz)' 버튼을 눌렀고, 에러를 마주했습니다. 아이는 저를 올려다보며 물었습니다. "내가 뭘 잘못했어?" 아이는 아무것도 잘못하지 않았습니다. 제품이 잘못한 것이었습니다. 여덟 살 아이가 이 도구로 1분 안에 퀴즈를 만들 수 없다면, 그 제품은 실패한 것입니다. 이것이 제가 첫날 Quizzy를 위해 적어두었던 규칙이었고, 저는 방금 그것이 제 눈앞에서 무너지는 것을 목격했습니다. 아이조차도 마찰(Friction) 없이 퀴즈를 만들 수 있어야 합니다. 저는 개발자를 위한 기능을 만들어 가족들에게 배포했던 것입니다.
시도 2: 마법 같은 사라짐
다음 아이디어는 생각하는 것만으로도 정말 즐거웠습니다. 만약 AI가 직접 저에게 퀴즈를 보내준다면 어떨까요? 제 머릿속의 흐름은 이랬습니다: 사용자는 고유 ID(Unique ID)가 포함된 프롬프트를 받습니다. 이를 자신의 AI에 붙여넣습니다. AI는 퀴즈를 생성하고, 해당 ID와 함께 JSON을 /api/generate-quiz로 POST 요청합니다. 제 백엔드(Backend)는 해당 ID로 Redis에 이를 저장합니다. 프론트엔드(Frontend)는 그동안 계속해서 폴링(Polling)을 하거나 웹소켓(Websocket)을 유지하며 기다립니다. ID에 불이 들어오는 순간, 퀴즈가 나타납니다. 사용자는 아무것도 할 필요가 없습니다.
사용자가 프롬프트(Prompt)를 붙여넣고, AI가 몇 초 동안 생각하는 것을 지켜본 뒤, 다시 Quizzy를 돌아보면 퀴즈가 그 자리에 놓여 있습니다. 복사도, 붙여넣기도, JSON도 필요 없습니다. 이것은 마법 같았을 것입니다. 하지만 결과적으로 대부분의 AI 에이전트(AI agents)가 임의의 URL로 POST 요청을 보내지 않기 때문에 작동하지 않았습니다. 어떤 에이전트는 이를 즉시 차단합니다. 어떤 에이전트는 사용자가 활성화하지 않은 도구(Tool)를 요구합니다. 어떤 에이전트는 조용히 거부합니다. 2026년에 작동할 버전은, 사용자가 우연히 열어둔 어떤 AI를 사용하더라도 작동하는 버전은 아닙니다. 언젠가는 가능할지도 모릅니다. 아직은 아닙니다.
시도 3: URL 밀수 (The URL smuggle)
POST가 금지되어 있다면, GET은 어떨까요? 대부분의 AI 에이전트는 요청을 받으면 URL을 "브라우징(Browse)"하거나 "검색(Search)"합니다. 그렇다면 프롬프트가 AI에게 생성된 퀴즈 전체가 쿼리 스트링(Query string)에 포함된 URL을 구성한 뒤, 그 URL을 방문하도록 명령한다면 어떨까요? 제 서버는 이전과 마찬가지로 쿼리 파라미터(Query params)에서 퀴즈를 파싱하여 Redis에 저장할 것입니다. 저는 이 버전을 구축했습니다. 거의 성공할 뻔했습니다. 하지만 두 가지 비낭만적인 이유로 실패했습니다. 첫 번째는 브라우저와 프록시(Proxy)가 URL 길이를 2k에서 8k자 사이로 제한한다는 점입니다. 각 4개의 선택지가 있는 10문제짜리 퀴즈는 아주 손쉽게 그 제한을 넘어버립니다. 두 번째는 AI의 내장 브라우징 도구들이 무엇을 유효한 URL로 간주할지에 대해 나름의 기준을 가지고 있으며, 6k자 길이의 쿼리 스트링은 그 기준에 부합하지 않았다는 점입니다. 요청은 결코 도달하지 않았습니다. DNS는 아무런 쓸모 없는 곳으로 해석되었습니다. 저는 공기를 밀수하고 있었던 셈입니다.
결국 상황은 이랬습니다. JSON을 숨길 수도 없었고, 복사-붙여넣기를 피할 수도 없었습니다. 그리고 Quizzy 트래픽의 대부분이 발생하는 모바일 환경에서는, 모든 붙여넣기가 앱 전환을 의미했습니다. Quizzy를 열고, 프롬프트를 복사하고, ChatGPT로 스와이프하여 붙여넣고, 기다린 다음, 응답을 복사하고, 다시 스와이프하여 돌아와서, 다시 붙여넣어야 합니다. 스마트폰에서의 앱 전환은 그 자체로 하나의 마찰 비용(Friction tax)이며, 다른 문제들과 달리 이 버전에서는 공학적인 방법으로 해결할 수 없었습니다. 사용자의 AI는 제 앱과 다른 앱에 있으며, 그 사이의 경로는 운영체제(OS)를 통과하기 때문입니다. 따라서 남은 질문은 더 작은 것이었습니다. 이 모든 상황이 고정된 상태에서, 기존의 흐름이 최소한 UX에 대한 처벌이 되지 않게 만들 수는 없을까?
내가 실제로 출시한 것
개발자가 아닌 사람들을 위해 무언가를 만들 때 내가 스스로에게 계속 상기시키는 사실이 있습니다. 사용자들은 당신의 제품을 원하는 것이 아닙니다. 그들은 당신의 제품이 제공하는 '무언가'를 원합니다. 사용자가 고민하지 않도록 당신이 대신 흡수할 수 있는 모든 단계가 곧 제품입니다. 나는 복사-붙여넣기 (copy-paste) 단계를 제거할 수는 없었습니다. 하지만 거의 모든 상황을 허용할 수 있게 만들 수는 있었습니다. 두 가지 변화가 대부분의 역할을 했습니다.
JSON 대신 JSONL 사용. AI에게 하나의 커다란 JSON 배열 (array)을 요청하는 대신, 한 줄당 하나의 JSON 객체 (object)를 출력하도록 요청했습니다. 이제 사용자가 부분적인 스트림 (stream) — 예를 들어 10줄 중 3줄 — 을 붙여넣더라도, 에러 대신 3개의 질문으로 구성된 퀴즈를 얻게 됩니다. 사용자의 복사는 불완전하지만, 파싱 (parse)은 유연합니다. 나타나는 퀴즈는 예상보다 조금 짧을 뿐, 빨간색 경고 배너가 뜨지는 않습니다.
그 외 모든 것을 위한 jsonrepair. 사용자들은 단순히 JSON만 붙여넣지 않습니다. 그들은 상단의 "물론이죠! 여기 퀴즈가 있습니다:"와 하단의 "수정하고 싶은 부분이 있으면 말씀해 주세요!"를 포함하여 AI의 응답 전체를 붙여넣습니다. jsonrepair 패키지는 LLM의 출력이 지저분해지는 바로 그 방식들에 맞춰 매우 관대하게 작동합니다. 잡담을 제거하고, 닫히지 않은 대괄호를 닫으며, 뒤따르는 쉼표를 수정하고, 작은따옴표를 고쳐줍니다. "거의 JSON에 가까운 것"을 JSON으로 바꿔줍니다.
결과적으로: 흐름에는 여전히 붙여넣기 단계가 남아 있지만, 그 단계가 실패하는 일은 거의 없습니다. 사용자는 퀴즈가 나타나는 것을 봅니다. 그들은 파서 (parser)가 그들의 지저분한 붙여넣기 내용을 다시 형태에 맞게 꿰매고 있는 모습은 보지 못합니다. 이것은 두 번째 시도에서 원했던 마법처럼 프롬프트가 사라지는 흐름은 아닙니다. 하지만 제품은 출시되었고, 퀴즈당 비용이 들지 않으며, 일요일 아침에 ChatGPT에서 내용을 복사해 붙여넣는 조부모님들도 사용할 수 있을 만큼 잘 작동합니다.
결론 (The thread)
내가 마주한 모든 막다른 길은 동일한 본능의 변형이었습니다: 사용자의 도구가 일을 하게 두자. 그 본능은 옳았습니다. 요점은 그 본능에서 물러나는 것이 아니라, "사용자의 도구"가 가진 거친 모서리들 (부분적인 붙여넣기, 친절한 서문, 절반만 스트리밍된 응답)을 사용자의 문제가 아닌 내가 흡수해야 할 나의 문제로 받아들이는 것이었습니다. 이 경우 좋은 UX는 영리한 파이프라인 (pipeline)이라기보다 관대한 파서 (parser)에 가까운 모습이었습니다.
영리한 아키텍처 (architecture)를 구축하는 것이 더 만족스러웠을 것입니다. 또한 그것은 출시되지도 못했을 것입니다. 직접 시도해 보고, 당신이라면 어떻게 할지 제게 알려주세요. 서비스는 quizzy.earth 에서 바로 이용 가능합니다. 사이트를 열고, 주제를 선택하고, 프롬프트 (prompt)를 생성한 뒤, 당신이 즐겨 사용하는 AI에 붙여넣고, 그 응답을 다시 붙여넣으세요. 계정 생성 없이, 당신의 토큰 (tokens)을 사용하여 30초면 충분합니다. 만약 당신이 제가 시도하지 않은 방식으로 "타인의 API 예산으로 훌륭한 UX를 구현하는 문제"를 해결했다면, 꼭 듣고 싶습니다. 특히 그 마법처럼 사라지는 버전 (version)에 대해서 말이죠. 저는 여전히 그것을 작동하게 만들 방법이 있다고 생각합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기