SettleLab
전체 코스
LESSON 05Privacy and Non-EVM

Solana 계정 모델

핵심40분근거 2

학습 결과

  • Solana의 program/account 분리와 rent, ownership 개념을 설명한다.
  • 토큰 결제 구현 시 필요한 account 준비 흐름을 설계한다.

선행 조건

  • Move, Sui, Aptos 비교

완료 기준

  • Solana account model을 program account, data account, owner program, rent 관점에서 설명했다.
  • USDC checkout에 필요한 ATA 준비 흐름과 비용 부담 정책을 설계했다.
  • account list failure, owner mismatch, mint mismatch, indexer 지연을 트랜잭션 실패 조건으로 정리했다.

Solana 계정 모델

도입

Solana에서 stablecoin 결제를 구현할 때 가장 흔한 착각은 "recipient 주소만 알면 전송이 된다"는 것이다. EVM에서는 token contract가 code와 storage를 함께 갖고 있어 transfer 호출이 비교적 익숙한 모양을 띤다. Solana에서는 program account가 실행 코드를 담고, mutable state는 별도의 account에 저장된다. instruction은 실행할 program뿐 아니라 읽고 쓸 account list를 함께 제출해야 한다.

따라서 Solana 결제 설계의 핵심은 함수 호출보다 account 준비다. merchant token account가 있는지, payer가 account creation 비용을 부담하는지, 어떤 account가 signer/writable인지, owner program이 무엇인지가 checkout 성공률과 운영 비용을 좌우한다.

학습 목표

  • Solana의 program/account 분리와 rent, ownership 개념을 설명한다.
  • 토큰 결제 구현 시 필요한 account 준비 흐름을 설계한다.

개념 설명

상태머신가로 스크롤 · 크게 보기 지원
Solana 계정 모델 상태머신이 시각화는 privacy 기능과 non-EVM 실행환경에서 상태 전이가 어떤 증거와 실패 조건으로 움직이는지를 보여주며, 'Solana 계정 모델'에서 남겨야 할 설계 증거를 좁힌다.
State 1

AccountDeclared

Solana의 program/account 분리와 rent, ownership 개념을 설명한다.

program owner, token account, PDA, signer의 역할을 분리한다.
State 2

PdaDerived

숨길 데이터와 공개할 데이터가 분리되는가

seed, bump, merchant, mint가 client와 program에서 같은 규칙으로 검증된다.
State 3

RentOrOwnerMismatch

체인별 ownership 모델을 오해하지 않는가

rent 부족, owner mismatch, ATA 누락을 서로 다른 실패 사유로 기록한다.
State 4

SettlementRecorded

Solana 계정 모델 이해 점검

account model을 설명했다.
크게 보기
State 1

AccountDeclared

Solana의 program/account 분리와 rent, ownership 개념을 설명한다.

program owner, token account, PDA, signer의 역할을 분리한다.
State 2

PdaDerived

숨길 데이터와 공개할 데이터가 분리되는가

seed, bump, merchant, mint가 client와 program에서 같은 규칙으로 검증된다.
State 3

RentOrOwnerMismatch

체인별 ownership 모델을 오해하지 않는가

rent 부족, owner mismatch, ATA 누락을 서로 다른 실패 사유로 기록한다.
State 4

SettlementRecorded

Solana 계정 모델 이해 점검

account model을 설명했다.

account가 상태의 기본 단위다

Solana 공식 문서는 account를 state 저장의 기본 단위로 설명한다. 모든 account는 lamports, data, owner, executable, rent 관련 필드를 가지며, account의 data를 수정할 수 있는 주체는 해당 account의 owner program이다. 이 구조 때문에 Solana transaction은 "어떤 program을 호출한다"와 "그 program이 어떤 account를 읽고 쓸 수 있는가"를 함께 선언한다.

표 자료가로 스크롤 · 크게 보기 지원
개념결제 설계에서의 의미
Program accountexecutable code를 담는다. SPL Token 또는 Token-2022 program이 여기에 해당한다.
Data account잔고, mint, 설정 등 mutable state를 담는다.
System account기본 SOL 보유와 account creation에 관여한다.
PDAprogram-derived address. program이 직접 private key 없이 서명 가능한 주소처럼 사용한다.
Instructionprogram 실행 요청. account list와 data가 함께 간다.
Transaction여러 instruction을 원자적으로 묶는다. account 생성과 transfer를 함께 넣을 수 있다.
CPIprogram이 다른 program을 호출한다. Transfer Hook 같은 extension에서 중요하다.
크게 보기
개념결제 설계에서의 의미
Program accountexecutable code를 담는다. SPL Token 또는 Token-2022 program이 여기에 해당한다.
Data account잔고, mint, 설정 등 mutable state를 담는다.
System account기본 SOL 보유와 account creation에 관여한다.
PDAprogram-derived address. program이 직접 private key 없이 서명 가능한 주소처럼 사용한다.
Instructionprogram 실행 요청. account list와 data가 함께 간다.
Transaction여러 instruction을 원자적으로 묶는다. account 생성과 transfer를 함께 넣을 수 있다.
CPIprogram이 다른 program을 호출한다. Transfer Hook 같은 extension에서 중요하다.

EVM 호출과 Solana instruction 비교

표 자료가로 스크롤 · 크게 보기 지원
항목EVMSolana
code/state 배치contract가 code와 storage를 함께 가짐program code와 data account 분리
호출 입력calldata 중심instruction + account list
상태 접근contract 내부 storage 접근account read/write set 명시
병렬 처리실행 중 storage 충돌 판단account list로 병렬성 판단
토큰 구현token별 ERC-20 contractSPL Token/Token-2022 program과 mint/token account
크게 보기
항목EVMSolana
code/state 배치contract가 code와 storage를 함께 가짐program code와 data account 분리
호출 입력calldata 중심instruction + account list
상태 접근contract 내부 storage 접근account read/write set 명시
병렬 처리실행 중 storage 충돌 판단account list로 병렬성 판단
토큰 구현token별 ERC-20 contractSPL Token/Token-2022 program과 mint/token account

이 차이는 성능 설명으로 끝나지 않는다. account list가 틀리면 transaction은 실행 전후 단계에서 실패한다. writable로 넘겨야 할 account를 readonly로 넘기거나, ATA가 없는데 transfer만 보내거나, Token Program과 Token-2022 Program ID를 혼동하면 checkout은 실패한다.

USDC checkout의 ATA 준비 흐름

Solana stablecoin 결제에서 일반적으로 검토할 흐름은 다음과 같다.

흐름도가로 스크롤 · 크게 보기 지원
강의 흐름도상태, 책임, 검증 지점을 순서대로 읽기 위한 다이어그램이다.
크게 보기

여기서 중요한 것은 account creation을 결제 UX의 일부로 본다는 점이다. destination ATA가 없으면 누가 만들고 비용을 내는지 정해야 한다. 사용자에게 한 번에 보이는 transaction이라도 내부적으로는 ATA 생성, transfer, memo 또는 후속 프로그램 호출이 함께 있을 수 있다.

코드로 확인하기

Solana에서는 account가 데이터 저장소이고 program이 그 데이터를 해석한다. 결제 시스템은 "누가 token을 갖고 있는가"뿐 아니라 "어떤 account가 어떤 program에 의해 소유되는가"를 확인해야 한다.

컨트랙트vault PDA account 구조

CODE SURFACErust
use anchor_lang::prelude::*;#[account]pub struct MerchantVault {    pub merchant: Pubkey,    pub mint: Pubkey,    pub bump: u8,    pub settled_amount: u64,}#[derive(Accounts)]pub struct Settle<'info> {    #[account(        mut,        seeds = [b"merchant-vault", merchant.key().as_ref(), vault.mint.as_ref()],        bump = vault.bump,        has_one = merchant    )]    pub vault: Account<'info, MerchantVault>,    /// CHECK: merchant는 서명자가 아니라 vault seed와 has_one 검증의 기준 identity다.    pub merchant: UncheckedAccount<'info>,}pub fn settle(ctx: Context<Settle>, amount: u64) -> Result<()> {    let vault = &mut ctx.accounts.vault;    require!(amount > 0, CheckoutError::ZeroAmount);    require_keys_eq!(vault.merchant, ctx.accounts.merchant.key());    vault.settled_amount = vault        .settled_amount        .checked_add(amount)        .ok_or(CheckoutError::Overflow)?;    Ok(())}#[error_code]pub enum CheckoutError {    #[msg("amount must be greater than zero")]    ZeroAmount,    #[msg("settled amount overflow")]    Overflow,}

PDA는 임의 주소가 아니라 seed와 bump로 재현 가능한 program-derived address다. vault account가 올바른 merchant와 mint를 가리키는지 검증해야 한다.

클라이언트merchant vault PDA 파생

CODE SURFACEtypescript
function deriveMerchantVault(programId: PublicKey, merchant: PublicKey, mint: PublicKey) {  return PublicKey.findProgramAddressSync(    [      Buffer.from("merchant-vault"),      merchant.toBuffer(),      mint.toBuffer()    ],    programId  );}

클라이언트와 program이 같은 seed 규칙을 써야 reconciliation이 가능하다. seed 규칙이 문서화되지 않으면 운영자는 어느 vault가 어느 merchant의 것인지 추적하기 어렵다.

강의 포인트

Solana 계정 모델은 "프로그램이 stateless하다"는 문장만 외우면 실무로 이어지지 않는다. 결제 제품에서는 account list가 곧 입력 검증 목록이고, rent가 곧 onboarding 비용이며, owner program이 곧 권한 경계다.

강의에서는 다음 질문을 반복해서 던진다.

표 자료가로 스크롤 · 크게 보기 지원
질문왜 중요한가
이 transaction이 읽고 쓰는 account는 무엇인가병렬성, 실패 원인, 권한 검증의 출발점이다.
이 token account의 owner와 mint는 무엇인가다른 사용자의 token account나 잘못된 mint로 보내는 사고를 막는다.
legacy SPL Token과 Token-2022 중 무엇인가program ID와 extension decoding이 달라진다.
account creation 비용은 누가 내는가checkout UX, fee display, refund 정책에 영향을 준다.
indexer는 어떤 event/state를 기준으로 완료를 판정하는가signature 성공만으로 회계 완료를 확정하면 안 된다.
크게 보기
질문왜 중요한가
이 transaction이 읽고 쓰는 account는 무엇인가병렬성, 실패 원인, 권한 검증의 출발점이다.
이 token account의 owner와 mint는 무엇인가다른 사용자의 token account나 잘못된 mint로 보내는 사고를 막는다.
legacy SPL Token과 Token-2022 중 무엇인가program ID와 extension decoding이 달라진다.
account creation 비용은 누가 내는가checkout UX, fee display, refund 정책에 영향을 준다.
indexer는 어떤 event/state를 기준으로 완료를 판정하는가signature 성공만으로 회계 완료를 확정하면 안 된다.

실무 예시

Solana USDC 결제 트랜잭션을 설계할 때 제출물은 코드보다 먼저 account matrix여야 한다.

표 자료가로 스크롤 · 크게 보기 지원
Account역할signerwritable실패 시나리오
payer walletfee payer, 사용자 승인 주체yesyesSOL 부족으로 fee/rent 지불 실패
source token account사용자의 USDC ATAnoyesmint 불일치, 잔고 부족, frozen state
destination token accountmerchant USDC ATAnoyesATA 미생성, owner mismatch
mintUSDC mintnono잘못된 mint allowlist
token programSPL Token 또는 Token-2022nonoprogram ID 혼동
associated token programATA 생성 시 사용nono생성 instruction 누락
크게 보기
Account역할signerwritable실패 시나리오
payer walletfee payer, 사용자 승인 주체yesyesSOL 부족으로 fee/rent 지불 실패
source token account사용자의 USDC ATAnoyesmint 불일치, 잔고 부족, frozen state
destination token accountmerchant USDC ATAnoyesATA 미생성, owner mismatch
mintUSDC mintnono잘못된 mint allowlist
token programSPL Token 또는 Token-2022nonoprogram ID 혼동
associated token programATA 생성 시 사용nono생성 instruction 누락

이 표가 있으면 support ticket도 단순해진다. "결제가 실패했다"를 "destination ATA 없음", "fee payer SOL 부족", "program ID mismatch", "source ATA owner mismatch" 같은 진단 가능한 상태로 바꿀 수 있다.

흔한 오해와 실패 시나리오

표 자료가로 스크롤 · 크게 보기 지원
오해실패 장면바로잡는 기준
address만 있으면 token을 받을 수 있다.merchant token account가 없어 transfer가 실패한다.recipient wallet address와 destination token account를 구분한다.
simulation이 통과하면 회계도 완료다.signature는 성공했지만 indexer 반영 지연으로 dashboard가 누락된다.transaction status, token balance diff, indexer checkpoint를 분리한다.
account list는 SDK가 알아서 채운다.Transfer Hook이나 Token-2022 extension에서 extra account가 누락된다.instruction별 required account list를 명시적으로 검토한다.
rent 비용은 infra 비용이라 제품과 무관하다.신규 merchant onboarding에서 account creation 비용을 누가 내는지 분쟁이 생긴다.account creation 비용과 환불 불가 비용을 정책 문서에 넣는다.
크게 보기
오해실패 장면바로잡는 기준
address만 있으면 token을 받을 수 있다.merchant token account가 없어 transfer가 실패한다.recipient wallet address와 destination token account를 구분한다.
simulation이 통과하면 회계도 완료다.signature는 성공했지만 indexer 반영 지연으로 dashboard가 누락된다.transaction status, token balance diff, indexer checkpoint를 분리한다.
account list는 SDK가 알아서 채운다.Transfer Hook이나 Token-2022 extension에서 extra account가 누락된다.instruction별 required account list를 명시적으로 검토한다.
rent 비용은 infra 비용이라 제품과 무관하다.신규 merchant onboarding에서 account creation 비용을 누가 내는지 분쟁이 생긴다.account creation 비용과 환불 불가 비용을 정책 문서에 넣는다.

실습 과제

  1. Solana 계정 모델 이해 점검: Solana USDC 결제에 필요한 account, signer, writable 여부, owner program을 표로 작성한다. ATA 생성 비용과 실패 처리를 한 줄씩 붙인다.
  2. Solana 계정 모델 적용 과제: EVM transferFrom 기반 checkout flow와 Solana instruction + account list flow를 나란히 그리고, 운영 로그에 저장할 필드를 signature, sourceAta, destinationAta, mint, tokenProgram, finalizedBalanceDelta로 정리한다.

완료 기준

  1. Solana account model을 program account, data account, owner program, rent 관점에서 설명했다.
  2. USDC checkout에 필요한 ATA 준비 흐름과 비용 부담 정책을 설계했다.
  3. account list failure, owner mismatch, mint mismatch, indexer 지연을 트랜잭션 실패 조건으로 정리했다.

근거 자료

Final checkpoint

읽기를 마쳤다면 여기서 기록한다

아래 버튼은 읽기 진도를 저장한다. 체크리스트, 과제, 랩 산출물은 위 Workbook에서 따로 관리한다.

  • Solana account model을 program account, data account, owner program, rent 관점에서 설명했다.
  • USDC checkout에 필요한 ATA 준비 흐름과 비용 부담 정책을 설계했다.
  • account list failure, owner mismatch, mint mismatch, indexer 지연을 트랜잭션 실패 조건으로 정리했다.

학습 자료 근거

Solana 계정모델
Solana program/data account 분리, instruction/account list 모델, 결제 영향 정리의 근거.
내부 참고 문서
Solana Accounts Documentation
https://solana.com/docs/core/accounts