projects

Candanta

2026.06 ~ 현재웹 개발

국내·미국 주식의 보유 자산, 비중, 수익률을 한눈에 확인하고 투자 전략을 검토하는 웹 애플리케이션.

  • Next.js 16
  • React 19
  • TypeScript
  • TanStack Query
  • Tailwind CSS 4
  • Radix UI
  • Recharts
  • React Hook Form
  • Zod
  • Drizzle ORM
  • Neon PostgreSQL
  • NextAuth.js
  • OpenAI API
visit project(opens in a new tab)

계좌 데이터를 모아 보여주는 포트폴리오 대시보드

.problem

국내·미국 주식의 보유 현황과 현금 잔고를 함께 보여주려면 통화와 자산 비중의 기준을 맞춰야 했습니다. 대시보드의 여러 API가 같은 계좌 정보를 동시에 요청하는 중복 호출도 있었습니다.

.solution

계좌의 보유 종목과 매수 가능 금액을 조회하고 환율을 적용해 원화 기준 자산, 평가손익, 수익률, 시장·섹터별 비중을 계산했습니다. 사용자별로 진행 중인 계산 Promise를 공유해 동시 요청을 합치고, 서버 쿼리 하이드레이션과 TanStack Query를 연결했습니다.

.tradeoff

advantages
동시에 들어오는 요청은 같은 계산을 공유하면서 이후 요청에는 새 계산을 사용할 수 있습니다.
disadvantages
메모리의 Promise 공유는 같은 서버 인스턴스 안에서만 적용됩니다.
rationale
계산 결과를 장기간 보관하는 캐시 대신 진행 중인 요청만 합치는 방식으로 중복 호출을 줄였습니다.

.result

총자산, 현금, 평가손익과 자산 배분을 한 화면에서 확인하고, 투자 프로필의 승인 여부와 제안 조회 상태에 따라 다음 행동을 안내하도록 구성했습니다.

.learning

서버에서 미리 조회한 데이터와 클라이언트 쿼리를 연결하더라도, 여러 서버 API가 공유하는 외부 요청의 중복은 서비스 계층에서 별도로 다뤄야 합니다.

AI 전략 추천의 입력·출력 검증과 대체 경로

.problem

AI 응답이 서버에서 준비한 종목 후보를 벗어나거나 호출 시간 초과·응답 형식 오류가 발생할 수 있어, 응답을 그대로 투자 제안에 사용할 수 없었습니다.

.solution

전략 조건을 통과한 후보로 AI 입력을 제한하고, 후보 심볼을 포함한 구조화 응답 스키마와 서버 검증을 적용했습니다. 호출 실패, 후보 불일치, 시간·일일 호출 한도에 대해서는 규칙 기반 추천으로 전환하고 추천 출처와 진단 정보를 구분했습니다.

.tradeoff

advantages
AI가 반환한 종목 범위를 검증하고 호출 실패에도 대체 제안을 구성할 수 있습니다.
disadvantages
규칙 기반 대체 결과는 AI 응답과 같은 판단 근거를 제공하지 않습니다.
rationale
추천 출처를 구분하고 검증 가능한 후보와 전략 조건 안에서 제안을 생성하도록 했습니다.

.result

AI 호출과 규칙 기반 대체를 같은 추천 계약으로 반환하고, 후보 범위를 벗어난 응답은 폐기하도록 구현했습니다.

.learning

구조화 응답만으로 업무 규칙까지 보장할 수 없으므로, 후보 집합 검증과 실패 시 동작을 서버에서 함께 정의해야 합니다.

리밸런싱 주문의 중복 실행과 불확실한 결과 처리

.problem

같은 제안을 동시에 실행하거나 주문 접수 후 응답·저장이 실패하면, 재시도가 중복 주문으로 이어질 수 있었습니다.

.solution

외부 주문 전에 제안을 pending에서 executing으로 조건부 전환해 실행을 선점했습니다. 이미 접수된 주문의 스냅샷을 후속 실행에 전달하고, 주문이 접수됐을 가능성이 남은 오류는 자동으로 pending으로 되돌리지 않도록 처리했습니다.

.tradeoff

advantages
동시 실행과 불확실한 결과에 대한 무조건적인 재시도를 억제합니다.
disadvantages
결과를 확정할 수 없는 실행은 즉시 재실행하지 않고 상태 확인과 복구가 필요합니다.
rationale
외부 주문과 DB 저장을 하나의 트랜잭션으로 묶을 수 없어, 실행 상태와 접수 이력으로 재시도 범위를 제한했습니다.

.result

제안 실행의 선점, 접수 이력 보존, 오류 상황의 상태 유지와 복구 경로를 구성했습니다.

.learning

외부 시스템에 부작용을 만드는 요청은 HTTP 실패 여부와 실제 처리 여부를 구분해 재시도를 설계해야 합니다.

보유 자산 스냅샷을 이용한 전략 백테스트

.problem

현재 계좌가 바뀌어도 과거 백테스트의 입력을 확인할 수 있어야 하고, 매입단가 누락과 과거 가격 데이터 부족도 결과 해석에 반영해야 했습니다.

.solution

실행 시점의 종목·수량·매입단가를 별도 스냅샷으로 저장하고, 매입단가가 없으면 과거 종가와 현재가의 대체 경로를 사용했습니다. 캔들 페이지네이션으로 가격 이력을 조회하고 수수료, 슬리피지, 비중 괴리에 따른 리밸런싱을 계산했습니다.

.tradeoff

advantages
실행 당시 입력을 보존하고 가격 대체 여부와 데이터 범위를 함께 확인할 수 있습니다.
disadvantages
전략 엔진은 시장별 네이티브 통화를 명목값으로 계산하므로, 국내·미국 종목이 섞인 결과가 실제 원화 환산 수익률과 다를 수 있습니다.
rationale
입력 스냅샷과 데이터 범위 정보를 남기고, 시뮬레이션의 통화 계산 한계를 구분했습니다.

.result

보유 자산을 고정한 입력을 바탕으로 전략 수익 곡선, 거래 내역, 결과 요약과 데이터 범위 정보를 생성하도록 구현했습니다.

.learning

백테스트는 계산 결과뿐 아니라 입력 시점, 대체 가격 사용 여부, 통화 모델의 한계를 함께 보존해야 해석할 수 있습니다.