개인계좌와 주문 PRD

배경 (Background)

토스 Open API의 개인 계좌·주문 기능을 연동해 계좌 조회·선택, 주식 주문·정정·취소, 보유 종목 및 거래 내역 조회를 하나의 UI에서 처리할 수 있게 한다. MySQL에 모든 상태를 영속화하여 앱이 꺼져도 주문 내역이 유지되고, Toss CUD 요청과 로컬 DB를 항상 동기 상태로 유지한다.

목표

ID요구사항우선순위
R-01토스 계좌 목록을 조회해 원하는 계좌를 선택하고, 선택 상태를 MySQL에 영속화한다높음
R-02매수 가능 금액·매도 가능 수량·매매 수수료를 주문 전 실시간으로 조회한다높음
R-03선택 계좌로 매수·매도 주문을 접수하고, Toss 성공 시 MySQL에 동기화한다높음
R-04미체결 주문의 가격·수량을 정정하거나 취소할 수 있다높음
R-05계좌의 보유 종목 현황(수량·평균 매수가)을 조회하고 MySQL에 upsert한다중간
R-06특정 계좌의 거래 내역을 최신순으로 조회하고 MySQL에 upsert한다중간

요구사항

사용자 문제와 해결 방안

사용자 문제해결 방안
계좌가 여러 개일 때 어떤 계좌로 주문하는지 분명하지 않다계좌 목록 조회 후 활성 계좌 선택, 선택 상태 MySQL 영속화
매수 전 가용 금액·수수료를 별도로 확인해야 한다매수 가능 금액, 매도 가능 수량, 매매 수수료를 API로 사전 조회
주문 후 결과를 앱 안에서 확인할 수 없다주문 접수·정정·취소 API + MySQL 동기화로 로컬 주문 이력 유지
보유 종목 현황을 실시간으로 볼 수 없다보유 종목 조회 API를 통해 계좌별 holdings 스냅샷 제공
어떤 거래를 했는지 히스토리를 확인하기 어렵다거래 내역 조회 API + MySQL에 trade_history 적재

기대 효과

  • 주문 흐름(계좌 선택 → 가용 금액 확인 → 주문 → 이력 확인)을 앱 안에서 완결.
  • Toss와 MySQL을 항상 동기 상태로 유지해 오프라인 조회 가능.
  • 알림·시그널·추천 기능과 연동(추천 가격으로 바로 주문 등록 흐름 확장 가능).

경쟁사·동일 제품군 비교

토스증권 앱 (내 자산·주문)

  • 앱 내 계좌·주문·보유 종목 전체 제공. 단 외부 도구 연동·자동화 불가.

증권사 HTS (키움 영웅문 등)

  • 조건 주문·자동 주문 기능 풍부. 단 외부 API·자체 도구 연동이 어렵고 Mac 지원 미흡.

비교 요약표

항목본 도구토스 앱증권사 HTS
계좌 목록 연동✅(토스 API)
주문·정정·취소
로컬 DB 영속화✅(MySQL)
커스텀 자동화 연동
Mac 네이티브

세부 정책

정책 1: 계좌 목록 조회와 선택

유저 스토리

  • 사용자로서, 토스 계좌 목록을 조회해 원하는 계좌를 선택하고 싶다.
  • 사용자로서, 선택한 계좌가 앱 재시작 후에도 유지되기를 원한다.

UI / UX 주요 작업 포인트

  • 계좌 선택 드롭다운: 계좌번호(마스킹)·계좌명·잔고 표시.
  • 선택 계좌는 헤더·주문 폼·보유종목 탭에서 전역 컨텍스트로 사용.

상세 정책

  • GET /api/v1/accounts → 계좌 목록을 MySQL accounts 테이블에 upsert 후 응답.
  • PUT /api/v1/accounts/{accountNumber}/select → 선택 상태 플래그(selected) MySQL에 영속화.
  • 활성 계좌는 1개만 허용. 선택 변경 시 기존 선택 해제.

마이그레이션 조건 (선택)

  • accounts 테이블 신규 생성. 실패 시 역방향 DDL로 제거.

정책 2: 매수 가능 금액·매도 가능 수량·수수료 조회

유저 스토리

  • 사용자로서, 주문 전 매수 가능 금액과 수수료를 미리 확인하고 싶다.
  • 사용자로서, 매도 시 판매 가능한 수량을 실시간으로 확인하고 싶다.

UI / UX 주요 작업 포인트

  • 주문 폼: 종목·수량·가격 입력 → “조회” 클릭 → 가능 금액/수량·예상 수수료 인라인 표시.

상세 정책

  • GET /api/v1/accounts/purchasable?symbol=&quantity=&price= → 토스 API 프록시, MySQL 저장 없음.
  • GET /api/v1/accounts/sellable?symbol=&quantity= → 토스 API 프록시, MySQL 저장 없음.
  • GET /api/v1/accounts/fee?symbol=&quantity=&price=&orderType= → 토스 API 프록시, MySQL 저장 없음.
  • 세 API 모두 실시간 조회가 목적이므로 캐시 없이 Toss API를 즉시 호출.

정책 3: 주식 주문 접수·정정·취소

유저 스토리

  • 사용자로서, 선택한 계좌로 종목을 매수/매도 주문하고 싶다.
  • 사용자로서, 접수된 주문의 가격 또는 수량을 정정하고 싶다.
  • 사용자로서, 미체결 주문을 취소하고 싶다.

UI / UX 주요 작업 포인트

  • 주문 폼: 매수/매도 탭, 종목·수량·가격·주문 유형(시장가/지정가) 입력.
  • 미체결 주문 테이블: 정정·취소 버튼 제공.

상세 정책

  • POST /api/v1/orders → Toss 주문 API 호출 → 성공 시 MySQL orders 테이블에 INSERT.
  • PATCH /api/v1/orders/{id} → Toss 주문 정정 API 호출 → 성공 시 MySQL orders UPDATE(status=CORRECTED, 가격/수량 반영).
  • DELETE /api/v1/orders/{id} → Toss 주문 취소 API 호출 → 성공 시 MySQL orders UPDATE(status=CANCELLED).
  • Toss 호출 실패 시 MySQL 업데이트 없음(Toss가 진실 원천). 트랜잭션은 MySQL 업데이트 단계에만 적용.
  • 주문 상태: PENDINGCOMPLETED / CANCELLED / CORRECTED.

마이그레이션 조건 (선택)

  • orders 테이블 신규 생성. 실패 시 역방향 DDL.

정책 4: 거래 히스토리 조회

유저 스토리

  • 사용자로서, 특정 계좌의 거래 내역을 최신순으로 보고 싶다.

UI / UX 주요 작업 포인트

  • 거래 내역 탭: 거래 유형(매수/매도)·종목·수량·체결가·거래 시각 표시.

상세 정책

  • GET /api/v1/accounts/{accountNumber}/trade-history?from=&to= → Toss API 호출 → MySQL trade_history에 upsert 후 응답.
  • toss_transaction_id unique 제약으로 중복 적재 방지.
  • 조회 범위 기본값: 최근 30일.

마이그레이션 조건 (선택)

  • trade_history 테이블 신규 생성. 실패 시 역방향 DDL.

정책 5: 보유 주식 리스트 조회

유저 스토리

  • 사용자로서, 현재 계좌에서 보유 중인 종목과 평균 매수가를 보고 싶다.

UI / UX 주요 작업 포인트

  • 보유 종목 탭: 종목명·수량·평균 매수가·현재가·수익률 표시.

상세 정책

  • GET /api/v1/accounts/{accountNumber}/holdings → Toss API 호출 → MySQL holdings 테이블에 upsert(계좌번호+종목코드 복합 UK).
  • refreshed_at 컬럼으로 마지막 동기화 시각 추적.
  • 현재가는 가격 캐시에서 조인.

마이그레이션 조건 (선택)

  • holdings 테이블 신규 생성. 실패 시 역방향 DDL.

사용자 시나리오

시나리오 1: 계좌 선택 후 주식 주문

  1. 사용자가 계좌 목록을 조회하면 GET /api/v1/accounts가 Toss에서 계좌를 fetch해 MySQL에 upsert한다.
  2. 사용자가 원하는 계좌를 선택하면 PUT /api/v1/accounts/{accountNumber}/select가 selected 플래그를 단일 트랜잭션으로 전환한다.
  3. 주문 폼에서 매수 가능 금액을 조회해 수량을 결정하고 POST /api/v1/orders로 주문을 접수한다.
  4. Toss 성공 응답 후 MySQL orders에 PENDING 상태로 저장된다.

시나리오 2: 미체결 주문 정정·취소

  1. 사용자가 미체결 주문 테이블에서 주문을 확인한다.
  2. “정정” 클릭 시 PATCH /api/v1/orders/{id}로 Toss에 정정 요청 → 성공 시 MySQL status=CORRECTED, 가격·수량 갱신.
  3. “취소” 클릭 시 DELETE /api/v1/orders/{id}로 Toss에 취소 요청 → 성공 시 MySQL status=CANCELLED.
  4. COMPLETED·CANCELLED 상태 주문은 정정·취소 버튼이 비활성화된다.

범위 외

  • 멀티 유저 / 인증 (단일 사용자 로컬 도구).
  • 실시간 주문 체결 알림 (WebSocket·push: 토스 Open API 미제공).
  • 자동 주문 스케줄링 (향후 검토).
  • 조건부 주문(stop-loss, OCO 등).

관련 문서