theplaycompany AI Transformation Report

제안서 생성기의 진화
Agentic 코딩으로 만드는
AI 서비스

더플레이컴퍼니 PPT 제안서 생성기의 3단계 진화 과정을 통해 백엔드, 프론트엔드, 데이터베이스, LLM 활용의 핵심 개념을 이해합니다

v0.1 → v0.2 → v0.3 — 3 Versions, 29 Modules, 2 AI Features
01 — Concepts

IT 개념을 우리 업무로 이해하기

FE
프론트엔드 = 교육 현장
교육 참석자가 직접 보고 사용하는 화면. 우리로 치면 교육 현장에서 참석자에게 보이는 프로그램 안내판, 교구 배치, 진행 순서표와 같습니다. Next.js, React로 구현.
BE
백엔드 = 본사 기획팀
사용자에게는 보이지 않지만 모든 로직을 처리하는 서버. 우리로 치면 본사 기획팀이 견적을 계산하고, 모듈을 조합하고, PPT를 만들어내는 것과 같습니다. FastAPI, Python으로 구현.
DB
데이터베이스 = 모듈 카탈로그
29개 교육 프로그램의 이름, 시간, 목표, 단가 등 모든 정보가 저장된 곳. 우리의 프로그램 카탈로그, 지역별 단가표와 같습니다. 현재는 Python 파일, 향후 PostgreSQL 등으로 확장 가능.
API
API = 전화선/연결통로
프론트엔드(현장)와 백엔드(기획팀)를 연결하는 통로. '현장에서 기획팀에 전화해서 견적 요청하면 기획팀이 계산해서 알려주는 것'과 같습니다. REST API로 구현.

우리 프로젝트에서 이 4가지가 어떻게 나뉘는가

제안서 생성기의 기능을 4개 블록으로 분해하면 이렇습니다 v0.3 기준

실제 기능 흐름
👤 사용자가 화면에서
모듈 선택 + 정보 입력
📡 API 호출
"이 모듈로 견적 계산해줘"
⚙️ 서버가 계산
단가표 × 인원 × 시간
📦 DB에서 조회
29개 모듈 정보 + 지역 단가
📄 결과를 화면에
견적표 + PPT 다운로드
블록 우리 서비스에서 하는 일 구체적 예시
FE 사용자가 보고 누르는 화면 v0.1 v0.3 • 모듈 카드를 클릭해서 "레고레이스" 선택
• 고객사명, 인원수, 지역 입력 폼
• "제안서 생성" 버튼
• 견적 테이블 실시간 표시
v0.1 Streamlit  →  v0.3 Next.js로 전환
BE 눈에 안 보이는 처리 로직 v0.1 FE에 통합 v0.3 분리 • "서울, 80명, 8시간" → 견적 자동 계산 (₩12,340,000)
• 선택된 4개 모듈 → 76장 PPT에서 해당 슬라이드만 추출
• 표지에 "삼성전자" 자동 삽입, 견적표에 금액 채우기
• 완성된 PPT 파일 생성 → 프론트에 전달
v0.1 app.py 안에 통합  →  v0.3 FastAPI로 독립
DB 모든 정보가 저장된 곳 v0.1~v0.3 동일 • 29개 모듈: 이름, 시간, 목표, 설명, 키워드, 팀 규모
• 5개 지역 × 3개 인원 구간 = 15가지 단가표
• 시스템 사용료: 레고레이스 2만원, PLUS 2만원...
→ 현재는 Python 파일(modules.py, pricing.py)에 저장
API 화면과 서버를 연결하는 통로 v0.1 없음 v0.3 8개 GET /api/modules → "29개 모듈 목록 줘"
POST /api/calculate-cost → "이 조건으로 견적 계산해줘"
POST /api/generate-proposal → "PPT 만들어줘"
POST /api/auto-select → "자연어로 모듈 추천해줘"
→ 총 8개 API 엔드포인트가 프론트↔백을 연결합니다
v0.1에서는 이 4가지가 전부 한 파일(app.py)에 섞여 있었습니다.
v0.3에서는 각각 독립되어, 화면만 바꾸거나 서버만 업데이트하는 게 가능해졌습니다.
02 — Evolution

제안서 생성기의 3단계 진화

수작업 30분 → 버튼 1번 → 자연어 1줄. AI 에이전트가 주도하는 서비스 빌드업 과정

Version Evolution Pipeline
v0.1 Streamlit
v0.2 + AI
v0.3 FastAPI+Next.js
v0.4 HTML 우선
v0.1 — 초기 빌드
Streamlit
아키텍처: 모놀리식
프론트: Streamlit
백엔드: 없음
LLM: 없음
아웃풋: PPT
기능: 모듈 수동 선택 → PPT 조합
"기획팀이 직접 현장 운영"
▶ 체험하기
v0.2 — AI 통합
+ Claude API
아키텍처: 모놀리식 + AI
프론트: Streamlit 3탭
백엔드: 없음
LLM: Claude (텍스트+선택)
아웃풋: PPT
기능: AI 맞춤 텍스트, 자동 선택
"AI 어시스턴트 합류"
▶ 체험하기
v0.3 — 프로덕션
FastAPI + Next.js
아키텍처: 마이크로서비스
프론트: Next.js + TS
백엔드: FastAPI
LLM: Claude
아웃풋: PPT
기능: REST API, 모바일 지원
"기획팀·현장·AI 독립 운영"
▶ 체험하기
v0.4 — HTML 우선
HTML + Hybrid
아키텍처: HTML 마스터
프론트: Next.js + Jinja2
백엔드: FastAPI
LLM: Claude
아웃풋: HTML / PDF / PPT
기능: 픽셀 매칭, 7배 빠름, PPT 변환 가능
"디지털 마스터 + 다중 출력"
▶ 체험하기
⚠️ 시연 시 가장 중요한 포인트

v0.2 → v0.3는 결과물(PPT)이 똑같습니다.
의도적입니다.

v0.2와 v0.3은 같은 generate_proposal() 함수를 호출합니다. 한 글자도 안 바뀌었어요. 그래서 다운로드한 PPT가 동일합니다. 다른 건 "결과를 만드는 방식"입니다.

v0.2 — "1인 식당"

한 사람이 주문도 받고, 요리도 하고, 서빙도 함.
손님이 늘면 줄 서야 함.
메뉴 바꾸려면 식당 문 닫고 전체 수정.
배달앱 연동 불가 — 전화 주문만.

v0.3 — "주방+홀 분리된 식당"

주방(FastAPI)은 요리 전담, 홀(Next.js)은 응대 전담.
손님 많아지면 홀만 확장.
인테리어 바꿔도 주방은 그대로.
배달앱이 주방에 직접 주문 (REST API).

v0.2 — app.py (Streamlit) if st.button("PPT 생성"): result = generate_proposal(...) st.download_button("다운로드", result) # UI와 로직이 한 파일에 섞임
v0.3 — routers/proposal.py (FastAPI) @router.post("/generate-proposal") def create_proposal(req): return generate_proposal(...) # 외부에서 API로 호출 가능

개발 단계에서 가장 중요한 작업이 '결과는 그대로 두고 내부 구조만 바꾸는 것'
이걸 리팩토링(refactoring)이라고 합니다.

v0.3가 가져온 실질적 가치 (지금은 같지만, 미래의 확장 가능성)
항목v0.2v0.3
다른 시스템에서 호출 불가능 POST /api/generate-proposal
모바일에서 사용 불편 (Streamlit) 반응형 자동
CRM 연동, Slack 봇 불가 API 한 줄
디자인 변경 Streamlit 한계 CSS 자유
버전 업데이트 전체 재배포 백/프론트 독립
다음 단계 (v0.4) 진행 전체 갈아엎기 라우터 1개만 추가
"같은 음식을 1인 식당에서 만들든, 분리된 식당에서 만들든 손님 입에는 똑같죠.
하지만 손님이 100명 오면 1인 식당은 망하고, 분리된 식당은 견딥니다.
v0.2 → v0.3은 손님이 늘기 전에 미리 갈아탄 것입니다."
03 — LLM Integration

LLM이 서비스 모듈로 작동하는 법

Claude는 '똑똑한 어시스턴트'가 아니라, 서비스의 한 부품(모듈)으로 작동합니다

AI 맞춤 텍스트 생성 파이프라인 v0.2에서 추가 v0.3 API화
사용자 입력
고객사/업종/목적
PPT 텍스트 추출
실제 슬라이드 300자
Claude API
재작성 ±10%
맞춤 텍스트
slide_texts
PPT 반영
generate_proposal
자동 프로그램 설계 파이프라인 v0.2에서 추가 v0.3 API화
자연어 입력
"삼성 리더십 1일"
Claude API (tool_use)
29개 카탈로그 + 규칙
구조화된 JSON
선택/근거/플로우
검증
상호배타/인원
모듈 조합
PPT 생성
"LLM은 만능이 아닙니다. 정확한 입력(프롬프트)과 출력(구조화된 JSON)을 설계해야, 서비스의 신뢰할 수 있는 부품이 됩니다."
04 — Code Comparison

코드로 보는 변화

v0.1

PPT 생성 (ZIP 레벨 조작)

ppt_generator.py — v0.1 def _extract_slides(src, keep_indices, dest): """76장 템플릿에서 필요한 슬라이드만 추출""" # ZIP 파일을 열어 슬라이드 XML을 직접 조작 with zipfile.ZipFile(src) as zin: with zipfile.ZipFile(dest, 'w') as zout: for item in zin.infolist(): # slide1.xml ~ slide76.xml 중 필요한 것만 복사 ...
v0.2

AI 맞춤 텍스트 (Claude API)

ai_generator.py — v0.2 def generate_custom_texts(client_name, industry, ...): """Claude API로 고객사 맞춤 텍스트 생성""" client = anthropic.Anthropic(api_key=api_key) response = client.messages.create( model="claude-opus-4-6", max_tokens=32768, messages=[{"role": "user", "content": prompt}], ) # "교육생" → "삼성전자 신임 팀장"으로 맥락 치환
v0.3

REST API + 자동 선택 (tool_use)

auto_selector.py — v0.3 response = client.messages.create( model="claude-opus-4-6", system=system_prompt, # 29개 모듈 카탈로그 + 비즈니스 규칙 tools=[TOOL_SCHEMA], # 구조화된 출력 스키마 tool_choice={"type": "tool", "name": "select_program_modules"}, messages=[{"role": "user", "content": "삼성 신임팀장 80명 리더십 1일"}], ) # → {"selected_modules": ["check_in", "plus", "team_maker_workshop", "super_lens"]}
05 — Architecture Maturity

아키텍처 성숙도 모델

L1
수작업 이전
76장 PPT에서 직접 삭제, 30분+
L2
자동 조합 v0.1
모듈 선택 → PPT 자동 생성
L3
AI 맞춤 v0.2
고객 맥락 반영, 자연어 자동 선택
L4
API 분리 v0.3
프론트/백 분리, REST API, 모바일 지원
L5
풀 자동화 향후
CRM 연동, 자동 발송, 분석
06 — Deployment

배포란 무엇인가

지금은 내 컴퓨터(localhost)에서만 돌아갑니다. 배포하면 누구나 접속할 수 있습니다.

현재 (localhost) v0.1~v0.3

내 컴퓨터에서만

컴퓨터를 켜야만 접속 가능. 같은 와이파이만 가능. 꺼면 끝.

http://localhost:8000
배포 후 (cloud) 향후

누구나, 언제든

theplay-proposal.vercel.app 같은 주소로 24시간 접속. 프론트는 Vercel, 백엔드는 Railway/AWS.

https://theplay-proposal.vercel.app
07 — Agentic Coding

Agentic 코딩이란

"사람이 코드를 한 줄씩 작성하는 대신, AI 에이전트가 설계-구현-테스트-디버그를 자율적으로 수행합니다. 사람은 '무엇을 만들지'를 지시하고, '어떻게 만들지'는 에이전트가 판단합니다."
AS-IS (전통 개발) v0.1

개발자가 코드 작성 → 테스트 → 버그 수정 → 반복. 1주일

TO-BE (에이전트 코딩) v0.2~v0.3

Claude Code에게 지시 → 병렬 에이전트가 3개 파일 동시 작성 → 자동 테스트 → 결과 검증. 수 시간

실제 사례

이 프로젝트에서 일어난 일

이 보고서에 나온 v0.1→v0.3 전체 진화는 Claude Code 단일 세션에서 수행되었습니다. 3개 파일을 병렬 에이전트로 동시 수정하고, AI 텍스트 유실 버그를 자동 발견·수정하고, 프론트엔드/백엔드 아키텍처를 한 번에 전환했습니다.

병렬 에이전트 자동 버그 탐지 아키텍처 전환 단일 세션
08 — Roadmap

향후 발전 방향

Phase 1 — 즉시
즉시 실행

프로덕션 배포

  • 프론트엔드: Vercel 배포
  • 백엔드: Railway 배포
  • 도메인 + HTTPS
  • 환경변수 분리
Phase 2
1개월

사용자 인증 + 히스토리

  • 로그인/회원가입
  • 생성 히스토리 DB
  • 제안서 버전 관리
Phase 2.5 — 신규
2개월

💰 견적서 생성기 (모듈 추가)

  • 지역×인원×시간 자동 계산
  • FT/시스템/교통/숙박 항목별 단가
  • 할인율 + VAT 자동 반영
  • 제안서 빌더와 독립 모듈
참고 디자인:
Google Drive 미리보기 ↗
Phase 3
3개월

CRM 연동 + 자동 발송

  • CRM 시스템 연동
  • 제안서 자동 이메일
  • 고객 응답 추적
Phase 4
6개월

AI 이미지 + 다국어

  • AI 이미지 생성
  • 다국어 제안서
  • 글로벌 진출
🧩 모듈 구조 개발의 가치

견적서 생성기는 완전히 새 시스템이 아닙니다.
v0.3 백엔드에 라우터 1개 추가로 끝납니다.

만약 v0.1 모놀리식이었다면 견적서를 추가하려면 Streamlit 페이지를 갈아엎어야 했을 겁니다.
v0.3에서 우리는 backend/routers/ 안에 estimate.py 한 파일만 추가하면 됩니다.
프론트엔드도 /estimate 페이지 1개만 추가. 기존 제안서 빌더는 한 줄도 안 바뀝니다.

v0.1 모놀리식이었다면

견적 로직을 어디에 넣지? Streamlit 새 탭? 기존 코드 영향은? 디자인 통일은? 2~3주

v0.3 모듈화 구조

routers/estimate.py 추가 + /estimate 페이지. 기존 코드 무영향. 2~3일

"모듈화는 미래의 기능을 위한 보험" — 처음에 잘 나누면 나중에 무한히 확장할 수 있습니다.

09 — Output Evolution

아웃풋 포맷이 시스템을 결정한다

PPT 고정 아웃풋 → HTML 유연 아웃풋 → PDF/PPT 하이브리드. 결과물의 형태가 바뀌면 시스템 전체가 바뀝니다.

Output Format Evolution
PPT Only v0.1~v0.3
HTML First v4
PDF Export v4
Editable PPT v4
PPT 아웃풋 v0.1~v0.3

코드의 59%가 포맷과 싸우는 코드

• ZIP 파일을 열어 XML을 직접 수술 (99줄)

• 텍스트 박스 고정 크기 → AI 텍스트 ±10% 글자 수 강제

• 견적 테이블 4열 고정 → 열 추가 불가

• 템플릿 디자이너가 슬라이드 순서 바꾸면 전체 코드 수정

• PDF 변환: LibreOffice 30~60초

생성 시간: 35~70초

HTML 아웃풋 v4

코드의 95%가 비즈니스 로직

• Jinja2 템플릿 렌더링 (20줄 핵심 로직)

• 텍스트 자동 리플로우 → AI가 자연스럽게 작성

• 테이블 열/행 자유롭게 추가

• CSS 변수 1곳 수정 → 전체 브랜딩 변경

• PDF 변환: Playwright 2~5초

생성 시간: 3~10초 (7배 빠름)

하이브리드 출력

하나의 HTML에서 3가지 포맷 생성

HTML — 웹 브라우저에서 바로 열어 확인. URL로 공유 가능.

PDF — Playwright(headless Chrome)로 2~5초 만에 변환. 인쇄용.

편집 가능 PPT — dom-to-pptx 라이브러리로 DOM을 네이티브 PPTX로 변환. 모든 텍스트 박스 클릭해서 수정 가능.

HTML → PDF: 2초 HTML → PPT: 3초 파일 크기: 60KB (PPT 대비 83배 작음)
10 — Self-Review Workflow

에이전트가 스스로 결과물을 검증하는 법

사람이 매번 확인하지 않아도, AI 에이전트가 결과물을 PDF로 변환해서 직접 보고 문제를 발견하고 수정합니다.

Self-Review Loop
HTML 생성
Playwright
PDF 변환
에이전트가
PDF 직접 열람
문제 발견
오버플로우, 유실, ID 노출
코드 수정
템플릿/생성기
재검증
실제 사례

이 프로젝트에서 발견된 버그들

에이전트가 PDF를 직접 읽고 발견한 문제들:
발견된 문제 원인 수정
AI 텍스트 유실 (363자 → 53자) PPT 텍스트 박스에 맞추려고 글자 수를 줄임 실제 슬라이드 텍스트를 AI에 전달하여 동일 길이로 재작성
간지에 코드 ID 노출 (check_in, team_maker) auto_selector의 rationale을 그대로 사용 AI가 생성한 proposal_background로 대체
견적서 슬라이드 위치 오류 하드코딩된 인덱스 (len-3) ordered_slides.index()로 정확한 위치 계산
AI 응답 JSON 잘림 (7모듈+) max_tokens=4096 부족 16384로 증가 + 잘린 JSON 복구 로직 추가
"에이전트가 PPT는 못 읽지만 PDF는 읽을 수 있다. 그래서 HTML → PDF → 에이전트 리뷰 → 수정 루프를 만들었다. 사람이 매번 열어보지 않아도 품질이 올라가는 구조."
기존 검증 방식

사람이 PPT를 열어서 슬라이드 하나하나 확인.
텍스트 넘침, 유실, 오타를 눈으로 찾음.
모듈 4개 기준 10~15분

에이전트 셀프 리뷰

HTML → PDF 자동 변환 → 에이전트가 PDF 열람.
슬라이드별 글자 수 비교, 오버플로우 감지, 맥락 키워드 검증.
자동, 30초

© 2026 theplaycompany. Agentic Coding Report — Generated with Claude Code