지난 글에서는 엑셀 자동화 도구를 웹 서비스로 전환하면서, 데이터를 하나의 원본으로 모으고 접근과 출력의 폭을 넓힌 과정을 다뤘습니다. 여러 사람이 함께 쓰고, 사람뿐 아니라 AI도 같은 데이터를 조회할 수 있게 되었습니다.
그런데 과거의 거래내역만 쌓인 시스템은 현재의 가치를 보여주지 못합니다. “지금 내 자산은 얼마이고, 그동안 얼마를 벌었나”에 답을 못합니다. 매입가와 거래내역은 모두 과거의 숫자입니다. 오늘의 가치를 알려면 외부의 현재가 정보가 필요합니다. 외부 데이터와 끊겨 있는 시스템은 사실상 멈춰 있는 닫힌 시스템이었고, 외부와 연결되는 순간 비로소 살아 움직이는 시스템이 됩니다. 1편과 2편에서 만든 것은 그 연결을 받아낼 준비 작업에 가까웠습니다. 외부 세계와 이어지는 이번 단계가 실질적인 진화 단계입니다.
이번 글에서 다룰 외부 연결은 크게 세 가지입니다. 외부의 시세 정보를 반영하고, 증권사에서 거래 데이터를 직접 가져오고, 외부망에서도 서비스를 이용할 수 있게 하는 것입니다. 이를 진행하는 과정에서 중요한 점은 연결할 기준과 적용 방식을 정하는 일이었습니다. 앞서 「바이브 코딩, 제대로 하는 법 — 10가지 원칙」에서 정리한 원칙들이 이 단계에서 어떻게 작동했는지도 함께 보겠습니다.

목 차
닫힌 시스템에서 열린 시스템으로
V1~V4의 입력은 모두 직접 업로드한 파일이 전부였습니다. 거래를 정확하게 기록하고 여러 관점으로 조회할 수 있었지만, 그 안의 숫자는 모두 과거입니다. 언제 얼마에 샀고 얼마에 팔았는지는 알아도, 지금 그 종목이 얼마인지를 알 수 없습니다. 아직까지는 잘 정리된 기록 보관소일 뿐, 판단을 돕는 도구는 아니었습니다.
자동화와 앱 개발이 향하는 곳은 결국 이 판단을 돕는 도구입니다. 외부 시세가 들어와야 가치를 평가할 수 있게 되고, 평가가 있어야 의사결정으로 이어집니다. 그래서 지금까지가 준비 단계였다면, 외부와 연결되는 이번 단계가 실질적 목적에 닿는 지점입니다.
외부 연결은 하나가 아니라 세 방향으로 나뉘었습니다. 첫째는 외부 시세를 들여오는 연결입니다. 종목을 식별하고, 가격을 받아오고, 그 위에서 평가와 수익률, 대시보드가 만들어집니다. 외부 연결에서 가장 중요한 부분입니다. 둘째는 증권사 API에서 거래 데이터를 직접 가져오는 연결이고, 셋째는 집 밖에서도 안전하게 서비스에 접속하는 연결입니다.
아래에서 이 순서대로 살펴보겠습니다.
연결 ① 시세 정보 반영
보유한 주식 종목에 대한 현재 시세 정보를 반영해야 평가금액이 생기고, 평가금액이 있어야 수익률을 계산할 수 있고, 대시보드로 시각화를 할 수도 있습니다. 종목을 식별하는 일부터, 시세를 받아 캐시하는 일, 평가와 수익률을 계산하는 일, 그리고 그것을 대시보드로 묶는 일까지 차례로 다루겠습니다.

종목 식별
시세를 붙이기 전에 먼저 풀어야 할 문제가 있었습니다. 업로드한 종목명과 표준 종목코드를 잇는 일입니다.
현실적으로 RAW 파일에 적힌 종목명만으로는 가격을 바로 가져올 수 없습니다. 같은 이름이 서로 다른 종목을 가리킬 수 있고, 보통주와 우선주가 비슷한 이름을 쓰기도 합니다. ETF나 해외 주식, 같은 이름의 국내외 종목이 겹치는 경우도 있습니다. 종목명만 보고 가격을 매핑하면 엉뚱한 종목의 시세가 붙을 위험이 있습니다.
그래서 종목 식별을 별도의 단계로 두었습니다. 종목 마스터에 시장 종류, 종목코드, 통화, 출처를 기록하고, 원본 종목명과 실제 종목을 연결하는 별칭(alias) 테이블을 따로 관리합니다. 종목 매핑을 실행하면 업로드된 모든 고유 RAW 종목명이 종목 마스터에 등록되고 별칭으로 연결됩니다. 다만 자동으로 등록된 이름이 시세 조회용 실제 종목과 정확히 맞지 않을 수 있어서, 종목 매핑 화면에서 종목명 검색과 수동으로 직접 연결하는 방식도 유지했습니다.
여기서 한 가지 원칙을 분명히 했습니다. 종목코드가 확인되지 않은 종목을 별도로 관리하는 것입니다. 해당 종목 가격을 매수가격이나 0으로 처리하면 평가금액 합계가 왜곡되고, 결국 잘못된 정보를 제공하게 됩니다. 그래서 가격정보가 없거나 매핑이 안 된 종목은 “가격 없음” 또는 “매핑 필요” 상태로 따로 표시하고, 평가 합계에서 제외한 뒤 “평가 불가 종목 N개”로 표시하게 했습니다.
시세 캐싱
종목이 식별되면 시세를 가져옵니다. 평가금액과 평가손익은 외부 공개 시세 데이터를 사용합니다. 국내 종목은 날짜별 종가 기준으로 한 번에 받아오는 방식을 적용했고, 출처는 한국거래소(KRX), 공공데이터, 네이버 순서로 시도합니다. 해외 종목과 환율은 Yahoo 데이터를 사용했고, 환율은 평가일별로 저장합니다.
가격 데이터는 매 조회마다 외부를 호출하지 않고 DB에 캐싱하도록 했습니다. 외부 서비스는 호출이 잦으면 제한에 걸릴 수 있고, 과거 날짜의 같은 종가를 반복해서 받아올 이유도 없기 때문에, 한 번 받은 가격은 저장해 두고 다시 사용합니다. 기준일이 휴장일이면 그 직전 영업일의 종가를 사용하되, 화면에는 실제로 사용한 가격일을 함께 표시했습니다. 사용자가 어떤 날짜의 가격으로 평가됐는지 확인할 수 있어야 하기 때문입니다.
이 가격 데이터를 다루는 관점이 중요했습니다. 시세와 그 위에서 만들어지는 스냅샷은 모두 언제든 다시 만들 수 있는 ‘파생 데이터’입니다. 원본은 어디까지나 거래내역입니다. 가격이나 계산식이 바뀌면 파생 데이터는 전체를 다시 생성하면 되고, 그 과정에서 원본 거래는 건드리지 않습니다. 1편에서 정답지로 삼았던 거래 데이터의 역할이 여기서도 그대로 유지됩니다.
해외 종목은 원화로 환산할 때 가격의 통화와 환율 기준일을 함께 저장했습니다. 종가 기준일과 환율 기준일이 어긋나면 환산 결과가 흔들릴 수 있어서, 평가일별 환율을 따로 관리하고 누락된 날짜만 채우는 방식으로 처리했습니다.

평가금액과 수익률
시세가 붙으면 평가가 가능해집니다. 보유수량에 기준일 종가를 곱하면 평가금액이 나오고, 거기서 매수가 기준 보유금액을 빼면 평가손익이 됩니다. 기준일 현황 화면에서 특정 날짜 기준으로 누적 매도수익, 배당, 수수료, 세금과 함께 평가금액, 평가손익, 평가수익률을 볼 수 있게 했습니다.
수익률은 세 가지 방식으로 제공하기로 했습니다. TWR, Modified Dietz, XIRR입니다. 세 지표는 모두 “얼마나 벌었나”를 계산하지만, 입출금의 타이밍을 다루는 방식이 다릅니다.
- TWR(시간가중수익률) — 평가 기준일 사이의 외부 현금흐름을 제거하고 기간별 성과를 이어 붙입니다. 입출금 타이밍의 영향을 걷어내고 자산 자체의 성과를 봅니다.
- Modified Dietz — 기간 중 들어오고 나간 현금을 그 현금이 머문 일수로 가중해 반영합니다. 매일의 평가 없이도 기간 수익률을 근사할 수 있는 방식입니다.
- XIRR — 실제 입출금이 발생한 날짜와 종료 시점 평가금액을 현금흐름으로 놓고 내부수익률을 구합니다. 언제 돈을 넣고 뺐는지가 결과에 그대로 반영됩니다.
같은 계좌라도 세 숫자가 다르게 나올 수 있습니다. 어느 하나가 맞고 나머지가 틀린 것이 아니라, 보는 관점이 다른 것입니다. 그래서 수익률 숫자를 누르면 계산 과정을 볼 수 있는 리포트를 따로 두었습니다. 구간별 평가값, 현금흐름, 분자와 분모 산식을 펼쳐 사용자가 숫자의 근거를 확인할 수 있게 했습니다.
계산의 경계를 정하는 일도 까다로웠습니다. 외부 현금흐름은 입금과 출금만 반영하고, 환전과 매매 정산성 입출금은 제외했습니다. 주식을 사면서 빠진 출금, 팔면서 들어온 입금은 이미 거래금액에 반영되어 있어서, 이를 다시 현금흐름으로 넣으면 같은 돈을 두 번 세게 됩니다. 환전은 외부에서 새로 들어온 투자금이 아니라 통화만 바꾼 것이므로 역시 제외했습니다.
잔고를 처리하는 방식이 좀 까다로웠습니다. 현재는 완벽한 회계 장부를 만들기보다는, 업로드한 파일에서 확인되는 예수금을 기준점(checkpoint)으로만 저장해 수익률 계산의 보조 자료로 썼습니다.
이 계산들은 정답이 비교적 분명한 영역입니다. 입출금과 평가금액이 주어지면 기대값이 정해지기 때문입니다. 그래서 현금흐름이 없는 기간, 중간에 입출금이 있는 기간, 종료 평가금액만 있는 기간을 각각 검증 시나리오로 만들어 기대값과 맞는지 검증했습니다. 1편에서 만든 정답지의 사고방식이, 금융 계산이라는 더 까다로운 영역으로 옮겨온 셈입니다.
대시보드
특정 날짜의 수익률 현황을 보는 것 외에도, 주어진 기간내의 연속적 변화, 두 날짜의 비교까지 보려면 별도의 화면이 필요했습니다. 그래서 별도의 대시보드 메뉴를 두고, 기준일 현황, 기간 변화, 날짜 비교의 세 가지 방식을 제공했습니다.
V4에서 통계를 정확히 맞추기 위해, 조회할 때 매번 계산하는 대신 쓰기 작업 시점에 누적 포지션을 미리 저장하는 방식을 적용했습니다. 대시보드는 그 방식을 시간 축으로 확장한 것입니다. 거래가 있는 날짜마다 그날의 보유와 손익 상태를 스냅샷으로 저장해 두고, 조회할 때는 저장된 값을 읽습니다.
문제는 속도였습니다. 처음에는 대시보드를 열 때마다 세 가지 수익률을 다시 계산했고, 기준일이 바뀔 때마다 전체 거래를 처음부터 누적하는 구조였습니다. 화면이 느려졌고, 재계산이 길어지면 DB에 락이 걸려 다른 작업까지 영향을 받았습니다. 해결 방향은 단순했습니다. 한 번 계산한 것은 다시 계산하지 않는 것입니다.
그래서 스냅샷 사이에 증분 구조를 도입했습니다. 새 기준일의 값이 필요하면 가장 가까운 이전 스냅샷의 누적 상태를 이어받아, 그 사이에 늘어난 거래와 잔고, 가격, 환율만 반영합니다. 수익률 계산 결과도 기준일과 조건별로 저장해 두고, 같은 조건의 요청은 저장된 값을 재사용합니다. 거래가 바뀌거나 명시적으로 재계산을 요청할 때만 영향받은 기간을 다시 계산합니다. 여기에 더해, 업로드와 삭제, 가격 갱신이 제각기 다른 경로로 파생 데이터를 건드리던 것을 하나의 진입점으로 모아, 무엇을 어떤 순서로 다시 계산할지 한곳에서 결정하도록 정리했습니다.
연결 ② 증권사 API 연동

두 번째 연결은 데이터를 가져오는 경로 자체를 바꾸는 일이었습니다. 지금까지 거래 데이터는 사람이 증권사에서 파일을 내려받아 업로드하는 방식이었습니다. 주 거래 증권사인 키움증권의 경우 공식 REST API를 제공하므로, 이를 통해 거래내역을 직접 가져올 수 있는지 확인했습니다.
여기서 구조를 한 겹 나눴습니다. 키움 API를 직접 호출하는 별도의 로컬 API 서버를 두고, 본 시스템은 그 서버를 통해서만 키움 데이터를 받도록 한 것입니다. 이렇게 한 이유는 인증 정보의 경계 때문입니다. 키움 API를 쓰려면 발급받은 app key와 secret이 필요한데, 이 값이 주식 거래 관리 시스템 본체나 브라우저로 흘러가지 않도록 별도 서버로 분리한 것입니다. 호출하는 쪽과 호출받는 쪽의 인증을 구분했기 때문에, 주식 거래 관리 시스템에서는 그 서버를 부를 자격을 증명하는 별도의 키만 가지고, 키움 인증 정보 자체는 알지 못합니다. 외부 응답이나 로그에도 계좌번호 원문이나 비밀 키가 남지 않게 했습니다.
이렇게 가져온 데이터는 파일 업로드와 같은 흐름을 타도록 했습니다. 증권사 API에서 온 데이터든 사람이 올린 파일이든, 같은 정규화 과정을 거쳐 같은 형태로 저장됩니다. 입력 경로가 갈라지면 유지보수가 두 배로 늘어나기 때문입니다. 키움 API로 가져온 데이터도 RAW 데이터로 보관하고, 기존의 자료 입력, 삭제, 재계산 등 모든 추적 흐름을 재사용했습니다. 중복은 응답 단위의 해시와 거래 단위의 식별값을 함께 보고 막았습니다.
공식 개인 API가 확인되지 않은 미래에셋증권과 삼성증권은 기존의 파일 업로드 방식을 유지했습니다. 비공식 스크래핑이나 화면 자동화는 보안과 약관 위험 때문에 처음부터 범위에서 제외했습니다. 한편 V4에 반영된 MCP의 경우, 외부로 열리는 환경에서는 그 통로도 더 조심스럽게 다뤄야 합니다. 그래서 MCP의 외부 공개는 보수적으로 접근하고 매수·매도 주문 같은 기능은 아직 구현하지 않았고 추후 검토할 예정입니다.
연결 ③ 외부 접속

세 번째 연결은 시스템 자체를 외부로 여는 일이었습니다. 서버로 이용중인 Mac mini를 인터넷에 직접 노출하지 않으면서 집 밖에서 안전하게 쓸 수 있는 방법으로 Cloudflare Tunnel을 선택했습니다. 공유기 포트를 열거나 고정 IP를 두는 대신, Mac mini가 바깥으로 나가는 연결만 유지하고 그 연결을 통해 외부 요청이 들어오는 방식입니다. 들어오는 포트를 열지 않으니 집 네트워크의 노출면이 줄고, 실제 IP도 드러나지 않습니다. 사용자는 고정 주소로 접속하지만, 내부 운영 구조는 기존의 포트포워딩 방식과 다릅니다.
접속 경로가 열리면 인증을 다시 봐야 합니다. 2편까지의 로그인은 내부 네트워크를 전제로 한 방식이었습니다. 외부로 열면 그 전제가 더 이상 성립하지 않습니다. 그래서 인증을 계층으로 나눴습니다. 외부 진입점에서는 Google 계정 기반의 승인된 세션만 통과시키고, 외부에서 들어온 쓰기 요청은 출처를 한 번 더 확인하도록 했습니다. 반면 내부 네트워크에서는 기존의 로컬 로그인을 그대로 유지했습니다. 같은 서비스라도 외부에서는 로컬 회원가입과 ID/비밀번호 로그인 화면을 숨기고, 내부에서는 그대로 두는 식으로 입구를 분리한 것입니다.
외부로 열면, 실제 가족 데이터와 상관없이 화면만 둘러볼 상황도 생깁니다. 그래서 운영 데이터와 분리된 점검용 계정을 따로 두었습니다. 외부에서 화면을 확인하거나 모바일 사용성을 점검할 때 이 계정을 쓰면 실제 거래 데이터를 건드리지 않습니다. 점검을 위해 잠시 권한을 높였다가 끝난 뒤 되돌리는 식으로, 점검 행위가 운영 데이터에 영향을 주지 않도록 분리했습니다.
주식 거래 관리 시스템 화면
세 가지 외부 연결이 더해지면서 시스템의 모습도 달라졌습니다.
자료 매핑, 거래내역 조회, 계좌별 요약, 대시보드, 수익률 리포트까지 V5에서 구현한 주요 화면입니다.






AI 협업 방식
이번 단계에서 AI와의 협업은 무게중심이 한 번 더 올라갔습니다. 외부 시세 연동, 환율 환산, 세 가지 수익률 계산 등은 제가 잘 모르는 영역입니다. 이 부분에서 AI의 효용성은 매우 컸습니다. 모르는 개념을 파악하고 결정을 내리는 과정도 AI와 충분한 대화를 하면서 작업을 진행할 수 있었습니다. 특히 TWR, Modified Dietz, XIRR 와 같은 생소한 개념을 듣고 이해하는 것과 올바르게 구현되었는지 확인하는 일은 전혀 다른 차원의 일이었습니다.
그렇기 때문에 이런 영역일수록 결과를 신뢰하는 근거가 중요해집니다. 그 근거가 이번에는 기대값이 분명한 테스트였습니다. 제가 한 일은 계산식을 한 줄씩 검토하는 것이 아니라, 무엇을 입력으로 보고 무엇을 기대값으로 둘지를 정하는 것이었습니다. 수익률 계산은 입출금과 평가금액이 주어지면 답이 정해지므로, 다양한 상황을 검증 시나리오로 만들어 두면 AI가 작성한 코드가 맞는지 그 자리에서 확인할 수 있습니다.
경계를 정하는 결정도 마찬가지였습니다. 환전을 현금흐름에서 빼는 것, 정산성 입출금을 중복으로 보지 않는 것, 가격 없는 종목을 0으로 두지 않는 것은 모두 제가 정해서 문서에 남긴 기준입니다. 키움 인증 정보를 별도 서버에 격리한 것이나, 외부와 내부의 입구를 나눈 것도 같은 성격의 결정이었습니다. AI는 그 기준 위에서 구현했고, 기준이 분명한 만큼 익숙하지 않은 영역에서도 방향이 크게 어긋나지 않았습니다. 익숙하지 않을수록, 직접 구현하는 능력보다 무엇을 기준으로 삼을지 정하고 그 기준으로 검증하는 능력이 더 중요해진다는 점을 다시 확인했습니다.
맺음말
세 편에 걸쳐 하나의 도구가 구현되는 과정을 정리했습니다. 1편은 입력의 폭을 넓혀 사람이 하던 일을 자동화했고, 2편은 접근과 출력의 폭을 넓혀 여러 사람이 함께 쓰는 서비스로 만들었습니다. 그리고 3편에서 외부 세계와 연결되면서, 멈춰 있던 기록 보관소가 비로소 살아 움직이는 시스템이 되었습니다. 시세를 들여오고, 증권사에서 거래내역을 직접 가져오고, 집 밖에서도 접속할 수 있게 해주는 연결을 통해서 그 전환을 만들었습니다. 연결이 하나 늘어날 때마다 무엇을 기준으로 삼을지 다시 정했고, 그 기준을 문서와 테스트로 고정한 것이 전체를 관통한 방식이었습니다.
돌아보면 이 과정 전체가 AI 전환의 한 단면이기도 합니다. 기존에 동작하던 것을 버리지 않고, 점진적으로 확장하며, 매 단계를 검증과 기록으로 통제하는 것. 새로운 도구를 들이는 일은 한 번에 모든 것을 바꾸는 것이 아니라, 정답지를 지키면서 받아들일 수 있는 폭을 넓혀 가는 일에 가까웠습니다.
이로써 이번 시리즈에서 다루려 한 단계는 일단락됐습니다. 다음 작업은 두 갈래로 이어집니다. 하나는 빠르게 만든 화면을 더 다루기 쉬운 구조로 다시 정리하는 일이고, 다른 하나는 그 위에 자산 구성이나 비중 같은 판단을 돕는 분석을 얹는 일입니다. 기록하고, 조회하고, 평가하는 단계를 지났으니, 이제는 그 데이터가 무엇을 말하는지 읽어 내는 쪽으로 가게 될 것 같습니다. 좀 더 확장된 가능성을 본다면, 조회에서 시작한 증권사 연동이 자동매매로 이어질 가능성도 열려 있습니다. 다만 그 단계는 신중하게 다가가야 할 영역입니다.
외부와 끊긴 기록은 멈춰 있습니다. 연결되어야 비로소 살아 움직입니다.
ChulJoo Kim (김철주)
※ 참고문헌
- 키움증권, 「키움 REST API」, openapi.kiwoom.com.
https://openapi.kiwoom.com - Cloudflare, 「Cloudflare Tunnel」, Cloudflare Docs, developers.cloudflare.com.
https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/
ckarch.kr
© 2026
is licensed under
CC BY-NC-SA 4.0