DeFi 프로토콜 개발 6계층
도입
DeFi protocol 개발은 Solidity contract 하나로 끝나지 않는다. contract가 reserve와 debt를 업데이트하면 oracle이 가격을 제공하고, indexer가 event를 읽고, backend가 사용자 상태를 계산하고, client가 행동 가능한 문구를 보여주고, operations가 alert와 pause rule을 관리한다. 한 계층이 빠지면 좋은 contract도 product failure를 만들 수 있다.
이 강의에서는 새 기능을 만들 때 "코드가 돌아가는가"가 아니라 "어떤 invariant가 어떤 계층에서 지켜지는가"를 먼저 묻는다. AMM, lending, vault, perps 모두 같은 방식으로 분해할 수 있다.
학습 목표
- protocol development를 contract, oracle, indexer, backend, client, operations 계층으로 분리한다.
- invariant-first 설계와 fixed-point rounding 방향을 release gate로 연결한다.
- DeFi 기능을 출시하기 전에 필요한 테스트와 모니터링 산출물을 정의한다.
개념 설명
CONTRACT
- state transition
- access control
- invariant
ORACLE
- fresh price
- decimals
- deviation guard
INDEXER
- event ordering
- snapshot
- reconciliation
BACKEND/CLIENT
- risk calculation
- user action
- copy
OPS
- alert
- pause matrix
- governance diff
| 계층 | 책임 | 놓치면 생기는 문제 |
|---|---|---|
| CONTRACT | state transition과 invariant | accounting drift |
| ORACLE | 가격 입력 검증 | wrong liquidation |
| INDEXER | event와 snapshot | 사용자 상태 불일치 |
| BACKEND | risk 계산 | 잘못된 한도와 경고 |
| CLIENT | 행동 가능한 UI | 사용자가 위험을 이해 못 함 |
| OPS | alert와 대응 | 사고 대응 지연 |
코드로 확인하기
release_gate: contract: - invariant_tests_pass - access_control_reviewed - rounding_direction_documented oracle: - stale_price_rejected - decimals_checked operations: - dashboard_alerts_created - pause_matrix_approvedexport function invariantResult(totalAssets: bigint, totalShares: bigint, minSharePriceRay: bigint) { if (totalShares === 0n) return { ok: true }; const sharePriceRay = (totalAssets * 10n ** 27n) / totalShares; return { ok: sharePriceRay >= minSharePriceRay, sharePriceRay };}YAML은 release가 checklist 문서가 아니라 배포 gate가 되어야 함을 보여준다. TypeScript invariant는 vault나 lending accounting을 backend에서도 재검증할 수 있음을 보여준다.
강의 포인트
| 관점 | 확인할 질문 | 증거로 남길 것 |
|---|---|---|
| Invariant | 절대 깨지면 안 되는 관계는 무엇인가 | test and monitor |
| Rounding | 누구에게 유리하게 반올림되는가 | direction policy |
| Events | 상태를 재구성할 수 있는가 | event schema |
| Operations | 실패 시 누가 무엇을 끄는가 | runbook |
실무 예시
컨트랙트[OPS] 새 vault 전략을 출시한다. contract test가 통과해도 release gate는 끝나지 않는다. oracle feed가 stale일 때 deposit이 막히는지, indexer가 share price event를 읽는지, UI가 withdrawal delay를 표시하는지, ops가 strategy loss alert를 받는지 확인해야 한다.
이 방식은 개발 속도를 늦추는 것처럼 보이지만 사고 비용을 낮춘다. DeFi에서 작은 rounding 오류나 event 누락은 나중에 reconciliation 불가능한 상태를 만들 수 있다.
흔한 오해와 실패 시나리오
| 오해 | 실패 시나리오 | 교정 방식 |
|---|---|---|
| audit를 받으면 된다 | 운영 alert와 UI 상태가 빠진다 | release gate를 계층별로 둔다 |
| invariant는 테스트용이다 | production monitor에도 필요하다 | onchain/offchain 재검증을 둔다 |
| event는 로그다 | indexer가 state를 복구하는 증거다 | event schema를 설계한다 |
| rounding은 사소하다 | 반복 거래에서 가치가 새어나간다 | 방향과 한계를 문서화한다 |
실습 과제
- 6계층 책임표 작성하기: AMM 또는 lending 기능 하나를 CONTRACT, ORACLE, INDEXER, BACKEND, CLIENT, OPS 책임으로 나눈다.
- Release gate YAML 만들기: invariant test, oracle check, dashboard alert, admin timelock을 요구하는 release gate를 작성한다.
완료 기준
- 새 DeFi 기능 하나를 6개 계층 책임과 실패 상태로 분해했다.
- invariant, oracle guard, monitoring alert, admin action을 release checklist로 작성했다.
근거 자료
- 11 Protocol Development
- OpenZeppelin Contracts