AI Product Manager · 2023.09—Now
PRD를 쓰고, HTML 목업을 만들고, 지표 산식까지 감사하는 AI PM. 38개 AI 투자 알고리즘 기획, 200+ 실운용 계좌, 운용시간 83% 단축.
세 번의 판단.
2023 — 2026
생각의 기록.
19 posts · 2024 — 2026
토큰 단가를 모르면 '이거 해주세요'의 비용을 모르는 것. 주주톡 6에이전트 시스템과 Claude Code 스킬을 만들면서 AI 비용을 기획 언어로 번역하게 된 과정.
에이전트 6개가 내놓은 결과를 단순 다수결로 합치면 항상 '중립'이 나왔다. 그건 결론이 아니라 포기였다. 합의 설계에서 PM이 실제로 결정해야 하는 것들.
사내 퀀트 분석 플랫폼의 프론트엔드를 NiceGUI에서 Vite로 옮겼어요. 원래 견적은 3주였는데 5일에 끝났어요. 그게 가능했던 건 이주 전에 쌓아둔 워크플로우 덕분이었어요.
고객 미팅에서 나온 막연한 질문들을 투자 백테스트 대시보드의 매매 탐색 화면으로 번역한 하루. 3탭을 2탭으로, 페이지 전환을 인라인 드릴다운으로, 기여수익률 분해까지.
AI 경마 해커톤에서 데이터 분석과 시장 신호가 충돌했다. AI를 믿고 배당 급등을 무시한 결과는 전멸. 데이터와 현장이 다른 말을 할 때, 기획자는 어느 쪽에 베팅해야 할까?
Claude API를 호출하면 결과가 나와요. 종목 분석을 시키면 분석이 나오고, 목업을 넘기면 코드가 나오고. “되네?”의 순간이 연속되다 보면, 비용은 나중에 생각하게 돼요.
주주톡 초기가 그랬어요. 에이전트를 4개로 나눴다가 6개로 늘리고, 병렬로 바꾸고, 토론 시스템을 붙이고. 기능이 하나씩 붙을 때마다 LLM 호출 횟수도 조용히 늘어났어요.
어느 날 종목 하나 분석에 총 몇 번의 호출이 들어가는지 세어봤어요.
에이전트 6개 + 토론 라운드 3회 + Supervisor 종합 = 한 분석당 최소 15번의 LLM 호출
숫자를 보고 나서야 “이거, 기획서에 없는 숫자다”라는 생각이 들었어요.
처음에 6개 에이전트를 순서대로 돌리면 각각 10~15초, 합치면 약 90초가 걸렸어요. 사용자한테 90초 기다리라고 할 수는 없으니 병렬화했고, 그건 15~20초로 줄었어요.
근데 시간만의 문제가 아니었어요. Claude API를 직접 쓴다면, 한 번의 종목 분석에 들어가는 토큰이 얼마인지 계산해봐야 했어요. 에이전트 하나당 입력 3,000~5,000 토큰, 출력 500~1,000 토큰. 6개면 입력만 약 25,000 토큰, 여기에 토론과 Supervisor를 더하면 분석 한 번에 40,000 토큰 이상이에요.
사이드 프로젝트 기준으로 계산하면, 하루 사용자가 50명이고 각자 5번 분석을 돌린다고 가정하면 하루 250회, 총 약 1,000만 토큰. Claude Opus 기준으로 환산하면 하루 수십 달러 규모가 나왔어요.
이때 처음으로 “AI 호출을 설계한다”는 게 뭔지 감이 잡혔어요.
6개 에이전트가 항상 다 필요한 건 아니에요. AAPL 같은 기술주를 분석하는데 원자재 에이전트가 왜 필요해요? 에너지 종목이 아니면 유가 분석은 거의 무의미해요.
그래서 섹터별 가중치 매트릭스를 만들었어요. 12개 섹터 × 6개 에이전트의 가중치를 정의하고, 0.5 미만이면 아예 호출 안 하는 구조로요.
| 섹터 | 차트 | 재무 | 금리 | 뉴스 | 원자재 | 경쟁사 |
|---|---|---|---|---|---|---|
| 기술 | 0.85 | 0.90 | 0.55 | 0.70 | 0.40 | 0.65 |
| 에너지 | 0.80 | 0.75 | 0.85 | 0.65 | 0.95 | 0.60 |
| 금융 | 0.75 | 0.85 | 0.90 | 0.70 | 0.30 | 0.70 |
AAPL을 넣으면 원자재(0.40)와 경쟁사(0.65 → 섹터 기준 따라 다름) 에이전트는 빠져요. 결과적으로 종목에 따라 6개 중 4~5개만 실행돼요.
이 결정의 핵심은 “비용을 줄이려고 품질을 희생한 게 아니다”는 거예요. 오히려 관련 없는 에이전트가 “데이터 부족, 중립” 판정을 내려서 전체 점수를 오히려 왜곡하는 문제를 막았어요.
비용 절감이 분석 품질과 함께 갔을 때, 이 결정이 기획서에 들어갈 수 있는 것이에요.
AED에서 Claude Code 스킬을 두 개 만들었어요. mockup-apply(목업을 기존 코드에 적용)랑 frontend-checkpoint(구현 상태를 스펙과 비교). 둘 다 기존에 없는 거라 직접 만들어야 했어요.
여기서 “직접 만들기 vs 사서 쓰기 vs AI에 맡기기”의 ROI를 따지게 됐어요.
직접 만들기: 스킬 하나 만드는 데 약 1~2일. 유지보수는 내가 다 해야 해요.
사서 쓰기: 해당 기능을 정확히 커버하는 도구가 없었어요. 비슷한 건 있었지만, 우리 워크플로우에 맞으려면 어차피 커스텀이 필요했어요.
AI에 맡기기: 스킬 명세서를 작성하고, Claude Code에 “이 워크플로우대로 돌아가는 slash command를 만들어달라”고 넘겼어요. 약 3~4시간.
결론적으로 AI에 맡겼어요. 근데 중요한 건 그 이후예요. AI가 만든 스킬이 처음부터 제대로 돌아간 건 아니었어요. mockup-apply는 초기 버전에서 기존 기능을 날리는 문제가 있었어요. 이걸 잡는 데 하루가 더 들었고요.
결국 “AI에 맡기기”의 진짜 비용은 프롬프트 작성 시간 + 검증 시간이에요. 프롬프트만 넘기고 끝난다고 생각하면 실제 비용을 과소평가하게 돼요.
지금은 두 스킬 모두 안정적으로 쓰고 있어요. 하지만 “AI에 맡기면 저절로 된다”는 착각이 얼마나 비싼지 이 경험으로 알게 됐어요.
이 경험들이 쌓이면서, 저는 기획서에 AI 관련 항목을 따로 넣기 시작했어요. 세 가지예요.
기능 하나가 추가될 때마다 “이 기능은 호출당 몇 토큰인가?”를 명시해요. 정확한 숫자가 아니어도 돼요. 오더 오브 매그니튜드만 잡아도 충분해요.
이걸 기록해두면 “기능 추가 = 비용 증가”가 눈에 보이는 숫자가 돼요.
모든 작업에 가장 비싼 모델이 필요한 건 아니에요. 주주톡에서는 이렇게 나눴어요.
“언제 비싼 모델을 쓸 것인가”를 기획 단계에서 명시하면, 구현할 때 모델 선택이 임의적이지 않게 돼요.
API 장애, 타임아웃, 예산 초과 시 어떻게 할지를 기획서에 써요. “LLM 호출 실패 시 캐시된 결과 반환”, “예산 임계치 도달 시 소형 모델로 자동 전환” 같은 것들이요.
주주톡에서는 Supervisor 에이전트의 셀프리뷰를 데이터 품질 0.4 미만인 경우에만 실행하게 했어요. 항상 실행하는 것 대비 약 60~70%의 Supervisor 추가 호출을 줄였어요. 폴백이 아니라 조건부 실행이지만, 발상은 같아요 — 항상 최선이 아니어도 되는 경우를 명확히 정의하는 것.
“기능 하나 추가”를 이제 “토큰 X원짜리 기능 하나 추가”로 생각하게 됐어요.
이게 단순히 비용 절감 마인드가 아니에요. AI 기능의 규모를 가늠할 수 있는 단위가 생긴 것이에요. 이전에는 “에이전트 하나 더 붙이면 어때요?”라는 질문에 “좋은데요, 해볼게요”라고 답했어요. 지금은 “에이전트 하나 더 붙이면 분석당 8,000토큰 추가예요. 그 품질 향상이 그 비용을 정당화하나요?”라고 물어볼 수 있어요.
기획자가 AI 시스템을 설계할 때, 토큰 단가를 모른다는 건 인건비를 모르고 채용 계획을 세우는 것과 비슷해요.
숫자를 알면 협상할 수 있어요. 아끼거나 쓰거나 바꾸거나. 모르면 그냥 쓰는 거예요.
솔직히, 이 프레임워크도 완벽하지 않아요.
섹터 가중치 매트릭스는 제가 도메인 직관으로 채웠어요. 0.4와 0.5 사이의 컷오프가 최적인지는 충분히 검증하지 못했어요. 다른 섹터 분류 기준을 쓰면 전체가 달라질 수도 있어요.
그리고 “토큰 예산”을 기획서에 넣으면 이걸 실제로 추적하는 인프라가 필요해요. 로깅, 모니터링, 알림. 사이드 프로젝트에서 이걸 다 갖추기는 아직 무거워요.
기획서에 숫자를 넣는 건 시작이에요. 그 숫자가 실제와 얼마나 맞는지 검증하는 루프가 있어야 진짜 관리가 돼요. 그 루프는 아직 만들고 있는 중이에요.
주주톡에는 6개의 분석 에이전트가 있어요. 거시경제, 기술적 분석, 공시, 뉴스, 재무, 온체인. 각자 다른 데이터를 보고, 다른 관점에서 종목을 평가해요.
처음에는 단순하게 생각했어요. 6개 에이전트한테 각각 “매수 / 중립 / 매도” 중 하나를 고르게 하고, 가장 많이 나온 걸 최종 의견으로 쓰면 되지 않을까? 민주주의적으로 공정하잖아요.
결과는 기대와 달랐어요. 거의 항상 “중립”이 나왔어요.
삼성전자를 분석했을 때를 예로 들게요. 결과는 이랬어요.
다수결 결과: 중립 (4:1:1)
이게 맞는 결론일까요? 아니라고 생각해요. 중립 4표 중 2표는 사실 “데이터가 없거나 변동이 없어서 판단 안 함”이었어요. 거시와 기술이 정면으로 충돌하는 상황인데, 그 충돌이 결과에 전혀 드러나지 않았어요. 중립이 아니라 “의견 없음의 합산”이었던 거죠.
이건 사용자에게 아무 정보도 주지 않는 것과 같아요. 아니, 어떤 면에서는 더 나빠요. “AI가 분석했는데 중립이래”라는 가짜 안도감을 줄 수 있으니까요.
첫 번째로 바꾼 건 집계 방식이에요.
모든 에이전트의 표가 같은 무게를 가지면 안 된다는 걸 깨달았어요. 온체인 에이전트가 “데이터 부족”으로 중립을 낸 것과, 재무 에이전트가 3개 분기 실적을 검토하고 중립을 낸 건 완전히 다르거든요.
그래서 에이전트별로 데이터 품질 점수를 도입했어요. 해당 분석에서 실제로 사용된 데이터의 양, 신선도, 커버리지를 기준으로 각 에이전트의 신뢰도를 그때그때 동적으로 조정해요. 데이터가 충분하지 않아서 나온 중립은 가중치가 낮아지고, 풍부한 근거를 가진 의견은 더 반영되는 구조예요.
완벽한 해법은 아니에요. 가중치 자체가 또 다른 편향의 원천이 될 수 있으니까요. 하지만 “모든 의견을 동등하게 취급하면 아무 의견도 반영되지 않는다”는 문제보다는 낫다고 판단했어요.
두 번째 결정은 더 어려웠어요. UX 문제였거든요.
충돌을 합산해서 하나의 숫자로 보여주면 간결하긴 해요. 그런데 그러면 사용자는 “AI가 분석했다”는 사실만 기억하고, 그 안에 얼마나 큰 불확실성이 있었는지는 모르게 돼요.
주주톡에서 선택한 방향은 충돌 자체를 보여주는 것이었어요. 에이전트들의 의견이 갈릴 때, 결과 화면에는 단일 권고 대신 세 가지 시나리오가 나와요.
각 시나리오 아래에는 어떤 에이전트가 그 관점을 지지하는지, 근거는 무엇인지가 붙어요.
사용자 입장에서는 더 복잡해 보일 수 있어요. 그게 의도예요. 주식 투자가 복잡한 게 실제 현실이니까, 그 복잡성을 숨기는 게 오히려 더 위험하다고 봤어요.
세 번째가 가장 중요한 결정이에요.
처음에는 “AI가 결론을 내려줘야 서비스지”라고 생각했어요. 그런데 6개 에이전트가 3:3으로 갈리는 상황에서 시스템이 억지로 결론을 내린다면, 그건 근거 없는 답을 만들어내는 거예요.
주주톡이 정한 경계는 이거예요. AI는 근거를 구조화하고, 결정은 사람이 한다.
AI가 하는 일: 각 에이전트의 분석을 정리하고, 어디서 의견이 갈리는지 명확히 하고, 각 시나리오의 논리를 설명한다.
AI가 하지 않는 일: “그러므로 매수하세요.”
이 경계가 불편하게 느껴질 수 있어요. 사용자는 결론을 원하니까요. 하지만 AI가 판단할 수 없는 것—사용자의 투자 성향, 리스크 허용 범위, 포트폴리오 상황—을 AI가 모르는 채로 결론을 내리는 건 서비스가 아니라 무책임이에요.
AI 시스템에서 에이전트 합의를 설계할 때 PM이 실제로 결정해야 하는 건 크게 세 가지예요.
1. 집계 방식: 단순 다수결인가, 가중 투표인가, 아니면 아예 집계 자체를 안 하는가. 어떤 방식이든 트레이드오프가 있어요. “가장 좋은 방법”보다 “어떤 문제를 해결하려는 방법인지”가 더 중요해요.
2. 불확실성 표현: 시스템이 확신하지 못할 때 그걸 어떻게 보여줄 것인가. 숨기면 사용자가 잘못된 확신을 갖게 되고, 너무 드러내면 서비스가 혼란스러워 보여요. 그 균형점은 데이터 문제가 아니라 UX 결정이에요.
3. 판단 경계: 어디까지 AI가 결론을 내리고, 어디서부터 사람에게 넘길 것인가. 이건 기술의 한계가 아니라 서비스의 철학이에요. AI가 할 수 있어도 안 해야 하는 영역이 있어요.
주주톡을 만들면서 가장 많이 고민한 건 “어떻게 더 좋은 분석을 하게 할까”가 아니었어요. “AI가 틀릴 수 있다는 걸, 시스템이 어떻게 정직하게 보여줄 것인가”였어요.
에이전트가 3:3으로 갈릴 때 시스템이 어떻게 결론을 내리는지 — 사실 그게 기획이에요.
리서처들이 매일 쓰는 사내 퀀트 분석 플랫폼. 어느 날부터 서버가 터지기 시작했어요. NiceGUI로는 더 이상 안 됐고, React로 옮겨야 했어요. 처음 받은 견적은 3주. 실제로는 5일에 끝났어요. 중간에 Next.js를 버리고 Vite로 꺾는 결정까지 포함해서요.
먼저 팀이 이렇게 생겼어요.
프론트엔드 개발자 0명, 디자이너 0명.
AED 백테스팅 엔진이랑 분석 파이프라인은 회사에 이미 있었어요. 그 위에 화면을 덮은 건 본부장님이었어요. Claude Code로 대충 구현해서 리서처 3~4명이 쓰고 있었죠. “쓸 만하지만 진짜 도구라고 하기엔…” 정도의 상태가 2025년 10월부터 이어지고 있었어요.
2026년 1월부터 제가 프론트엔드를 손보기 시작했어요. 리서처들 사이에서 “이거 이렇게 보면 좋겠다”, “이 화면에 이것도 있어야 하지 않나?” 같은 요구가 쌓이기 시작했거든요. “기획자가 코드도 짜?”라는 질문에는 “안 짜면 아무도 안 짜는데요”라고 답하는 수밖에 없는 상황이었어요.
처음 쓴 건 NiceGUI였어요. 이유는 단순했어요.
몇 달 동안은 잘 굴러갔어요. 페이지를 하나씩 더 만들고, 디자인을 조금씩 다듬고, 기능도 누적됐어요. 3~4명이 쓸 땐 가볍고 반응도 괜찮았어요.
문제가 없던 건 아니었어요. 디자인 시안을 옮기면 70%만 재현됐고, 복잡한 인터랙션은 우회해야 했고, 다크 모드와 다국어는 매끄럽지 않았어요. 그래도 “이 정도면 쓸 만하다” 범주 안이었어요. 사실 이 시점부터 이미 React 이주는 계획에 있었어요. 당장은 아니고, 언젠가.
그 “언젠가”가 훨씬 빨리 왔어요.
내부에서 AED를 쓰는 사람이 늘기 시작했어요. 기능도 계속 추가됐고요. 어느 순간부터 NiceGUI 서버가 쉽게 터지는 문제가 생겼어요. 그냥 느린 게 아니라, 리서처 몇 명이 동시에 백테스트 결과를 열면 응답이 안 오는 수준이요.
3~4명일 땐 문제가 아니었던 게, 사용자 수 × 기능 수 × 데이터 양이 누적되니까 한계를 넘어버렸어요. 우회로 버틸 수 있는 단계는 이미 지나있었고요. 이주를 더 미룰 수 없었어요.
React로 가기로 정하고 나서 처음 잡은 견적은 3주였어요. 이유는 간단했어요.
20+ 페이지. 라우팅, i18n, 차트, 테이블, 다크 모드, 다국어. 전부 재작성이에요.
기획자 한 명이 이걸 평범한 속도로 해내면 3주는 잡아야 한다고 본 거예요. 그리고 첫 타겟은 Next.js였어요. React 생태계에서 가장 무난한 기본값이니까요. 레퍼런스 많고, 풀스택 지원, 디자인 시스템 생태계(shadcn, Tailwind)가 풍부하고요.
근데 견적 3주와 실제 5일 사이에 격차가 생긴 이유는, 이주 작업을 시작하기 전에 이주가 쉬워지는 것들을 먼저 만들어뒀기 때문이었어요.
NiceGUI 시절에 저는 각 페이지마다 PRD를 작성하고 있었어요. 그냥 처음에 한 번 쓰고 끝내는 기획서가 아니라, 구현하면서 내린 결정이 PRD로 역류하게 만들었어요.
예를 들어 “이 테이블에서 태그 몇 개까지 보여줄 것인가?”라는 질문에 처음엔 “5개”로 썼다가, 실제로 구현해보니 부족해서 “10개”로 바꿨어요. 이때 코드만 고치는 게 아니라 PRD도 같이 고치고, “왜 바꿨는지”를 같이 기록했어요. 이런 식이요.
MAX_VISIBLE_TAGS: 10(변경: 5는 구현 중 너무 적은 것을 확인)
이게 이주할 때 왜 중요하냐면, 옮길 때 제가 참고하는 게 코드가 아니라 PRD가 됐거든요. 코드엔 “어떻게”가 있지만, PRD엔 “왜”가 있어요. 옮길 땐 “왜”만 알면 새 프레임워크에 맞게 “어떻게”는 다시 짜면 되거든요. 한 달치 결정이 PRD에 전부 기록돼 있으니까, 이주 때 “이거 왜 이렇게 되어 있었지?”로 낭비되는 시간이 없었어요.
제가 만든 Claude Code 스킬 중에 mockup-apply라는 게 있어요. HTML 목업을 기존 페이지에 적용할 때, 변경 체크리스트(ADD/CHANGE/KEEP)를 자동으로 뽑고, 기존 기능은 보존하면서 새 UI만 덧씌우는 워크플로우예요.
원래는 디자인 개선용으로 만든 건데, 이주에도 그대로 쓸 수 있었어요. 입력을 NiceGUI 페이지 스펙으로 바꾸고, 출력을 React 컴포넌트로 바꾸기만 하면 됐거든요. 한 페이지씩 수작업으로 옮길 때 들어가는 “컬럼 순서 맞추고, 이벤트 핸들러 이름 맞추고, 조건부 렌더링 누락 없이 옮기고…” 같은 피로가 대부분 이 스킬에서 해결됐어요.
NiceGUI 시절부터 저는 색상, 간격, 타이포를 전부 CSS 변수로 정의해뒀어요.
--bg-page: #FBF9F9;
--bg-card: #FFFFFF;
--accent-blue: #2D4A5A;
--accent-emerald: #2B6951;
토큰 이름을 의미 기반으로 쓴 게 핵심이에요. --blue-600 같은 수치 기반이 아니라 --accent-blue 같은 의미 기반.
덕분에 React로 옮길 때 이 토큰 파일을 그대로 복사하면 됐어요. 컴포넌트 코드는 바뀌지만, 디자인은 자동으로 따라왔어요. 나중에 Editorial Precision 컬러 팔레트로 톤을 바꿀 때도, 컴포넌트 코드 한 줄 안 바꾸고 전체가 새 톤으로 이동했고요.
실제로 5일 동안 일어난 일은 이래요.
처음에 Next.js로 옮기는 작업을 시작했어요. Living PRD + mockup-apply + CSS 토큰 조합이 진짜 말이 되게 빨랐어요. 한 페이지 옮기는 데 몇 시간씩 걸릴 줄 알았는데, 대부분 한 시간 이내였어요. “3주 견적이 과했나?”라는 생각이 점점 들기 시작했어요.
옮기는 중에 문득 이상한 걸 깨달았어요. AED는 전부 인증 뒤의 대시보드예요. SEO 필요 없고, 공개 페이지 없고, 모든 페이지가 "use client"로 선언돼 있었어요.
Next.js의 핵심 가치(SSR, ISR, 서버 컴포넌트)를 단 한 페이지도 쓰고 있지 않았어요.
SSR 준비 비용만 그대로 떠안고, 이점은 0. 한마디로 과잉이었던 거예요. “트렌드니까 썼다”는 게 부끄러운 순간이었어요.
본부장님한테 “우리 Vite로 가는 게 낫지 않을까요?” 꺼냈어요. 측정 결과도 같이 들고요.
| 지표 | Next.js 16 | Vite 8 |
|---|---|---|
build | 8s | 741ms |
| Dev server start | 5s | 150ms |
| HMR | 2s | 즉시 |
본부장님도 같은 느낌을 받고 계셨고, 옮기자고 결정됐어요. 1인 풀스택 환경이라도 결정을 혼자 내리는 건 아니에요. 공감하는 사람이 한 명만 있으면 움직이기 시작해요.
Next.js에서 Vite로 옮기는 건 큰 작업이 아니었어요. 이주의 본체는 이미 끝나가고 있었거든요. 남은 건 이 정도였어요.
next-intl → i18next"use client" 디렉티브 제거next/link, next/navigation, next/dynamic → react-router-dom + React.lazy전부 기계적인 치환이에요. Claude Code에 프롬프트 한 줄로 “이 프로젝트를 Next.js 16에서 Vite 8로 바꿔달라”고 넘겼고, 그대로 돌아갔어요.
NiceGUI부터 Vite까지 전체가 5일에 끝났어요. 3주 견적 대비 약 70% 단축한 거예요.
사실 이 글의 숫자 중 가장 자랑스러운 건 빌드 속도 8초에서 741ms가 된 것도 아니에요. 3주 견적이 5일이 된 것이요. 그리고 두 번을 옮기면서 꼭 지킨 원칙이 하나 있어요.
사용자는 프레임워크를 몰라야 한다.
리서처들 중 누구도 NiceGUI가 뭔지, Next.js가 뭔지, Vite가 뭔지 몰라요. 알 필요도 없어요. 그들에게 AED는 “어제 쓰던 Holdings 화면”이고, “오늘도 그대로 작동해야 하는 도구”예요.
그래서 이주할 때 이걸 지켰어요.
/backtest/detail/{alphaId} 같은 경로는 이주 후에도 그대로예요. 북마크, 공유 링크가 안 깨지게요.이주 끝나고 리서처 한 명이 말했어요.
“오 뭐 바꿨어요? 좀 더 빨라진 것 같은데?”
이게 성공이에요. 마이그레이션의 진짜 성공은 “사용자가 알아채지 못한 것”이에요.
5일 스프린트에서 제가 가장 많이 배운 건 React도 Vite도 아니었어요. “이주를 이주 그 자체로 하면 안 된다”는 거였어요.
아무 준비 없이 NiceGUI를 열고 React로 한 페이지씩 옮겼으면, 아마 정말 3주가 걸렸을 거예요. 근데 그 3주가 5일이 된 건 이주를 위한 도구를 이주 전에 먼저 만들어뒀기 때문이었어요.
그리고 이주 중에 한 번 방향을 꺾는 결정도 배웠어요. 처음 정한 방향(Next.js)에 집착하지 않고, “왜 이걸 쓰고 있지?”라는 질문을 스스로 던질 수 있을 때, 진짜 맞는 도구에 도달할 수 있어요. Next.js를 시작한 지 며칠 되지 않아 Vite로 꺾은 건, 매몰비용을 인정하는 게 아니라 방향을 교정한 거였어요.
리소스가 없다는 건 핑계가 아니라 조건이에요. 개발자가 없으면 없는 대로, 디자이너가 없으면 없는 대로, 그 조건 안에서 어떻게 작업량을 1/4로 줄일지를 고민하는 게 기획자의 일인 것 같아요.
5일 스프린트가 끝난 다음 날, 한 글자 고치면 브라우저가 즉시 반응해요. 빌드가 8초에서 741ms가 됐고요. 이 느낌을 위해서 이주 전에 한 달간 쌓아둔 것들이 있었다는 걸, 이제는 잊지 않으려고요.
저는 자산운용사에서 퀀트 투자 전략 플랫폼의 기획과 프론트엔드를 담당하고 있어요. 5인 팀에서 기획, 디자인, 프론트엔드를 전담하고 있고, NiceGUI라는 Python 웹 프레임워크로 백테스트 결과를 분석하는 내부 도구를 만들고 있죠.
백테스트라는 건, 과거 데이터로 투자 전략을 시뮬레이션하는 거예요. “이 전략으로 2021년부터 투자했으면 어떤 결과가 나왔을까?”를 검증하는 과정이고, 그 결과를 분석하는 게 이 도구의 핵심 기능이에요.
이 도구에서 가장 중요한 화면이 백테스트 상세 페이지예요. 전략을 실행한 결과 — 수익률, 보유 종목, 매매 내역 — 를 분석하는 화면인데, 기존에는 성과/포트폴리오/분석 3개 탭으로 나뉘어 있었어요.
그러다 새로운 전략을 운용하는 팀과 미팅을 했어요. 주가가 떨어질 때 단계적으로 추가매수하고, 회복하면 파는 전략이에요. 이 전략의 매매 패턴을 분석하는 화면이 필요한 상황이었죠.
미팅에서 첫 번째 질문이 이거였어요.
“저 종목들로 매년 50%를 낼 수 있는 건가요?”
화면에는 누적수익률 차트 하나만 있었어요. 수익이 나긴 났는데, 왜 났는지, 어떤 종목이 기여했는지, 언제 어디서 벌었는지 — 이걸 보여주는 화면이 없었거든요.
이 글은 그 미팅 후 하루 동안, 막연한 질문들을 실제 인터랙티브 목업으로 만들어낸 과정이에요.
고객이 던진 질문들을 그대로 옮기면 이랬어요.
“기간을 찍었을 때 수익이 어떻게 났는지 확인해보자.”
“왜 이 종목이 선택됐는지, 왜 이 시점에 편입이 됐는지 알 수 있어야 해.”
“그 시점에 올랐는데, 그 기간에 대한 수익이 얼마나 났는지 기여도를 찾아볼 수 있으면 좋겠다.”
“그 안에서 매매했던 내용들이 다 보여지면 이해하기 쉬울 것 같아.”
“조금씩 모여서 수익을 냈는지 확인이 필요해.”
공통점이 있었어요. 전부 “왜”를 묻고 있다는 것. 수익이 났다는 건 알겠는데, 그게 어디서 어떻게 났는지를 모르겠다는 거예요.
기존에는 3개 탭으로 나뉘어 있었어요.
| 성과 | 포트폴리오 | 분석 |
|---|---|---|
| KPI, NAV 차트, Drawdown | Holdings, 비중 차트 | Trade History, Hit Ratio |
데이터 종류별 구분이라 깔끔해 보이지만, 유저의 사고 흐름과는 안 맞았어요.
“A종목이 8% 들어가있네” (포트폴리오 탭) → “그래서 얼마 벌었어?” (분석 탭으로 이동) → “언제 벌었어?” (매매 탐색이 없음) → “왜 그 시점에 샀어?” (어디에도 없음)
탭 3개를 왔다갔다 해야 하고, 가장 중요한 “왜”에 대한 답은 어디에도 없었어요.
여기서 선택지가 갈렸어요.
| 옵션 | 설명 | 판단 |
|---|---|---|
| A. 4번째 탭 추가 | 기존 3탭 + 매매 검증 탭 | 중복이 많아지고 탭 이동이 더 늘어남 |
| B. 기존 탭에 기능 삽입 | 포트폴리오 탭에 기여수익률 넣기 등 | 각 탭이 비대해지고 맥락이 섞임 |
| C. 3탭을 2탭으로 재구성 | 성과 요약 + 매매 탐색 | 기존 기능 100% 유지 + 신규 탐색 기능 |
C를 선택했어요. 유저의 질문이 크게 두 가지로 나뉘거든요.
위 이미지는 실제 화면이 아닌 구성 예시입니다.
가장 많이 고민한 부분이에요. 4단계 깊이의 드릴다운을 어떻게 자연스럽게 만드느냐.
페이지 전환? 탭이 끊기니까 맥락을 잃어요. 우측 패널? 차트 폭이 줄어들어요.
결론은 “누적수익률 차트 자체가 네비게이션 허브”가 되는 거였어요.
위 이미지는 실제 화면이 아닌 구성 예시입니다.
클릭하면 해당 날짜의 스냅샷이 차트 아래에 나타나요. 누적수익률, 일간수익률, 보유종목 수. 드래그하면 구간이 선택되고, 구간 수익률 + BM 대비 + 종목별 기여가 자동 계산돼요.
같은 차트에서 클릭과 드래그가 서로 다른 기능을 하는 건데, 이걸 자연스럽게 구분하는 게 꽤 까다로웠어요. 200ms 이내면 클릭(날짜 스냅샷), 그 이상이면 드래그(구간 선택)로 처리했죠.
고객이 가장 궁금해한 건 이거예요. “이 종목이 전체 수익에 얼마나 도움이 됐는지.”
기여수익률이라는 건, 업계에서 Brinson Attribution이라고 부르는 방법론이에요. 매일 “그 종목의 비중 x 그 종목의 수익률”을 계산해서, 기간 동안 합산하면 해당 종목이 포트폴리오 전체 수익에 기여한 정도가 나와요.
단순히 기여수익률 하나만 보여주면 부족했어요. 그래서 보유수익과 매매수익으로 분해했어요.
| 항목 | 의미 |
|---|---|
| 보유수익 (Holding Return) | 그냥 들고만 있었으면 가격 변동으로 벌거나 잃은 것 |
| 매매수익 (Trading Return) | 매매 타이밍으로 추가로 벌거나 잃은 것 |
| 효율 | 기여 / 비중. 1.0x 이상이면 비중 대비 효율적 |
이번 전략에서는 이 분해가 특히 중요했어요. 종목 자체가 많이 오르는 게 아니라, 하락할 때 추가매수하고 회복할 때 파는 타이밍에서 수익이 나는 전략이니까요. 매매수익이 높다는 건 매매 타이밍이 잘 먹히고 있다는 뜻이에요.
종목을 클릭하면 페이지 이동 없이 바로 아래에 펼쳐져요.
위 이미지는 실제 화면이 아닌 구성 예시입니다.
세 가지가 한번에 보여요.
사이클을 클릭하면 또 아래에 캔들차트 + 거래내역이 펼쳐지고요. 전부 같은 페이지 안에서 스크롤만으로 탐색할 수 있어요.
여기서 조심해야 할 게 있었어요. 기존에 Holdings 테이블에서 종목을 클릭하면 비중 차트에 오버레이가 되는 기능이 있었거든요. 이걸 매매 탐색 이동으로 바꿔버리면 기존 유저가 혼란스러워질 거예요.
해결은 간단했어요. 같은 행에 두 개의 진입점을 분리한 거죠.
기존 기능을 100% 보존하면서 새 기능을 추가하는 건, “어디에 넣느냐”보다 “기존 동작을 안 건드리느냐”가 더 중요하더라고요.
하나 더 고려한 게 있어요. 이 화면이 특정 전략에만 쓰이는 게 아니라는 점이에요.
기여수익률, 사이클 분석, 구간 분석 — 이건 모든 전략에 공통이에요. 하지만 이격도 차트, 매수 단계, 편입 사유 같은 건 이번 전략에 특화된 정보예요.
그래서 전략 태그 기반으로 조건부 표시하기로 했어요. 해당 태그가 있으면 전용 분석 차트가 보이고, 일반 전략에서는 숨겨지는 구조. 공통 기능은 모든 전략에서 동일하게 사용할 수 있고요.
미팅 끝나고 돌아와서, Claude와 핑퐁하면서 목업을 만들었어요.
기존 분석 사이트 두 곳을 브라우저로 직접 열어서 구조를 파악하고, 관련 소스코드에서 데이터 스키마를 확인하고, 기존 코드와 충돌 없는 설계를 잡고, HTML 인터랙티브 목업까지.
결과물은 2탭 구조의 전체 목업이에요.
고객이 “~를 보고 싶다”고 할 때, 바로 화면을 그리기 전에 거치는 단계가 생겼어요.
“뭘 보고 싶다”의 진짜 의미 파악 — “기간별 수익”이라고 했지만, 실제로는 “어떤 종목이 이 수익을 만들었는지”를 알고 싶은 거였어요.
기존 화면과의 관계 정리 — 새 기능이 기존 기능과 충돌하는지, 중복되는지, 자연스럽게 연결되는지.
데이터 존재 여부 확인 — 화면을 그리기 전에, 이 화면에 필요한 데이터가 실제로 있는지. 없으면 어떻게 계산하는지 산식까지 정리.
인터랙션 설계 — 같은 클릭이라도 어떤 맥락에서 어떤 결과를 보여줄지. “클릭 = 날짜 스냅샷, 드래그 = 구간 분석, 마커 클릭 = 종목 상세” 처럼 역할을 명확히 분리.
미팅에서 나온 막연한 질문이, 하루 만에 인터랙티브 목업으로 변환된 건 이 프레임워크 덕분이었어요. 다음에 비슷한 상황이 오면, 이 순서대로 풀어볼 생각이에요.
마감 5분 전. 30분 전까지 조용하던 3번 말에 갑자기 돈이 몰리기 시작했다.
AI는 “3번은 데이터상 별로”라고 했어요. 레이팅 낮고, 최근 성적 부진하고, 해당 거리 경험도 적고. 근거가 분명했어요.
근데 배당판은 다른 이야기를 하고 있었어요. 8.9배에서 2.8배로. 수만 명의 돈이 한 방향으로 움직이는 건, 데이터에 안 잡히는 뭔가를 시장이 알고 있다는 신호거든요.
AI를 믿었어요. 결과: 3번 1착. 전멸.
이건 경마 이야기가 아니에요. 데이터 분석 결과와 현장 신호가 충돌할 때, 기획자는 어느 쪽에 베팅하는가의 문제예요.

OpenClaw Lets Run 해커톤. 규칙이 독특했어요. 오직 AI 채팅만 허용, 직접 코딩하면 벌칙. 경마 데이터를 AI한테 던지고 분석시켜서 실제로 배팅하는 거예요.
사람이 할 수 있는 건 딱 하나 — AI한테 뭘, 어떻게 시키느냐. 기획서에서 요구사항을 정의하는 것과 구조적으로 같은 상황이었어요.
핸드폰 4대에 각각 다른 데이터를 띄워놓고 실시간 분석 중.
첫 경주에서 KRA 출마표 PDF를 AI한테 던지고 “이거 분석해줘”라고 했어요. AI가 뱉어낸 건 정보의 나열이었어요. 말의 레이팅, 최근 성적, 기수 승률, 마체중 변화… 2분 만에 정리해줬는데, “그래서 어떤 말에 걸어야 하는데?”에 대한 답은 없었어요.
기획서에 “사용자가 쉽게 비교할 수 있게 해주세요”라고 쓰는 것과 같은 문제였어요. “쉽게”가 뭔데? “비교”가 뭘 기준으로?
프롬프트를 깎았어요:
“이 거리(1800m)에서 출전 경험이 있는 말만 뽑아줘. 최근 3회 성적과 종반 200m 기록 기준으로 순위 매겨줘. 배당 변화가 30분 전 대비 30% 이상 떨어진 말을 따로 표시해줘.”
그제서야 의미 있는 결과가 나왔어요. 여기까지는 가설이 맞았어요. 요구사항의 해상도를 높이면, AI든 개발자든 결과물의 품질이 올라가는 구조.
근데 두 번째 경주에서, 이 가설이 깨졌어요.
두 번째 경주. AI가 해상도 높은 프롬프트로 분석한 결과는 깔끔했어요. 레이팅 상위, 거리 적성 검증됨, 최근 3회 성적 우수. 데이터상 완벽한 조합.
근데 마감 5분 전, 배당판이 흔들렸어요.
3번 말. AI 분석에서는 하위권이었던 말에 돈이 갑자기 몰리기 시작한 거예요. AI한테 다시 물어봤어요. “3번 말 배당이 급등하고 있는데, 어떻게 봐?” AI는 담담하게 답했어요: “현재 데이터 기준으로 3번은 추천 대상이 아닙니다.”
여기서 선택지가 갈렸어요:
| AI 분석 (정량 데이터) | 시장 신호 (배당 변화) | |
|---|---|---|
| 근거 | 레이팅, 거리 적성, 최근 성적 | 마감 직전 배당 8.9배→2.8배 |
| 해석 | 과거 데이터 기반 확률 | 수만 명의 실시간 판단 |
| 한계 | 현장 변수(컨디션, 내부 정보) 반영 불가 | 군중심리일 수 있음 |

AI를 믿었어요. 데이터가 근거가 있으니까. 논리적이니까.
3번 1착. 전멸.
이건 경마에서만 일어나는 일이 아니에요.
서비스 기획에서도 똑같은 충돌이 일어나요. 대시보드가 “이 기능은 사용률이 3%니까 삭제합시다”라고 말하는데, CS 채널에서는 “이 기능 없으면 안 돼요”라는 목소리가 계속 올라올 때. 데이터 분석은 “이 시장은 작아요”라고 하는데, 현장 영업팀은 “지금 분위기가 바뀌고 있어요”라고 할 때.
AI가 분석한 정량 데이터와 현장의 정성 신호가 충돌하면, 어느 쪽을 믿을 것인가. 이건 기획자가 매일 하는 판단이에요.
경마장에서 배운 건 이거예요:
문제는 “AI가 틀렸다”가 아니었어요. AI는 주어진 데이터 범위 안에서 정확하게 분석했어요. 문제는 AI가 볼 수 없는 데이터가 있었고, 그걸 판단하는 건 사람의 몫이라는 걸 무시한 거예요.
세 번째, 네 번째 경주에서 전략을 바꿨어요.
AI한테는 정량 분석만 시키고, 배당 변화 같은 시장 신호는 사람이 읽기로 했어요. 구체적으로:
1800m 경주. 직선 구간에서 순위가 뒤집히는 걸 보면 심장이 멈춘다.
전멸은 안 났어요. 대박도 안 났지만, 판단의 구조가 생긴 거예요. “AI가 이렇게 말했으니까”도 아니고, “감으로”도 아닌, AI 분석과 현장 신호 각각의 역할을 나눈 프레임워크.
동료 지웅님이 LinkedIn에 올린 말이 정확해요:
“텅 빈 지갑 대신, ‘이토록 빠르게 변화하는 실시간 환경에서 ML을 적용할 때 어떻게 접근해야 할까?‘에 대해 정말 깊게 고민해보는 값진 인사이트를 얻었습니다.”
이 경험 이후로, AI 기능을 기획할 때 이 질문을 먼저 해요:
“AI가 보는 데이터와 현장에서 오는 신호가 다를 때, 이 서비스는 어느 쪽을 따르게 설계할 것인가?”
AI 분석 결과를 그대로 보여주는 게 아니라, AI가 못 보는 맥락을 사용자가 보완할 수 있는 구조를 만드는 것. 그게 AI 서비스 기획자가 설계해야 할 경계선이에요.
경마장에서 지갑은 가벼워졌지만, AI 판단의 경계를 어디에 그을지는 꽤 선명해졌어요.
AI는 데이터로 판단하고, 시장(사람들)은 정보로 판단해요. 데이터는 과거를 정리한 것이고, 정보는 지금 누군가 알고 있는 것이죠. 두 신호가 같은 방향을 가리키면 확신이 생기지만, 충돌할 때가 진짜 기획의 순간이에요. 그 모순을 시스템이 어떻게 다루게 할 것인가 — AI가 판단을 멈추고 사람에게 넘겨야 하는 경계를 설계하는 것. 경마장에서 지갑보다 이게 더 선명해졌어요.
풀 리서치 리포트 보기 — 데이터, 방법론, 실험 결과를 논문 형식으로 정리했어요.
금융을 아는 PM이 직접 만들면.
금융을 이해하는 기획자, 기술로 검증하는 실행자.
에셋플러스자산운용에서 AI 투자 알고리즘 38개를 기획하고 운용심사를 통과시켰고, 200개 이상의 운용 계좌를 동시에 관리했어요. 현재는 알파브릿지에서 퀀트 리서치팀이 매일 쓰는 전략 분석 대시보드를 처음부터 다시 설계하고 있어요. 디자이너 없는 팀에서 20개+ 분석 페이지를 설계했고, AI 멀티에이전트 주식 분석 플랫폼을 혼자 기획부터 개발까지 했어요.
Resume학력
Johns Hopkins University
B.A. Economics · Minor in Marketing
현재
Alphabridge
2025 — Now
Domain
Finance · AI
Robo-advisor
Stack
ClickUp · Slack
GitHub · Claude
Contact