솔라나는 거래가 사용할 계정을 메시지에 미리 열거하므로, 스케줄러가 실행 전에 읽기 전용과 쓰기 가능 계정을 알 수 있습니다. 두 거래가 같은 계정을 쓰려 하거나 한쪽이 쓰는 계정을 다른 쪽이 읽으면 동시에 안전하게 실행할 수 없어 직렬화됩니다. 서로 다른 계정만 변경하는 거래는 같은 프로그램을 호출해도 병렬 실행될 수 있습니다. 따라서 충돌을 프로그램 이름이나 사용자 수가 아니라 실제 writable account 교집합으로 진단해야 합니다.
잠금은 프로그램이 아니라 계정 주소에 걸린다
Solana의 프로그램은 실행 코드를 제공하고 변경 가능한 상태는 별도 계정에 저장됩니다. 각 instruction은 프로그램 ID와 함께 읽거나 쓸 계정을 넘기며, transaction message는 이 계정 목록과 권한을 컴파일합니다. 런타임은 실행을 시작하기 전에 어떤 주소가 읽기 전용이고 어떤 주소가 writable인지 알 수 있습니다. 그래서 동일한 토큰 프로그램을 부르는 두 송금도 서로 다른 사용자 토큰 계정만 건드리면 병렬 후보가 되지만, 하나의 풀·오더북·민팅 상태처럼 같은 writable 계정을 공유하면 충돌합니다.
이 구분은 ‘Solana는 모든 거래를 병렬 처리한다’는 표현의 범위를 바로잡습니다. 병렬성은 가능성이지 보장이 아닙니다. 스케줄러는 계정 의존성과 블록 자원 한도, 우선순위 등을 함께 고려합니다. 주소가 다르더라도 한 transaction 안의 instruction은 원자적 순서로 실행되고, 어느 instruction이 실패하면 거래의 상태 변경은 커밋되지 않습니다. 계정 목록을 정확히 선언하는 구조가 안전한 병렬성의 출발점입니다.
솔라나의 병렬성은 프로그램 수가 아니라 동시에 잠글 수 있는 계정 집합에서 나온다.
JOBCOIN 해설

그림은 이 주제의 공통 개념을 단순화한 설명입니다. 아래 항목에서 이 글의 구체적인 조건과 예외를 함께 읽어보세요.
- 잠금은 프로그램이 아니라 계정 주소에 걸린다
Solana의 프로그램은 실행 코드를 제공하고 변경 가능한 상태는 별도 계정에 저장됩니다.
- 읽기와 쓰기 조합으로 충돌을 판정한다
두 거래의 계정 집합을 비교할 때 읽기-읽기는 상태를 바꾸지 않으므로 함께 실행할 수 있습니다.
- AccountInUse류 메시지는 원인보다 증상에 가깝다
클라이언트나 특정 처리 경로에서 AccountInUse 계열 오류를 봤다면 먼저 실패가 온체인 실행 오류인지, 전송·시뮬레이션·리더 스케줄링 단계의 일시적 잠금 충돌인지 구분해야 합니다.
AI로 제작한 개념도 · 실제 가격·거래 내역·통계가 아닙니다.
읽기와 쓰기 조합으로 충돌을 판정한다
두 거래의 계정 집합을 비교할 때 읽기-읽기는 상태를 바꾸지 않으므로 함께 실행할 수 있습니다. 반면 쓰기-쓰기는 양쪽 결과의 순서가 상태를 바꿀 수 있고, 쓰기-읽기도 읽는 값이 어느 시점의 값인지 달라지므로 동시에 실행할 수 없습니다. 한 거래가 여러 instruction을 담으면 instruction별 목록을 합친 transaction 전체 권한이 판단 기준이 됩니다. CPI로 호출된 프로그램도 상위 instruction이 전달한 권한을 넘어 임의 계정을 쓰지 못합니다.
예를 들어 A가 금고 V와 사용자 U1을 쓰고 B가 같은 V와 U2를 쓴다면 U1·U2가 달라도 V 때문에 직렬화됩니다. C가 가격 계정 P를 읽기만 하고 D도 P를 읽기만 하면 그 교집합은 충돌 원인이 아닙니다. 그러나 E가 P를 갱신하면 C·D와 E 사이에는 쓰기-읽기 의존성이 생깁니다. 이 표는 실행 성공을 보장하는 표가 아니라 계정 잠금 관점의 병렬 가능성을 분류한 것입니다.
| 거래 A | 거래 B | 잠금 관점 결과 |
|---|---|---|
| P 읽기 | P 읽기 | 읽기 공유 가능 |
| V 쓰기 | V 읽기 | 동시 실행 불가, 순서 필요 |
| V 쓰기 | V 쓰기 | 동시 실행 불가, 직렬화 |
| U1 쓰기 | U2 쓰기 | 주소가 다르면 병렬 후보 |
AccountInUse류 메시지는 원인보다 증상에 가깝다
클라이언트나 특정 처리 경로에서 AccountInUse 계열 오류를 봤다면 먼저 실패가 온체인 실행 오류인지, 전송·시뮬레이션·리더 스케줄링 단계의 일시적 잠금 충돌인지 구분해야 합니다. 모든 현대 클라이언트가 같은 문자열을 같은 상황에 노출한다고 가정하면 안 됩니다. 서명 상태, RPC 응답, simulation logs, slot과 blockhash 만료를 함께 기록해야 재전송이 필요한지 프로그램 수정이 필요한지 판단할 수 있습니다.
무작정 즉시 재전송하면 같은 핫 계정에 더 많은 경쟁을 만들고 recent blockhash 만료 뒤 중복 의도를 낳을 수 있습니다. 기존 서명의 상태를 먼저 조회하고, 아직 유효한 transaction을 새 서명으로 반복하지 않으며, 재시도에는 제한과 지연을 둡니다. 계정 충돌이 반복되면 시간대별 writable account 빈도와 실패율을 묶어 봐야 합니다. 평균 TPS만으로는 특정 상태 계정에 몰린 경합을 찾기 어렵습니다.
- transaction message에서 writable 계정 주소를 추출해 실패 거래끼리 교집합을 계산한다
- 같은 서명의 처리 상태와 recent blockhash 유효성을 확인한 뒤 재전송 여부를 정한다
- simulation logs의 프로그램 오류와 전송 단계의 잠금·만료 오류를 분리한다
- 핫 계정별 요청률·성공률·지연을 측정하고 재시도 상한을 둔다
상태 분할은 정확성 비용과 함께 평가한다
하나의 전역 카운터를 사용자별 또는 버킷별 PDA로 나누면 writable 교집합이 줄 수 있습니다. 그러나 집계 값을 즉시 일관되게 읽어야 한다면 여러 계정을 다시 모으거나 별도 집계 단계가 필요합니다. 계정 수가 늘면 transaction 크기, 로드 비용, rent와 운영 복잡도도 늘 수 있습니다. ‘샤딩하면 빨라진다’가 아니라 어떤 불변조건을 어느 시점에 보장할지 먼저 써야 합니다.
권장 순서는 측정, 최소 분할, 불변조건 테스트입니다. 먼저 상위 충돌 계정과 실제 병목을 찾고, 자연스러운 소유 단위가 있는 상태만 분리합니다. 그 다음 동시에 실행된 두 거래가 잔액·공급량·nonce 같은 불변조건을 깨지 않는지 검증합니다. 병렬 실행률이 올라도 실패 후 보상 로직이 복잡해진다면 전체 사용자 경험은 나빠질 수 있습니다.
실무 진단은 계정 집합에서 시작한다
탐색기에서 프로그램 호출 수만 세지 말고 transaction의 account keys와 writable 표시를 수집합니다. 실패 거래와 성공 거래를 같은 시간 창에서 비교해 특정 계정이 공통으로 등장하는지 봅니다. 우선순위 수수료는 스케줄링 가능성을 높일 수 있지만 동일 writable 계정의 상태 의존성을 제거하지 않습니다. 높은 수수료가 병렬성 자체를 구매하는 것은 아닙니다.
결론적으로 솔라나 병렬 실행의 단위는 선언된 계정 접근입니다. 읽기 전용 공유, 쓰기 충돌, transaction 원자성, 재시도 상태를 분리하면 처리 지연을 프로그램 성능 문제로 오인하지 않게 됩니다. Compute Budget를 조정하기 전에 어떤 계정이 직렬화 지점을 만드는지 확인하는 편이 비용과 원인을 함께 설명합니다.
자주 묻는 질문
같은 프로그램을 호출하면 항상 직렬 실행되나요?
아닙니다. 같은 프로그램이라도 서로 다른 writable 계정을 사용하고 공유 계정은 읽기 전용이면 병렬 실행 후보가 될 수 있습니다.
읽기 전용 계정을 여러 거래가 함께 사용해도 되나요?
계정 잠금 관점에서는 읽기-읽기 공유가 가능합니다. 다만 블록 자원 한도와 다른 스케줄링 조건은 별도로 적용됩니다.
우선순위 수수료를 높이면 계정 충돌이 사라지나요?
사라지지 않습니다. 처리 순서에 영향을 줄 수 있지만 동일 writable 계정의 실행 의존성은 유지됩니다.
더 깊이 읽기
본문에서 다룬 개념과 확인 절차를 다음 글에서 이어서 살펴보세요.



