모든 글

읽는 데 10분

CardanoWall API 위에서 빌드하기

CardanoWall 위에 자체 제품을 구축하는 방법: CardanoWall 자체가 운영되는 동일한 게이트웨이 API를 통해 견적, 업로드, 게시, 읽기, 검증, 모니터링까지 Label 309 레코드를 다룹니다.

사용자를 CardanoWall 웹사이트로 보내지 않고도, 존재 증명 기능을 자체 제품에 그대로 넣을 수 있습니다. CardanoWall은 호스팅된 게이트웨이 위에 올린 사용자 인터페이스이며, 그 게이트웨이는 평범한 HTTP API를 노출합니다. 증명에 대한 견적을 받고, 스토리지가 필요할 때 콘텐츠를 업로드하고, Label 309 레코드를 게시하고, 상태를 추적하고, 공개 레코드를 읽고, 잔액을 확인하고, 웹훅을 수신하는 일이 모두 가능합니다. Cardano에 안착하는 증명은 CardanoWall 전용의 비공개 포맷이 아니라 표준 Label 309 메타데이터입니다. 따라서 누구든, 어떤 도구로든 나중에 검증할 수 있습니다.

이것이 핵심 구조입니다. 제품 경험은 온전히 여러분의 것이 될 수 있습니다. 증명은 독립적으로 검증 가능한 상태로 남습니다. 이는 CardanoWall 자체의 웹 앱과 워커가 운영되는 바로 그 API입니다. 별도의 비공개 통로도, 더 빠른 내부 경로도 없습니다.

무엇을 빌드할 수 있습니까?

워크플로 안에서 존재 증명이 필요한 곳이라면 어디든 이 API가 들어맞습니다.

  • 고객 문서에 타임스탬프를 찍는 SaaS 제품;
  • 릴리스 매니페스트를 체인에 고정하는 CI/CD 파이프라인(CI/CD의 증명 참고);
  • 대규모 출처 증명 레코드를 게시하는 AI 플랫폼;
  • 매일의 증거 배치를 커밋하는 컴플라이언스 아카이브;
  • 특정 수신자를 위해 증거를 봉인하는 법률 도구;
  • 통제 스냅샷에 서명하는 내부 감사 시스템;
  • 발행자의 레코드를 나열하는 공개 탐색기 또는 프로필 페이지.

이 API는 단순히 웹사이트를 편하게 감싼 래퍼가 아닙니다. 사람이 개입하지 않는 순간에 손을 뻗게 되는 자동화 창구입니다.

주요 게시 흐름은 무엇입니까?

게시는 세 단계로 이루어집니다. 견적, 업로드(바이트를 저장해야 할 때만), 그다음 게시입니다. 게이트웨이의 데이터 플레인(/api/v1/*)에서는 다음과 같이 대응됩니다.

  • POST /api/v1/poe/quote — 짧은 시간 동안 가격을 잠급니다.
  • POST /api/v1/poe/uploads — 콘텐츠를 저장하고 콘텐츠 주소 지정 URI를 반환합니다.
  • POST /api/v1/poe/uploads/sessions 및 그 청크 라우트 — 대용량 파일을 위한 재개 가능 경로입니다.
  • POST /api/v1/poe/publish — 완성된 레코드를 제출합니다.
  • POST /api/v1/poe/publish-batch — 한 번의 호출로 여러 레코드를 제출합니다.
  • GET /api/v1/poe/events/{poe_id} — Server-Sent Events로 상태 업데이트를 스트리밍합니다.

정확한 요청·응답 본문은 모든 배포에서 제공되는 게이트웨이의 OpenAPI 문서에 들어 있습니다. 블로그 스니펫이 아니라 그 문서에 바인딩하십시오. 안정적으로 유지되는 것은 멘탈 모델입니다. 먼저 가격을 잠그고, 콘텐츠가 있으면 저장한 뒤, 완성된 canonical-CBOR 레코드 바이트를 견적 ID와 함께 제출합니다.

견적이 먼저 오는 이유는 무엇입니까?

게시는 유료 작업이고, 가격을 미리 알 수 없기 때문입니다.

게이트웨이는 여러분을 대신해 실제 비용을 지불합니다. Cardano 트랜잭션 수수료, 콘텐츠가 첨부될 때의 Arweave 스토리지, USD와 해당 네트워크 사이의 환 노출, 그리고 운영자 마진입니다. 견적은 게시 호출이 무언가를 지출하기 전에 그 비용을 명시적으로 드러냅니다. (유료 게시의 근거는 게시에 가격이 붙는 이유를 참고하십시오.)

견적 응답에는 quote_id, 가격이 매겨진 내역(네트워크, 스토리지, 서비스 구성 요소), 적용된 마진, 환율 스냅샷의 신선도, 그리고 만료 타임스탬프가 담깁니다. 가격은 한정된 시간(대략 15분) 동안만 잠기며, 그 후에는 새 견적을 요청합니다.

이를 통해 애플리케이션은 다음을 결정할 수 있습니다.

  • 계정이 게시 비용을 감당할 수 있는지;
  • 환율 스냅샷이 자체 정책 기준으로 충분히 신선한지;
  • 해당 작업에 사용자 확인이 필요한지;
  • 큰 배치를 나눌지;
  • 기존 견적이 만료되었을 때 새 견적으로 재시도할지.

게이트웨이가 비용이 들지 않음을 확인하기 전에는 "무료" 라벨을 표시하지 마십시오. 스토리지가 없는 해시 전용 레코드는 저렴할 수 있지만, 가격에 대한 권위는 여러분의 UI가 아니라 게이트웨이에 있습니다.

업로드 단계는 무슨 일을 합니까?

업로드는 어딘가에 자리 잡아야 하는 바이트를 처리합니다.

해시 전용 증명은 아무것도 업로드하지 않습니다. 이미 다이제스트를 손에 쥐고 있기 때문입니다. 첨부된 콘텐츠, 봉인된 암호문, 또는 복구 자료가 있는 레코드는 콘텐츠 주소 지정 스토리지가 필요하며, 업로드 엔드포인트가 그 바이트를 저장하고 ar://... 같은 URI를 반환합니다. 이 API는 멀티파트 업로드, 파일별 결과, 계정 내 콘텐츠 해시 기반 중복 제거, 그리고 한 번의 요청으로 보내기에 너무 큰 파일을 위한 재개 가능 세션을 지원합니다. CardanoWall은 고정된 업로드 최대 크기를 두지 않습니다. 콘텐츠는 바이트 단위로 과금되며, 수 기가바이트 규모의 업로드도 예상된 사용 범위입니다.

업로드를 그 자체의 작은 라이프사이클로 다루십시오.

  1. 바이트를 업로드합니다.
  2. 콘텐츠 주소 지정 URI를 받습니다.
  3. 그 URI를 사용해 Label 309 레코드를 빌드하거나 완성합니다.
  4. 레코드를 게시합니다.

업로드가 진행 중인 시도 ID를 반환하면, 무작정 다시 업로드하지 말고 그 시도의 상태 엔드포인트를 폴링하십시오. 응답을 놓쳤다고 해서 수 기가바이트 파일을 다시 보내는 것은 바로 그 시도 ID가 막으려는 종류의 실수입니다.

게시는 무엇을 하며, 왜 비동기입니까?

게시는 레코드를 제출하고 체인 파이프라인을 시작합니다.

게시 호출은 완성된 canonical-CBOR 레코드 바이트와 quote_id를 받습니다. 게이트웨이는 메타데이터 레이블 309 아래 레코드를 Cardano에 고정하고, 견적된 금액을 차감한 뒤, 트랜잭션이 아직 제출과 확인 과정을 거치는 동안 게이트웨이 레코드 ID(poe_... 값)를 반환합니다.

이 비동기성은 설계에 중요합니다. 호출이 반환될 때 온체인 트랜잭션 해시는 아직 존재하지 않을 수 있습니다. 대기 상태를 표시하고 업데이트를 수신하십시오. API가 보고하는 상태는 다음 값들을 거쳐 갑니다.

  • submitting — 트랜잭션이 빌드되어 브로드캐스트되는 중;
  • confirming — 체인에 올라갔으나 확인 임계치 미만;
  • confirmed — 임계치를 넘어 확정됨;
  • failed — 게시가 영구적으로 실패해 안착하지 않음.

GET /api/v1/poe/events/{poe_id}의 상태 스트림은 바로 이 목적을 위해 존재합니다. 영구적 실패가 발생하면 게이트웨이가 차감을 스스로 되돌립니다. 그래서 여러분의 제품은 자체 정산을 돌리지 않고도 사용자에게 "온체인에 안착한 것에 대해서만 과금됩니다"라고 정직하게 말할 수 있습니다. 게시 실패에 대한 벤더 측 환불 경로를 만들지 마십시오. 이중 환불이 발생합니다.

API 클라이언트는 무엇을 저장해야 합니까?

워크플로를 다시 이어 붙일 수 있을 만큼만 저장하고, 그 이상은 두지 마십시오. 최소한 다음이 필요합니다.

  • 여러분 자체의 사용자 또는 계정 ID;
  • 게이트웨이 poe_id;
  • 게시에 사용한 견적 ID;
  • 레코드 다이제스트, 또는 레코드 바이트의 해시;
  • 최종 Cardano 트랜잭션 해시(존재하게 된 이후);
  • 상태와 타임스탬프;
  • 업로드 시도 ID;
  • 콘텐츠 주소 지정 URI;
  • 나중에 검증할 때 필요한 로컬 자료.

데이터베이스를 증명으로 취급하지 마십시오. 제품용 읽기 모델로 취급하십시오. 증명은 온체인 Label 309 레코드와 그것을 검증하는 데 필요한 콘텐츠 또는 키이며, 이 조합은 여러분의 서버와 무관하게 그 자체로 성립합니다.

레코드는 어떻게 읽고 검증합니까?

레코드 관련 엔드포인트는 공개적이고 익명인 읽기를 위해 만들어졌습니다.

  • GET /api/v1/records — 필터와 페이지네이션이 있는 온체인 레코드 피드입니다.
  • GET /api/v1/records/count — 그 피드의 개수입니다.
  • GET /api/v1/records/{tx_hash} — 트랜잭션 해시로 조회하는 단일 레코드입니다.
  • POST /api/v1/records/{tx_hash}/verify — 서버 측 검증 보고서입니다.

목록과 조회 라우트는 익명 호출자에게도 응답합니다. 공개 검증 페이지와 탐색기에는 자격 증명이 필요 없습니다. 관련이 있는 곳에서는 베어러 토큰으로 계정 컨텍스트를 더할 수 있지만, 공개 레코드 검증이 비공개 CardanoWall 세션에 의존해서는 결코 안 됩니다.

이 엔드포인트들은 제품 편의를 위해 사용하십시오. 고신뢰 점검이 필요하다면, 직접 선택한 Cardano 인프라를 통해 체인 데이터를 가져와 독립적인 보고서를 산출하는 독립 실행형 검증기도 함께 돌리십시오. 그것이 건강한 분리입니다. API는 앱을 더 쉽게 빌드하게 해 주지만, 증명은 여전히 API 바깥에서 성립해야 합니다. 오픈소스 SDK와 CLI는 바로 그 검증기를 함께 제공합니다. 그 동작 방식을 처음부터 끝까지 보려면 Label 309 레코드 검증하기를 참고하십시오.

인증은 어떻게 작동해야 합니까?

자격 증명의 범위를 좁게 유지하고, 운영자 자격 증명은 백엔드에 두십시오.

게이트웨이는 두 플레인을 분리합니다. 사용자는 백엔드가 세션마다 발급하는 수명이 짧은 계정 토큰 또는 API 키로 데이터 플레인(/api/v1/*)에서 동작합니다. 컨트롤 플레인(/control/v1/*)을 위한 운영자 자격 증명은 오직 백엔드만 보유합니다. 계정 프로비저닝, 청구에서 돈이 들어왔을 때의 크레딧 적용, 마진 설정, 그리고 앞서 말한 계정 토큰 발급이 여기에 해당합니다.

데이터 플레인 접근에는 범위(scope)가 적용됩니다. 사용하게 될 범위는 다음과 같습니다.

  • poe:create — 견적, 업로드, 게시, 배치 게시;
  • poe:read — 레코드 읽기, 검증 라우트, 그리고 베어러로 호출되는 상태 스트림;
  • account:read — 잔액 및 원장 읽기;
  • webhooks:readwebhooks:write — 계정 범위의 웹훅 관리;
  • billing:read — 벤더 청구 화면을 위해 예약됨.

게시 페이지에는 poe:create가 필요하고, 잔액 위젯에는 account:read가 필요하며, 둘 다 그 이상은 필요하지 않습니다. 운영자 자격 증명은 브라우저 번들, 모바일 앱, 파트너의 스크립트, 또는 증명만 게시하면 되는 CI 작업에 결코 도달해서는 안 됩니다. 그런 곳은 대신 자체적으로 범위가 지정된 계정 토큰을 발급합니다. 유출된 계정 토큰은 한 시간짜리 문제여야지, 사고가 되어서는 안 됩니다.

재시도와 멱등성은 어떻게 작동해야 합니까?

재시도는 운영 전에 설계하십시오. 게시 시스템은 평범한 방식으로 실패하기 때문입니다. 네트워크 끊김, 만료된 견적, 잔액 부족, 속도 제한, 아직 진행 중인 업로드, 또는 끊긴 상태 스트림 등입니다.

견고한 통합이라면 다음을 갖춰야 합니다.

  • API가 멱등성을 지원하는 곳에서는, 안정적인 원본 요청 ID를 키로 삼아 멱등성을 활용합니다;
  • 견적 만료를 정상으로 취급합니다 — 새 견적을 가져와 계속 진행합니다;
  • 불확실한 실패 이후에는 무작정 재제출하지 말고, 권위 있는 시도 또는 레코드 엔드포인트를 폴링합니다;
  • 대용량 파일의 이중 업로드를 피합니다;
  • 잔액 이중 적립을 피합니다(모든 크레딧을 해당 결제 자체의 ID로 키 처리합니다);
  • 지원을 위해 요청 ID와 게이트웨이 ID를 로깅합니다;
  • 보고서에서 실패한 게시와 검증 불가능한 레코드를 구분합니다.

게시는 레코드 바이트를 기준으로 중복을 제거하고, 업로드 배치는 멱등 재생을 지원합니다. "다시 시도하고 잘되길 바라는" 루프 대신 이러한 의미론에 기대십시오.

웹훅은 무엇을 해야 합니까?

웹훅은 읽기 모델을 빌드하는 방법입니다. 매초 폴링하는 방식도 아니고, 더더욱 게이트웨이의 데이터베이스 테이블을 읽는 방식도 아닙니다. 그 테이블은 엔진 내부용이며 예고 없이 바뀝니다.

웹훅 구독을 등록하면 게이트웨이가 라이프사이클 이벤트를 푸시합니다. poe_status_changed, balance_changed, 환불 인텐트, 업로드 실패 등입니다. 운영자는 인스턴스 전체 범위의 파이어호스를 구독할 수 있고, 계정 범위의 웹훅 라우트도 데이터 플레인에 존재합니다. "보낸 항목" 뷰 — 각 사용자가 자신이 게시한 레코드를 실시간 상태와 함께 보는 화면 — 가 대표적인 활용 사례입니다. poe_status_changed를 소비해 자체 테이블에 투영하고, 거기서 렌더링하십시오.

수신기는 각 전달의 서명을 확인하고, 적어도 한 번(at-least-once) 전달을 수용하며, 투영을 이벤트 또는 전달 ID로 키 처리하고, 재전달을 무연산(no-op)으로 취급해야 합니다. 읽기 모델은 여러분의 앱에 속합니다. 권위 있는 지출 및 게시 상태는 게이트웨이에 속합니다. 필요하다면 렌더링을 위해 캐시하되, 지출을 결정짓는 판단에는 게이트웨이를 읽으십시오.

클라이언트를 결코 떠나서는 안 되는 것은 무엇입니까?

비공개 신원 자료입니다. 애플리케이션은 레코드를 게시하기 위해 API를 호출하며, 사용자의 신원 시드(Identity Seed), 서명 비공개 키, 또는 수신자 비공개 키를 게이트웨이에 결코 넘겨서는 안 됩니다.

  • 서명된 레코드의 경우, 로컬에서 서명하거나 호스트 외부 서명을 사용하십시오. SDK는 비공개 키가 KMS, HSM, 또는 에어갭 머신에 있고 공개 키와 서명만 네트워크를 건너오는 흐름을 제공합니다.
  • 봉인된 레코드의 경우, 종단 간 기밀성이 필요한 사용 사례라면 업로드 전에 로컬에서 암호화하십시오.
  • 수신자 검증의 경우, 로컬에서 복호화하십시오.

이 API는 게시 및 라이프사이클 작업을 위한 것입니다. 신뢰의 뿌리가 아니며, 결코 그럴 필요가 없도록 설계되었습니다. 더 넓은 원칙은 키가 기기를 떠나지 않는 이유를 참고하십시오.

어디서부터 시작할지

가장 빠른 길은 github.com/cardanowall에 있는 오픈소스 SDK와 CLI입니다. TypeScript SDK(@cardanowall/sdk-ts), Python SDK(cardanowall-sdk), Rust SDK(cardanowall), 그리고 cardanowall CLI가 있습니다. 모두 게이트웨이 비종속적입니다 — 베이스 URL과 불투명한 API 키만 공급하면 됩니다 — 그리고 모두 동일한 독립 실행형 검증기를 함께 제공합니다. API를 먼저 직접 손으로 다뤄 보고 싶다면, 첫 증명 게시하기가 레코드 하나를 처음부터 끝까지 안내하고, 자동화에서 CLI 사용하기가 스크립트 경로를 다룹니다. 호스팅된 백엔드 대신 직접 백엔드를 운영하고 싶다면, 게이트웨이도 오픈소스입니다 — 자체 게이트웨이 운영하기를 참고하십시오.

더 읽을거리

apidevelopersgateway