[BE-20] OCO 멱등키 전송과 알림 설정 키 보완
이 티켓은 분할 흡수됐습니다 — 멱등키는 BE-28-브로커-멱등키-불변식|BE-28], 알림 설정은 BE-32-알림-마스킹-설정검증|BE-32] 가 가져갑니다. 이 파일은 이력 보존용이며 착수 대상이 아닙니다.
작업 내용 (설계 의도)
두 건 다 wave 2 리뷰에서 후속으로 미룬 항목이다. 같은 티켓으로 묶는 이유는 둘 다 설정·계약 수준의 작은 보완이고 파일이 겹치지 않기 때문이다.
1. OCO 등록에 clientOrderId 전송
TossConditionalOrderGatewayImpl이 등록 요청에 clientOrderId를 보내지 않는다. 토스 스펙의 ConditionalOrderCreateRequest에는 이 필드가 존재하고, 응답에도 내려온다.
OCO 중복 등록은 동일 수량 매도 leg 2벌을 의미한다 — 한쪽이 체결되면 나머지가 취소되지만, 2벌이 등록돼 있으면 보유 수량의 2배가 매도 대기 상태가 된다. BE-10 LiveTradeExecutor에 재시도 정책이 붙기 전에 멱등키를 확정해야 한다.
키 형식은 TradingFill의 AT-{proposalId}와 충돌하지 않게 정한다(예: OCO-{positionId}). 형식과 근거를 KDoc에 남긴다.
2. notification.discord.error-webhook-url yml 선언
DiscordAutoTradingAlertGateway가 @Value("${notification.discord.error-webhook-url:${DISCORD_ERROR_WEBHOOK_URL:}}")로 읽는데, application.yml의 notification.discord 블록에는 webhook-url만 있다. 중첩 기본값 덕에 부팅은 실패하지 않고 no-op 로그로 떨어지지만, 운영자가 yml만 보면 error-alert 채널 미설정을 인지할 수 없다.
wave 2에서는 application.yml이 BE-08 소유라 의도적으로 남긴 항목이다.
롤백: 두 변경 모두 되돌리기가 안전하다 — 멱등키는 미전송 상태로, yml 키는 제거해도 중첩 기본값이 동작한다.
의존
- BE-08 (OCO 어댑터), BE-09 (알림 어댑터) — 둘 다 main 머지 완료
다이어그램
처리 흐름
sequenceDiagram participant Exec as LiveTradeExecutor participant Gw as TossConditionalOrderGatewayImpl participant Toss as Toss Open API Exec->>Gw: placeOcoOrder(spec) Gw->>Toss: POST conditional-orders (clientOrderId 포함) Toss-->>Gw: 같은 키 재요청 시 중복 등록 없음
클래스 의존
flowchart LR Impl[TossConditionalOrderGatewayImpl] --> Spec[OcoOrderSpec] Impl --> Dtos[TossConditionalOrderDtos] Alert[DiscordAutoTradingAlertGateway] --> Yml[application.yml]
테스트 케이스
- OCO 등록 요청 본문에
clientOrderId가 포함된다(MockWebServer 본문 검증). - 같은 포지션으로 두 번 등록해도 같은
clientOrderId가 전송된다(멱등키 파생 규칙). clientOrderId형식이TradingFill의AT-접두와 충돌하지 않는다.application.yml에error-webhook-url키가 선언돼 있고 환경변수 미설정 시 빈 문자열로 해석된다.- error-webhook-url이 빈 문자열이면
notifyOrderFailure가 no-op + 경고 로그로 떨어지고 예외를 던지지 않는다.