> ## Documentation Index
> Fetch the complete documentation index at: https://docs.intention.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# 매칭

> 오더북, 가격-시간 우선순위가 표현되는 방식, 주문 유효기간과 자기체결 방지가 그 위에서 해소되는 방식.

매칭은 체인이 말을 거는 외부 서비스가 아니라 [커널 실행](/ko/protocol/architecture/kernel) 안의 한 단계입니다. 블록의 주문을 커밋된 순서대로 받아 오더북에 대고 훑으며 체결을 냅니다. 누구의 잔액도 움직이지 않습니다. 잔액을 움직이는 일은 [클리어링 하우스](/ko/protocol/architecture/clearinghouse)의 몫이고, 매칭이 끝난 뒤에 일어납니다.

이 둘을 떼어 놓은 것이 엔진을 검사 가능하게 만듭니다. 매칭은 *무엇이 무엇과 거래되었는가*에 답합니다. 클리어링 하우스는 *그 거래가 얼마이고 이제 누가 누구에게 빚졌는가*에 답합니다.

<h2 id="the-book">
  오더북
</h2>

각 종목은 자체 오더북을 가지며, 서로 맞물린 세 가지 구조로 메모리에 보관됩니다.

<div className="dg" data-dg="matching-book">
  <div className="dg-c" style={{aspectRatio:"720 / 302"}}>
    <svg className="dg-w" viewBox="0 0 720 302" aria-hidden="true">
      <path className="dg-wire dg-soft" d="M 348.60 82.00 L 352.60 82.00" />

      <path className="dg-wire dg-soft" d="M 438.20 82.00 L 442.20 82.00" />

      <path className="dg-wire dg-soft" d="M 527.80 82.00 L 531.80 82.00" />

      <path className="dg-wire dg-soft" d="M 617.40 82.00 L 621.40 82.00" />

      <path className="dg-wire dg--blue" d="M 205.00 68.00 L 238.60 68.00" />

      <path className="dg-head dg--blue" d="M 245.00 68.00 L 238.60 72.40 L 238.60 63.60 Z" />

      <path className="dg-wire dg--sky" d="M 205.00 162.00 L 238.60 162.00" />

      <path className="dg-head dg--sky" d="M 245.00 162.00 L 238.60 166.40 L 238.60 157.60 Z" />
    </svg>

    <div className="dg-band" style={{left:"34.7222%",top:"9.9338%",width:"65.2778%",height:"56.2914%"}}><span className="dg-cap">slab arena — 사전 할당된 주문 슬롯 영역</span></div>
    <div className="dg-b dg--blue" style={{left:"0.0000%",top:"9.9338%",width:"27.7778%",height:"25.1656%"}}><span className="dg-t">가격 레벨</span><span className="dg-s">정렬된 맵 · 가격 → 레벨</span><span className="dg-n">최우선 호가는 훑지 않고 끝으로 이동해 얻음</span></div>
    <div className="dg-b dg--sky" style={{left:"0.0000%",top:"41.0596%",width:"27.7778%",height:"25.1656%"}}><span className="dg-t">주문 인덱스</span><span className="dg-s">주문 ID → 슬롯</span><span className="dg-n">취소와 정정이 상수 시간</span></div>
    <div className="dg-b dg--yellow" style={{left:"36.9444%",top:"19.5364%",width:"11.0556%",height:"15.2318%"}}><span className="dg-t">주문</span></div>
    <div className="dg-b dg--yellow" style={{left:"49.3889%",top:"19.5364%",width:"11.0556%",height:"15.2318%"}}><span className="dg-t">주문</span></div>
    <div className="dg-b dg--yellow" style={{left:"61.8333%",top:"19.5364%",width:"11.0556%",height:"15.2318%"}}><span className="dg-t">주문</span></div>
    <div className="dg-b dg--yellow" style={{left:"74.2778%",top:"19.5364%",width:"11.0556%",height:"15.2318%"}}><span className="dg-t">주문</span></div>
    <div className="dg-b dg--yellow" style={{left:"86.7222%",top:"19.5364%",width:"11.0556%",height:"15.2318%"}}><span className="dg-t">주문</span></div>
    <div className="dg-b dg-plain dg-left" style={{left:"36.9444%",top:"41.3907%",width:"60.8333%",height:"15.2318%"}}><span className="dg-s">도착 순서대로 꿰는 이중 연결 리스트로, 레벨 안의 우선순위가 계산이 아니라 위치로 정해집니다.</span></div>
    <div className="dg-b dg-dashed dg-left" style={{left:"0.0000%",top:"74.8344%",width:"100.0000%",height:"20.5298%"}}><span className="dg-t">재사용 순서가 고정된 이유</span><span className="dg-s">해제된 슬롯은 정해진 순서로 재사용되고 인덱스의 시드도 고정입니다. 성능을 위한 선택이 아닙니다. 두 검증자가 슬롯을 다른 순서로 재사용하면 포크가 납니다.</span></div>
    <div className="dg-lbl" style={{left:"31.2500%",top:"17.8808%",width:"15.2778%",whiteSpace:"normal"}}>각 레벨의 선두</div>
    <div className="dg-lbl" style={{left:"31.2500%",top:"62.9139%",width:"15.2778%",whiteSpace:"normal"}}>직접 조회</div>
  </div>
</div>

| 구조         | 역할                                                         |
| ---------- | ---------------------------------------------------------- |
| **가격 레벨**  | 가격에서 레벨로 가는 정렬된 맵. 최우선 매수호가와 매도호가를 훑어 찾는 대신 끝으로 이동해 얻습니다   |
| **주문 체인**  | 주문을 도착 순서대로 꿰는 이중 연결 리스트. 같은 레벨 안의 우선순위가 계산이 아니라 위치로 정해집니다 |
| **주문 인덱스** | 주문 ID에서 해당 슬롯으로 가는 직접 맵. 취소와 정정이 탐색이 아니라 상수 시간으로 처리됩니다     |

주문은 **slab arena** 안에 삽니다. 상수 시간에 할당하고 해제하는 사전 할당 영역입니다. 그래서 오더북 연산은 핫 패스에서 메모리를 할당하지 않고, 해제된 슬롯은 할당기가 마음대로 놓는 자리가 아니라 정해진 순서로 재사용됩니다. 마지막 항목은 성능을 위한 선택이 아닙니다. 두 검증자가 슬롯을 다른 순서로 재사용하면, 슬롯 배치를 관측하는 모든 것이 갈라지기 때문입니다.

같은 원칙이 주문 인덱스에도 적용되어, 인덱스의 시드는 무작위가 아니라 고정입니다. 프로세스마다 시드를 달리하는 해시 맵은 충돌 공격에 대한 표준적인 방어책이지만, 합의 실행 경로 위에서는 포크입니다.

가격은 처음부터 끝까지 정수입니다. 소수가 아니라 서브틱 단위이며, 이 단위가 제출하는 값과 어떻게 대응되는지는 [정밀도](/ko/trading/precision)에 정리되어 있습니다.

<h2 id="priority">
  우선순위
</h2>

우선순위는 가격이 먼저이고, 그다음이 그 가격의 체인 안에서의 위치입니다. 여기서 "시간"은 주문이 어느 노드에 도착한 시각이 아니라, 커밋된 블록 순서 안의 정규 위치입니다.

이것이 블록 내부의 지연 경쟁을 없앱니다. 같은 블록에 든 두 주문은 모든 검증자가 동일하게 계산하는 선후 관계를 가지며, 특정 노드에 아무리 가까이 붙어 있어도 그 선후를 바꾸지 못합니다. 블록과 블록 사이에서는 여전히 도착 시각이 중요합니다. 다만 경쟁의 단위가 마이크로초가 아니라 블록입니다.

커널의 단계 순서가 이를 한 번 더 강화합니다. 블록 안에서 취소가 공격적 주문 제출보다 먼저 실행되므로, 취소와 같은 블록에 도착한 주문이 대기 호가를 가져갈 수 없습니다.

<h2 id="matching-an-order">
  주문 매칭
</h2>

<div className="dg" data-dg="matching-walk">
  <div className="dg-c" style={{aspectRatio:"720 / 334"}}>
    <svg className="dg-w" viewBox="0 0 720 334" aria-hidden="true">
      <path className="dg-wire dg--blue" d="M 134.00 144.00 L 155.60 144.00" />

      <path className="dg-head dg--blue" d="M 162.00 144.00 L 155.60 148.40 L 155.60 139.60 Z" />

      <path className="dg-wire dg--sky" d="M 320.00 144.00 L 345.60 144.00" />

      <path className="dg-head dg--sky" d="M 352.00 144.00 L 345.60 148.40 L 345.60 139.60 Z" />

      <path className="dg-wire dg--green" d="M 510.00 144.00 L 535.60 144.00" />

      <path className="dg-head dg--green" d="M 542.00 144.00 L 535.60 148.40 L 535.60 139.60 Z" />

      <path className="dg-wire dg--sky" d="M 633.00 114.00 L 633.00 80.00 L 241.00 80.00 L 241.00 103.60" />

      <path className="dg-head dg--sky" d="M 241.00 110.00 L 236.60 103.60 L 245.40 103.60 Z" />

      <path className="dg-wire dg--green" d="M 633.00 174.00 L 633.00 213.60" />

      <path className="dg-head dg--green" d="M 633.00 220.00 L 628.60 213.60 L 637.40 213.60 Z" />

      <path className="dg-wire dg--sky" d="M 241.00 178.00 L 241.00 213.60" />

      <path className="dg-head dg--sky" d="M 241.00 220.00 L 236.60 213.60 L 245.40 213.60 Z" />
    </svg>

    <div className="dg-b dg--blue" style={{left:"0.0000%",top:"35.3293%",width:"18.0556%",height:"15.5689%"}}><span className="dg-t">들어온 주문</span></div>
    <div className="dg-b dg--yellow dg-round" style={{left:"23.0556%",top:"34.1317%",width:"20.8333%",height:"17.9641%"}}><span className="dg-t">오더북과 교차?</span></div>
    <div className="dg-b dg--sky" style={{left:"49.4444%",top:"35.3293%",width:"20.8333%",height:"15.5689%"}}><span className="dg-t">반대편 최우선 레벨 소진</span></div>
    <div className="dg-b dg--green" style={{left:"75.8333%",top:"35.3293%",width:"24.1667%",height:"15.5689%"}}><span className="dg-t">체결 생성</span></div>
    <div className="dg-b dg--green" style={{left:"75.8333%",top:"67.0659%",width:"24.1667%",height:"25.7485%"}}><span className="dg-t">완료</span></div>
    <div className="dg-b dg--sky dg-left" style={{left:"10.5556%",top:"67.0659%",width:"45.8333%",height:"25.7485%"}}><span className="dg-t">주문 유효기간에 따라 잔량을 대기 또는 거부</span><span className="dg-s">GTC 대기 · IOC 취소 · FOK 전량 아니면 미체결 · 포스트 온리는 교차 대신 거부</span></div>
    <div className="dg-lbl" style={{left:"60.6944%",top:"23.9521%",width:"27.7778%",whiteSpace:"normal"}}>잔량 — 다음 레벨로</div>
    <div className="dg-lbl" style={{left:"87.9167%",top:"58.9820%"}}>잔량 없음</div>
  </div>
</div>

매처는 들어온 주문이 소진되거나 오더북이 더 이상 교차하지 않을 때까지, 반대편 선두를 반복해서 소진하며 잡아먹는 메이커마다 체결을 하나씩 내보냅니다. 남은 잔량을 어떻게 할지는 주문 유효기간이 정합니다.

* **GTC** — 잔량을 오더북에 대기시킵니다.
* **IOC** — 잔량을 취소합니다.
* **FOK** — 주문 전량을 채울 수 없으면 아무것도 체결되지 않습니다.
* **ALO** — 포스트 온리입니다. 주문이 유동성을 가져가게 되면 교차하는 대신 거부됩니다.

체결에는 생성되는 시점에 귀속 정보가 붙습니다. 각 체결은 자기 종목의 체결 순서 안에서 어디에 있는지를 기록하고, 출력을 조립할 때 종목별 위치가 블록 전체를 아우르는 하나의 순서로 정리됩니다. 나중에 어떤 이벤트를 정확히 어떤 트랜잭션과 블록의 어느 지점까지 되짚을 수 있는 것은 이 덕분입니다.

<h2 id="self-trade-prevention">
  자기체결 방지
</h2>

들어온 주문이 같은 소유자의 대기 유동성과 매칭될 상황이 되면, 그 매칭은 실행되는 대신 억제됩니다. 어느 쪽이 물러날지는 설정할 수 있습니다.

| 모드         | 동작                           |
| ---------- | ---------------------------- |
| **테이커 만료** | 들어온 주문이 취소됩니다                |
| **메이커 만료** | 대기 주문이 취소되고 들어온 주문은 계속 진행됩니다 |
| **양쪽 만료**  | 둘 다 취소됩니다                    |

이렇게 취소된 메이커 주문은 매칭 중에 모아 두었다가 같은 블록 안에서 제거되므로, 오더북이 이미 억제된 주문을 계속 들고 있지 않습니다.

이 검사에서의 소유권은 오더북이 추적하는 계정 단위로 판정됩니다. 거래 관점의 설명은 [자기체결 방지](/ko/trading/self-trade-prevention)를 참고하십시오.

<h2 id="what-matching-does-not-do">
  매칭이 하지 않는 일
</h2>

매칭은 수수료를 계산하지 않고, 손익을 실현하지 않고, 포지션을 조정하지 않으며, 증거금을 검사하지 않습니다. 이 모두는 매칭이 낸 체결을 받아 매칭 이후 [클리어링 하우스](/ko/protocol/architecture/clearinghouse)에서 일어납니다.

주문이 존재해도 되는지를 판단하지도 않습니다. 증거금 적정성, 미체결 주문 수 한도, 리듀스 온리 제약, 시장가의 지정가 전환은 주문이 오더북에 닿기 전에 해소됩니다. 매처가 주문을 볼 시점에 남은 질문은 그 주문이 오더북의 어디에 놓이는가뿐입니다.

<h2 id="where-to-go-next">
  다음으로 읽을 문서
</h2>

<CardGroup cols={2}>
  <Card title="클리어링 하우스" href="/ko/protocol/architecture/clearinghouse">
    체결이 생긴 뒤 잔액과 포지션에 무슨 일이 일어나는지 설명합니다.
  </Card>

  <Card title="주문 유형" href="/ko/trading/order-types">
    거래 관점의 설명입니다. 무엇을 제출할 수 있고 각 유형이 어떻게 동작하는지 다룹니다.
  </Card>

  <Card title="오더북" href="/ko/trading/order-book">
    깊이와 가격 레벨, 그리고 트레이더 관점에서 오더북을 읽는 법입니다.
  </Card>

  <Card title="IntentionKernel" href="/ko/protocol/architecture/kernel">
    블록 실행에서 매칭이 놓이는 자리입니다.
  </Card>
</CardGroup>
