Skip to Content
Frontend개인 자산 대시보드와 시장 데이터 분리
🎨 Frontend2026년 5월 16일

개인 자산 대시보드와 시장 데이터 분리

#fastapi#react#sqlite#dashboard
개인 자산 대시보드와 시세 조회 도구1 / 2
FastAPI·SQLite·React로 개인 자산과 시장지표를 보는 Quant Vault를 만들었습니다. 직접 입력한 보유 정보와 외부 시세를 구분하고 가격 기준을 수정한 과정을 정리합니다.

보유 자산과 관심 종목, 시장지표를 한 화면에서 보고 싶어 Quant Vault를 만들었습니다. API는 FastAPI와 SQLite로, 화면은 React와 TypeScript로 구성했습니다.

개인 자산의 수량과 매입 정보는 직접 관리하고 가격은 외부에서 가져옵니다. 서로 다른 경로의 자료를 조합하는 화면이라 어떤 값을 입력했고 어떤 시세를 사용했는지 구분하는 것이 중요했습니다.

직접 입력한 자산과 외부 시세

보유 수량과 매입 정보를 입력하면 외부 시세와 조합해 평가금액과 손익을 표시하도록 했습니다. 관심 종목과 종목 검색, 시장지표, 미니 차트도 추가했습니다.

자료관리 방식
보유 수량·매입 정보직접 입력·수정
현재가·이전 종가외부 출처 조회
재무 정보별도 출처와 캐시
평가금액·손익입력값과 시세로 계산

계산식이 맞아도 원본 시세가 오래되거나 다른 거래 구간의 값이면 화면 해석이 달라집니다. 숫자를 표시하는 기능 외에 가격의 기준도 확인해야 했습니다.

현재가 조회 방식

해외 시세에서는 일봉 대신 분봉과 장전·장후 자료를 포함해 조회하는 방식으로 바꿨습니다. 이전 종가도 응답 필드의 우선순위와 대체 경로를 정리했습니다.

이 수정은 조회한 값의 시점과 거래 구간을 구분하기 위한 것입니다. 공개 출처의 응답을 거래소의 확정 가격과 같은 값으로 보장하는 구성은 아닙니다.

차트는 당일과 최근 기간을 선택할 수 있게 했습니다. 기준선 위아래의 색을 달리해 가격의 변화 방향도 함께 볼 수 있도록 구성했습니다.

계산에 쓰는 값과 화면의 표시

예를 들어 가상의 자산 3개를 평균 10,000원에 보유하고 있고 조회 가격이 11,000원이라면 평가금액은 33,000원, 매입금액은 30,000원, 차이는 3,000원입니다. 가격의 통화와 보유 정보의 통화가 같다는 전제가 있어야 이 계산을 바로 할 수 있습니다.

python
example/holding_value.py
from decimal import Decimal quantity = Decimal("3") average_cost = Decimal("10000") price = Decimal("11000") cost_basis = quantity * average_cost market_value = quantity * price gain = market_value - cost_basis gain_pct = gain / cost_basis * 100 if cost_basis else None assert (market_value, gain, gain_pct) == ( Decimal("33000"), Decimal("3000"), Decimal("10") )

이 코드는 계산 전제를 보여주기 위한 Decimal 예시입니다. 현재 앱의 구현을 Decimal로 바꿨다는 뜻은 아닙니다. 실제 backend/app/valuation.py는 float로 계산하고 응답 단계에서 금액과 비율을 반올림합니다. 통화가 다른 자산을 합칠 때 필요한 환산 기준도 개별 자산의 단순 곱셈과 별도로 봐야 합니다.

시세가 없을 때 남는 동작

현재 확인한 소스에는 시세를 찾지 못하면 매입가를 평가에 사용하는 부분이 있습니다. 다음은 해당 처리의 발췌입니다.

python
example/current-price-fallback.py
latest_price = snapshot["price"] if snapshot else None quantity = float(row["quantity"]) average_cost = float(row["average_cost"]) market_value = quantity * float(latest_price or average_cost)

이 경우 최신 시세가 없어도 화면에 평가금액은 생길 수 있습니다. 그것은 새 시세를 조회했다는 뜻이 아니므로 latest_price와 data_source를 함께 봐야 합니다. or를 사용하는 현재 코드에서는 숫자 0도 매입가 대체 경로로 들어갑니다. 이를 이번 글에서 이미 고친 기능처럼 쓰지는 않았습니다.

상태해석할 때 필요한 정보
시세 있음출처·통화·기준 시각과 거래 구간
시세 없음매입가 대체 여부와 시세 누락 표시
매입금액 0손익률의 분모를 계산할 수 있는지
여러 통화합계에 사용한 환산 기준

가격을 크게 표시하는 화면일수록 이 차이가 쉽게 가려집니다. 조회 출처와 대체값의 의미를 먼저 정리한 뒤 차트와 색을 적용해야 합니다. 이 글에서는 현재 코드의 범위와 남은 조건을 함께 기록했고, 실제 개인 보유 종목이나 금액은 예시에 사용하지 않았습니다.

조회 도구와 대시보드 연동

이후에는 토스증권 조회 CLI를 별도 도구로 만들었습니다. Quant Vault에 가격 제공자로 연결하는 방안도 검토했지만, 이 작업에서 실제 통합까지 완료한 것은 아닙니다.

대시보드는 직접 관리하는 보유 정보와 외부 시세를 함께 확인하는 개인 화면으로 정리했습니다. 매매나 주문 실행은 넣지 않았고, 이후 만든 토스증권 조회 CLI도 아직 연결하지 않았습니다. 시세 제공자를 바꾸거나 추가하는 작업과 외부 응답이 늦을 때의 처리는 대시보드 화면과 따로 관리해야 할 부분으로 남았습니다.

Last updated on