# [Claude Code + AI 에이전트] AI와 함께 만든 미국 주식 포트폴리오 대시보드: 테스트를 통과해도 실전에서 틀릴 수 있었다

📝 한줄 요약

미국 주식·ETF 한 계좌의 거래를 정확하게 기록하는 로컬 대시보드를 만들었습니다. 테스트 1,109개를 통과한 상태에서 실제 주식 API를 처음 호출했는데, 거기서 두 번 틀렸습니다. 이 글은 그 두 번을 어떻게 찾아냈는지에 대한 기록입니다.

바쁘시면 이것만 읽어도 돼요:

  • 차트부터 만들고 싶었지만, 제일 어려운 건 차트가 아니라 매수·매도가 반복돼도 평균단가가 한 푼도 틀리지 않는 거래원장이었습니다.

  • AI에게 코드를 맡기되 요구사항·검증 기준·최종 판단은 사람이 쥐었습니다. AI끼리도 구현·검수 역할을 나눴습니다.

  • 모의 응답으로 만든 테스트가 전부 통과했는데, 실제 API 응답에는 테스트에 있던 필드 하나가 아예 없었습니다.

  • 실제 데이터를 저장하고 나서야 "오늘 날짜 데이터는 아직 확정된 종가가 아니다" 는 걸 거래량을 보고 알아챘습니다.

  • 배운 것: '테스트 통과'와 '실제로 쓸 수 있다'는 같은 말이 아니었습니다.

🎯 이런 분들께 도움돼요

  • AI로 만든 결과물을 어디까지 믿어도 되는지 기준이 필요한 분

  • 돈·숫자를 다루는 도구를 만들면서 "이거 틀리면 안 되는데" 가 걱정인 분

  • 무료 API를 붙여보려는데 호출 한도와 요금이 무서운

  • AI 에이전트를 여러 대 쓰면서 역할을 어떻게 나눌지 고민 중인 분

😫 문제 상황 (Before)

처음에는 차트가 있는 주식 대시보드를 떠올렸습니다. 하지만 막상 만들기 시작하니 가장 어려운 문제는 차트가 아니라, 매수와 매도가 반복돼도 평균단가와 손익이 한 푼도 틀리지 않게 계산되는 거래원장이었습니다.

증권사 화면만으로는 제가 원하는 기준의 거래원장·이동평균단가·수수료 반영 실현손익을 한곳에서 보기 어려웠습니다. 관심종목, 환율, 위험 관리까지 욕심이 났지만, 그 전에 가장 먼저 틀리면 안 되는 것부터 만들기로 하고 범위를 줄였습니다. "한 계좌의 미국 주식·ETF 거래를 정확하게 기록하는 로컬 대시보드."

🛠️ 사용한 도구

  • 도구: Claude Code (구현), AI 에이전트 빅맥 (PM·QA), 독립 리뷰어 (읽기 전용 검수)

  • 기술: Streamlit 화면, DuckDB 저장, Python

  • 데이터: Financial Modeling Prep 무료 플랜 (하루 250회 한도)

  • 기록: Obsidian에 설계·프롬프트·결과 전부 남김


🔧 작업 과정

역할을 먼저 나눴습니다 — "AI가 알아서"가 아니라

이번에 제일 잘한 선택은 AI 사이에도 권한을 나눈 것입니다.

  • 저스틴(저): 목표, 범위, 중요한 제품 결정, 실제 서비스 가입과 외부 호출 승인

  • 빅맥: PM·QA. 완료 조건을 정하고, 숫자를 검증하고, 통합 보고

  • Claude Code: 테스트를 먼저 쓰고 그 다음 코드를 쓰는 방식으로 구현

  • 독립 리뷰어: 구현한 쪽과 분리해서, 반대 관점으로만 검수

특히 실제 외부 서비스 호출은 제 승인 없이는 못 하게 막아뒀습니다. 나중에 이게 크게 도움이 됩니다.


차트보다 먼저 — 10주 사고 2주 팔면 남은 8주의 원가는?

거래원장부터 만들면서 계속 물었던 질문은 이런 것들이었습니다.

10주를 사고 2주를 팔면 남은 8주의 원가는 어떻게 되나?
수수료는 평균단가에 넣나, 실현손익에서 빼나?
저장이 됐는지 안 됐는지 모를 때 자동으로 다시 시도해도 되나?

마지막 질문이 제일 중요했습니다. 저장 결과가 불확실할 때 프로그램이 알아서 재시도하면, 이미 저장된 거래가 한 번 더 들어갈 수 있습니다. 그래서 불확실하면 멈추고 사람에게 알리는 쪽으로 정했습니다. 보유 수량보다 많이 파는 입력도 저장 전에 막았습니다.

여기까지 오는 동안 화면은 아직 없었습니다. 숫자가 먼저였습니다.


무료 한도 250회를 어떻게 안 넘길 것인가

실제 주식 데이터를 붙일 차례가 되자 새로운 걱정이 생겼습니다. 무료 플랜은 하루 250회입니다. 실수로 반복 실행하면 그날은 끝입니다.

그래서 이렇게 정했습니다.

  • 호출하기 전에 오늘 몇 번 썼는지 먼저 기록하고, 그 다음에 호출

  • 실패한 호출도 한 번 쓴 것으로 셈 (실패는 한도를 소모하니까)

  • 기본 실행은 아무것도 건드리지 않는 미리보기(dry-run)

  • 진짜 호출은 명령에 --execute를 직접 붙여야만

미리보기를 돌리면 이렇게만 나옵니다. API 키는 "설정됨"이라고만 표시되고 값은 절대 찍히지 않습니다.

모드: dry-run (실제 호출·저장 없음)
종목(2): AAPL, SPY
기간: 2021-08-04 ~ 2026-08-03
예상 최대 호출 수: 2 (하루 상한 250)
API 키: configured

사건 1 — 테스트에는 있는데 진짜 응답에는 없는 필드

준비를 다 하고, 제 승인 아래 딱 2번만 실제로 호출했습니다. AAPL 하나, SPY 하나.

그런데 둘 다 실패했습니다.

응답은 정상이었습니다. HTTP 200에 22행이 왔습니다. 문제는 테스트에서 쓰던 가짜 응답에는 있던 adjClose(배당까지 반영한 종가) 필드가 실제 응답에는 아예 없었다는 것이었습니다. 프로그램은 그 필드를 필수로 요구하고 있었으니 전부 거부한 겁니다.

진단할 때도 규칙을 지켰습니다. 응답 원문과 API 키는 출력하지 않고, 필드 이름만 확인했습니다.

수정은 이렇게 했습니다. 그 필드가 있으면 원래대로 쓰고, 없으면 이미 검증된 종가를 대신 씁니다. 다만 값이 있는데 이상하면 조용히 대체하지 않고 거부합니다. 대체해버리면 API가 바뀐 사실 자체가 가려지니까요. 그리고 이 값은 배당까지 반영한 값이 아니라는 걸 코드에 분명히 적어뒀습니다.

테스트가 틀린 게 아니었습니다. 테스트가 현실의 응답을 충분히 닮지 못했던 것입니다. 이 경험으로 '테스트 통과'와 '실제 사용 가능'은 같은 말이 아니라는 걸 배웠습니다.

고친 뒤 AAPL 1,254행, SPY 1,254행, 총 2,508행이 5년치로 저장됐습니다. 중복·빈 값·음수·앞뒤가 안 맞는 가격은 0건이었습니다.


사건 2 — 거래량이 이상한데요?

저장된 데이터를 훑어보다가 숫자 하나가 눈에 걸렸습니다.

종목

8월 4일 거래량

8월 3일 거래량

AAPL

12,962,987

75,051,951

SPY

8,199,359

58,881,217

전날의 6분의 1도 안 됩니다. 수집한 시각이 미국장이 열린 지 얼마 안 된 때였습니다. 즉 이 숫자는 그날의 최종값이 아니라 아직 진행 중인 값이었습니다. 공식 문서를 보니 가격·거래량 데이터는 5~15분마다 갱신된다고 돼 있었습니다.

여기서 재미있는 일이 생겼습니다. 저희는 "이미 저장한 데이터는 덮어쓰지 않는다" 는 안전 규칙을 두고 있었습니다. 중복 저장과 예기치 않은 수정을 막으려던 규칙인데, 장중 값을 먼저 저장해버리니 오히려 그 값이 영영 확정값으로 안 바뀌게 된 겁니다.

안전 규칙끼리 부딪힌 셈입니다. 그래서 미국 동부시간 16시 30분(장 마감 + 반영 여유) 전에는 그날 데이터를 아예 받지 않도록 경계를 넣었습니다. 날짜를 직접 지정해도 조용히 잘라내지 않고 거부합니다.

실행할 수 없습니다: --to는 2026-08-03보다 뒤일 수 없다: 2026-08-04.
미국장 마감 후 그날 일봉이 확정된 뒤에 실행해야 한다

이 수정은 구현과 테스트(1,133개 통과)를 마쳤고, 지금은 검수를 기다리는 중입니다. 이미 저장돼버린 장중 데이터 2행도 백업 후 정리할 예정입니다. 아직 끝난 게 아닙니다.


✅ 결과 (After)

지금 되는 것

항목

상태

거래 추가·조회·수정

삭제와 복구 (되돌릴 수 있는 삭제)

보유 수량·평균단가·누적원가·실현손익

초과매도·잘못된 입력 차단

실제 주식 가격 5년치 수집

호출 한도 관리와 미리보기 실행

현재가·평가금액·미실현손익

⏳ 연결 전

환율·차트·관심종목·위험 관리

⏳ 다음 단계

현재 화면

⚠️ 아래 화면은 실제 투자내역이 아니라 임시 DB의 데모 데이터입니다.

데모 거래 3건(AAPL 10주 매수 → 2주 매도, SPY 3주 매수)을 넣으면 보유 종목 2개, 활성 거래 3건, 누적 실현손익 $39.30, AAPL 8주·SPY 3주가 계산돼 나옵니다.

현재가와 평가금액 칸은 준비 전이라고 표시됩니다. 0원으로 채우지 않았습니다. 된 것과 안 된 것을 화면에서 구분하는 게 낫다고 판단했습니다.

💬 이 과정에서 배운 AI 활용 팁

효과적이었던 것

  1. AI에게 "구현"을, 사람에게 "검증 기준"을 맡기기. 코드를 많이 쓰게 하는 것보다, 무엇을 믿어도 되는지 판단하는 기준을 만드는 게 훨씬 중요했습니다.

  2. 구현하는 AI와 검수하는 AI를 분리하기. 같은 AI에게 "네가 만든 거 검토해봐"라고 하면 자기 가정을 그대로 통과시킵니다. 반대 관점만 보는 역할을 따로 뒀습니다.

  3. 외부 서비스 호출은 사람 승인을 거치게 만들기. 이번에 실제 호출은 딱 2번이었습니다. 무료 한도를 태우지 않았습니다.

  4. 실패를 숨기지 않게 시키기. "데이터가 없으면 0으로 채우지 말고 '없음'이라고 표시해"라고 처음부터 못 박았습니다.

이렇게 하면 안 돼요

  1. 가짜 응답으로 만든 테스트를 100% 믿기. 저희는 1,109개를 통과한 상태에서 실제 API에 처음 붙었다가 바로 틀렸습니다. 가능하면 일찍, 최소 범위로 실제 호출을 해보세요.

  2. 모든 희귀한 오류를 출시 전에 다 막으려 하기. 끝이 안 납니다. 정상 사용 흐름·비밀정보 노출·데이터 손상만 "지금 고칠 것"으로 삼고 나머지는 미뤘습니다.

  3. "AI가 다 만들어줬다"고 생각하기. 이번에 발견한 두 문제는 둘 다 실제 데이터를 사람이 눈으로 보다가 찾았습니다. 거래량 숫자가 이상하다고 느낀 건 AI가 아니었습니다.

🌍 다른 업무에 적용한다면?

숫자가 틀리면 곤란한 모든 자동화에 그대로 적용됩니다. 정산, 재고, 근태, 매출 집계 같은 것들이요. 핵심은 세 가지입니다. ① 화면보다 계산을 먼저 맞춘다 ② 외부에서 받아온 데이터는 형식을 의심한다 ③ 확실하지 않으면 자동으로 재시도하지 말고 사람에게 알린다.

🚀 앞으로의 계획

  1. 미국장 확정 데이터 경계 검수 마무리, 잘못 저장된 2행 정리

  2. 현재가·평가금액·미실현손익을 화면에 연결

  3. 실제 데이터가 없어도 볼 수 있는 데모 모드

  4. 원/달러 환율과 원화 표시

  5. 가격 차트, 관심종목, 위험 관리

📋 재사용 가능한 프롬프트

프롬프트 1: 돈·숫자를 다루는 기능 만들 때

[만들 기능]을 구현해줘. 단, 다음을 지켜줘.

  • 데이터가 없으면 0이나 빈 값으로 채우지 말고 "없음"으로 표시할 것

  • 저장이 성공했는지 불확실하면 자동으로 재시도하지 말고 멈추고 알릴 것

  • 계산이 틀릴 수 있는 경계(반올림, 나눗셈, 수수료 반영 위치)를 먼저 나에게 질문할 것

  • 테스트를 먼저 쓰고, 실패하는 걸 확인한 다음 코드를 쓸 것

프롬프트 2: 외부 API를 처음 붙일 때

[API 이름]을 연동해줘. 실제 호출 전에 아래를 먼저 준비해줘.

  • 기본 실행은 아무것도 건드리지 않는 미리보기(dry-run)

  • 실제 호출은 내가 명시적으로 옵션을 붙였을 때만

  • 하루 호출 한도를 코드에 상한으로 두고, 실패한 호출도 한도에 포함

  • API 키와 응답 원문은 화면·로그·오류 메시지 어디에도 출력하지 말 것
    준비가 끝나면 실제 호출은 [대표 항목 1~2개]만, 내 승인을 받고 진행해줘.

프롬프트 3: AI가 만든 결과를 검수시킬 때

방금 구현한 코드를 수정하지 말고 읽기만 해서 검수해줘.

  • 정상 사용자 흐름을 막는 문제만 찾을 것

  • 각 문제는 재현 방법과 실패하는 테스트를 함께 제시할 것

  • 추측이 아니라 실제로 재현되는 것만 보고할 것

  • 희귀한 예외 상황은 별도 목록으로 분리할 것


이번 프로젝트에서 가장 크게 배운 점은, AI에게 코드를 많이 쓰게 하는 것보다 무엇을 믿어도 되는지 검증하는 기준을 만드는 일이 더 중요하다는 것이었습니다. 앞으로도 완벽한 기능 목록보다, 실제로 써보고 발견한 문제를 다음 개발 순서로 삼으려고 합니다.

1
밀어주고 끌어주는

온·오프라인 AI 스터디

AI로 어디까지 할 수 있는지
직접 확인하실 분만 신청하세요.