5.2 KiB
[REQ] GET /v1/portfolios 응답에 종목 코드(symbol) 포함
요약
GET /v1/portfolios 응답의 PortfolioItem 에 종목 코드(symbol) 필드를 추가해주세요. 현재는 asset_id (UUID) 만 반환되어, 종목 코드가 필요한 클라이언트가 별도 카탈로그 조회로 매핑해야 합니다.
배경
trex-orbit 자동매매 데몬은 매 사이클마다 GET /v1/portfolios 로 daemon-scoped portfolio 리스트를 받아 운용 대상 종목을 결정합니다. 이후 외부 데이터 서비스 (kis-data-hub) 에 시세 / 분봉을 요청하려면 종목 코드 (예: "005930") 가 필요한데, 현재 PortfolioItem 에는 asset_id (UUID) 만 있고 symbol 이 빠져 있어 다음 우회가 필요합니다.
- trex-orbit 부팅 시 asset 카탈로그를 별도로 조회해
asset_id → symbol캐시 구성 - 사이클 중
asset_id마다 캐시 lookup - 캐시 미스 시 portfolio-hub 에 추가 조회
이 과정에서 캐시 stale / 신규 asset 등록 후 동기화 지연 / 클라이언트마다 캐시 로직 중복 같은 운영 부담이 발생합니다.
현재 상태
Endpoint: GET /v1/portfolios (app/api/v1_portfolios.py:224)
응답 스키마: PortfolioItem
class PortfolioItem(BaseModel):
portfolio_id: str
asset_id: str | None = None # UUID
owner_user_id: str | None = None
broker: str
status: str
name: str
cash_balance: float = 0.0
asset_quantity: float = 0.0
price: float = 0.0
profit_buffer: float = 0.0
tag_ids: list[str] = Field(default_factory=list)
managed_by_daemon_id: str | None = None
created_at: datetime | None = None
updated_at: datetime | None = None
# symbol 없음
종목 코드는 별도 AssetItem 에만 존재 (app/schemas/v1.py:55):
class AssetItem(BaseModel):
asset_id: str
symbol: str # ← 여기 있음
status: str
...
요청 변경
1. 스키마
PortfolioItem 에 symbol 필드 추가:
class PortfolioItem(BaseModel):
portfolio_id: str
asset_id: str | None = None
symbol: str | None = None # ← 추가 요청
owner_user_id: str | None = None
...
2. 응답 채움 로직
GET /v1/portfolios 의 _portfolio_to_item 빌더가 portfolios.asset_id → assets.symbol join 결과를 활용해 symbol 을 채워주세요. 이미 repository 단계에서 join 되어 있다면 변환 로직만 추가하면 됩니다.
3. 단건 / 관련 엔드포인트도 동일 적용
다음 엔드포인트의 응답에도 symbol 포함:
POST /v1/portfolios(생성 후 반환)PATCH /v1/portfolios/{portfolio_id}DELETE /v1/portfolios/{portfolio_id}(soft delete 응답)- 기타
PortfolioItem을 반환하는 모든 경로
정당성
- 클라이언트 단순화: daemon 클라이언트 (trex-orbit 등) 가 portfolio 정보만 받으면 즉시 외부 시세 API 호출 가능. 추가 카탈로그 조회 / 캐시 관리 불필요.
- 일관성:
cash_balance,asset_quantity,price등 자산 관련 필드는 이미 PortfolioItem 에 포함됨.symbol도 자산 식별의 핵심이므로 같이 포함되는 것이 자연스러움. - stale cache 위험 제거: 클라이언트 캐시 + miss fallback 패턴은 카탈로그 변경 시 일시적 불일치 가능. server 측 join 으로 항상 최신 매핑 제공.
- 운영 부담 감소: 캐시 무효화 / 갱신 / 재로드 로직이 클라이언트마다 중복 구현되는 것을 회피.
호환성
symbol 은 신규 필드이며 Optional[str] 로 추가하면 기존 클라이언트에 영향 없음 (additive change).
영향 범위
app/api/v1_portfolios.py—_portfolio_to_item에 symbol 채움app/schemas/v1.py—PortfolioItem에symbol필드 추가app/repositories/—list_portfolios/get_portfolio가 asset join 결과를 들고 오도록 보강 (이미 그렇다면 변경 없음)docs/interface-contract.md—GET /v1/portfolios응답 예시 갱신- 테스트 —
PortfolioItem응답 형식 검증 케이스 추가
검수 기준
GET /v1/portfolios호출 시 각 item 에symbol필드가 포함됨symbol값은 해당asset_id의AssetItem.symbol과 일치 (server side join)- 단건 조회 / 생성 / 수정 / 삭제 응답도 동일하게
symbol포함 interface-contract.md의GET /v1/portfolios응답 예시에symbol명시- 기존 테스트 회귀 없음 + 신규 케이스 추가
우선순위
Medium — trex-orbit 사이드에서 캐시 기반 우회가 가능해 즉시 차단 이슈는 아니지만, 운영 본격 시작 전 정리하면 lifecycle 비용을 크게 줄임.
관련 문서
- trex-orbit
temp/plan.md8.4.1 step 3 (asset_id → symbol resolve) — 본 이슈의 우회 구현 단계 - trex-orbit
temp/plan.md8.6.4.1 전제 시점 — universe 결정 과정에서 symbol resolve 가 필요한 이유
작성자 / 일자
- 요청자: trex-orbit 팀 (genichin@gmail.com)
- 작성일: 2026-05-24