2026.9에는 Kraken의 개별 결함 네 가지가 반영되었으며, 그중 어느 것도 코드를 한 번 읽어서 발견할 수 있는 종류가 아니었습니다. 각각은 특정 조건에서만 드러납니다. 연결 시점의 잘못된 엔드포인트, 기기 밖으로 나가지 못하는 요청 본문, 몇백 밀리초 너무 이르게 일어나는 재연결. 네 가지 모두 수정되었고, 네 가지 모두 이해할 가치가 있습니다. 각각의 실패 양상이 전혀 다른 문제처럼 보이기 때문입니다.
스팟 클라이언트가 v2 엔드포인트에 v1을 사용하고 있었다
TsgcWSAPI_Kraken은 v1 스키마인 event, pair, subscription, subscriptionStatus, systemStatus를 생성하고 파싱합니다. 이 스키마에는 이유가 있습니다. 이 컴포넌트의 모든 구독 호출과 모든 이벤트 핸들러가 이를 기준으로 작성되어 있기 때문입니다. 그런데 연결 대상 엔드포인트는 기본값이 Kraken의 v2 WebSocket이었고, 이는 method, params, channel, type이라는 완전히 다른 스키마를 사용합니다. 연결은 오류 없이 열렸습니다. 다만 구독 확인이나 상태 이벤트가 단 하나도 발생하지 않았는데, 서버가 클라이언트가 전혀 파싱하지 못하는 형태로 응답하고 있었기 때문입니다.
이제 Kraken.Version은 기본값이 1이며, 컴포넌트는 그에 맞는 v1 엔드포인트를 선택합니다.
uses
sgcWebSocket, sgcWebSocket_APIs;
var
oKraken: TsgcWSAPI_Kraken;
begin
oKraken := TsgcWSAPI_Kraken.Create(nil);
oKraken.Client := oClient;
// Version defaults to 1, matching the event/pair/subscription
// schema this component already builds and parses.
oKraken.Kraken.Version := 1;
oClient.Active := True;
oKraken.SubscribeTicker('XBT/USD');
end;
혹시라도 애플리케이션이 예전의, 조용히 잘못되어 있던 기본값에 의존하고 있었다면, 이는 애초에 v1 이벤트도 실제로 받고 있지 않았다는 뜻이므로 오늘 시점에 보존해야 할 동작이 없습니다. 그 스키마를 의도적으로 사용하려는 경우를 위해, Kraken.Version := 2를 명시적으로 설정하면 여전히 v2 엔드포인트에 연결되며, RawMessages를 활성화하고 OnKrakenData 또는 OnMessage에서 페이로드를 처리하면 됩니다.
Futures 주문이 GET으로 전송되고 본문이 버려지던 문제
이번 문제는 더 조용하지만 더 심각합니다. Kraken Futures REST 클라이언트의 모든 비공개 요청, 즉 주문 전송, 주문 수정, 주문 취소, 이체, 출금이 모두 HTTP GET으로 전송되고 있었습니다. 서명된 요청 본문은 올바르게 생성되고, 계산되고, 포맷까지 되어 전송 준비가 끝난 상태였지만, GET 요청에는 본문을 담을 곳이 없었기 때문에 그대로 버려졌습니다. Kraken은 매개변수가 없는 GET을 받고 이를 거부하거나 무시했습니다. 이 호출들은 하나도 동작하지 않았습니다.
uses
sgcHTTP_API_Kraken;
var
oKraken: TsgcHTTP_API_Kraken_Futures_Rest;
oOrder: TsgcHTTPKrakenFuturesOrder;
begin
oKraken := TsgcHTTP_API_Kraken_Futures_Rest.Create(nil);
oKraken.KrakenOptions.ApiKey := 'your_api_key';
oKraken.KrakenOptions.ApiSecret := 'your_api_secret';
oOrder := TsgcHTTPKrakenFuturesOrder.Create;
try
oOrder.OrderType := kotfLMT;
oOrder.Symbol := 'PF_XBTUSD';
oOrder.Side := kosfBuy;
oOrder.Size := 1;
oOrder.LimitPrice := 30000;
// SendOrder now posts through DoHTTP_POST_PRIVATE, body included.
ShowMessage(oKraken.SendOrder(oOrder));
finally
oOrder.Free;
end;
end;
이제 SendOrder, EditOrderByOrderId, EditOrderByCliOrderId, CancelOrderByOrderId, CancelOrderByCliOrderId, Transfer, WithdrawalToSpotWallet 모두 비공개 POST 경로를 거치며, 서명된 본문이 실제로 요청에 첨부됩니다.
재연결 시 비공개 구독이 유실되던 문제
WatchDog가 재연결하고, 로그에는 깔끔한 재연결이 표시되지만, 그 시점부터 orders, balance, fills 채널이 그냥 사라져 있습니다. 오류도 없습니다. 로그도 없습니다. 재연결은 완전히 성공한 것처럼 보였는데, 연결 자체는 실제로 성공했기 때문이고, 다만 연결 끊김 이전에 발행된 비공개 구독만 이후에 전혀 재전송되지 않았을 뿐입니다. 이 문제는 Kraken 스팟과 Kraken Futures 모두에 영향을 미쳤으며, 같은 작업에서 함께 수정된 다른 여러 거래소 클라이언트에도 영향을 미쳤습니다. 이제 이는 표준 재구독 재전송 과정의 일부가 되었으며, 재연결 후 공개 시장 데이터 구독을 이미 복원하던 것과 동일한 경로를 사용합니다.
세션 인증 완료 전에 재구독하던 Futures 문제
밀접하게 관련된 또 다른 결함으로, Kraken Futures에 국한된 것입니다. 재연결 후, 활성 구독의 재전송이 인증 핸드셰이크가 실제로 완료되기 전에 실행될 수 있었습니다. 구독 요청은 Kraken이 아직 인증하지 않은 세션에서 전송되었고, 그 결과 비공개 구독은 거부되었으며, 이번에도 클라이언트에는 이유를 알려주는 것이 아무것도 없었습니다. 이제 재전송은 인증이 끝날 때까지 기다린 후에 재구독합니다.
업그레이드
네 가지 수정 사항 모두 그대로 적용되며, 마이그레이션이 필요한 API는 없습니다. 유의해야 할 유일한 동작 변경은 Kraken.Version 기본값이 이전의 사실상 동작하지 않던 값에서 1로 바뀐 것입니다. 이미 코드에서 명시적으로 Version := 2를 설정하고 있다면 아무것도 달라지지 않습니다.
질문이나 피드백, 마이그레이션 관련 도움이 필요하신가요? 문의하기 — 실제로 코드를 작성한 사람들에게서 답변을 받으실 수 있습니다.
