· 8분 읽기
Aptos Move 실전 가이드: 리소스 모델, 권한, 업그레이드, 가스
Aptos는 합의로 트랜잭션의 순서를 정하고, Move VM으로 상태 변경을 계산합니다. 이 구조 덕분에 실행 규칙이 언어 레벨에서 명확하게 드러나고, 컨트랙트 설계의 출발점도 자연스럽게 Move가 강제하는 소유권·권한·타입 규칙이 됩니다. 이 글은 Move의 실행 모델에서 시작해 권한 모델, entry function 실전, 업그레이드 정책, 가스 구조까지 Aptos 개발에 필요한 축을 한 번에 정리합니다.
Move 실행 모델과 리소스 중심 소유권
Move가 계약 로직에서 애매한 권한 경로를 줄이는 데 유리한 이유는 세 가지입니다.
- 리소스 중심 모델로 자산 복제를 통제합니다.
- 모듈 경계로 접근 제어를 강제합니다.
signer로 권한 주체를 명시합니다.
다른 VM과 비교하면 관점 차이가 분명해집니다.
| VM | 상태 저장 관점 |
|---|---|
| EVM | 계약 계정 중심 저장 |
| Solana | 프로그램 + 계정 지정 중심 |
| Aptos/Move | 소유자 계정 리소스 중심 + 강한 타입 제약 |
Aptos는 여기에 병렬 실행(Block-STM)을 결합해 고처리량을 목표로 합니다. 설계 단계에서는 다음 세 가지 기준을 지키는 것이 좋습니다.
- 데이터는 "모듈 배포 계정"이 아니라 "실제 소유 계정"에 저장합니다.
- 자산 입출금 권한은
signer기반으로 최소화합니다. - 제네릭은 타입 안정성 이점이 큰 경로에만 적용합니다.
구조체와 ability: 타입으로 동작을 제한한다
Move의 struct는 순수한 데이터 컨테이너입니다.
- 구조체 안에 메서드를 넣지 않습니다.
- 상속이 없습니다.
- 한 번 온체인에 배포된 구조체의 필드 정의는 바꿀 수 없습니다.
타입 안정성을 강하게 잡는 대신, 업그레이드 유연성은 모듈 레벨에서 관리하는 구조입니다. 각 타입이 할 수 있는 동작은 ability 조합으로 제한합니다.
| Ability | 허용되는 동작 |
|---|---|
copy |
값 복제 |
drop |
값 폐기 |
store |
다른 구조체 내부나 전역 저장소에 저장 |
key |
계정 전역 저장소의 최상위 리소스로 저장 |
토큰이나 NFT 설계에서 실수가 자주 나오는 지점은 copy입니다. 희소성이 필요한 자산 타입에 copy를 열어두면 설계 자체가 무너집니다.
전역 저장소, signer, acquires 권한 모델
Aptos 계정은 전역 저장소를 갖고 key 리소스를 소유합니다. 핵심은 소유권과 조작권의 분리입니다.
- 리소스의 소유자는 계정입니다.
- 리소스를 읽고 분해하고 수정할 권한은 그 타입을 정의한 모듈이 통제합니다.
- 따라서 소유권(계정)과 조작권(모듈 권한)이 분리됩니다.
이 분리가 Move 보안 모델의 핵심입니다. 여기에 signer가 권한 토큰 역할을 더합니다. entry fun의 첫 파라미터 &signer는 트랜잭션 서명자 권한을 나타냅니다.
signer로 계정 주소를 얻을 수 있습니다.- 반대로 주소만으로는
signer를 만들 수 없습니다. - 그래서 임의 주소를 넣어 남의 자산을 조작하는 패턴이 성립하기 어렵습니다.
문법 차원에서는 두 지점을 정확히 쓰는 것이 중요합니다. 전역 리소스를 읽거나 수정하는 함수는 acquires 선언으로 의도를 명확히 하고, 신규 리소스를 계정에 배치할 때는 move_to를 사용합니다. 이 둘만 일관되게 관리해도 코드 리뷰에서 권한 경계를 빠르게 확인할 수 있습니다.
리소스 계정 패턴
운영 서비스에서 자동화 실행이 필요하면 리소스 계정과 SignerCapability로 모듈에 실행 권한을 위임하는 패턴을 자주 씁니다.
- 장점: 개인키 노출 없이 모듈에 권한을 위임할 수 있습니다.
- 주의점: capability의 저장 위치와 회수 정책을 명확히 해야 합니다.
Entry function 실전: 전송, 계정 생성, 배포
Aptos에서는 체인의 기본 동작도 프레임워크 모듈의 함수 호출로 표현됩니다. 실무에서 가장 자주 만나는 인터랙션은 세 가지입니다.
코인 전송
대표 예시는 0x1::coin::transfer입니다.
- 타입 인자:
0x1::aptos_coin::AptosCoin - 인자: 수신자 주소, 수량
- 송신자: payload에 넣지 않고 서명 계정에서 결정
Coin<T>가 제네릭이므로 타입 인자를 정확히 전달해야 한다는 점이 핵심입니다.
계정 생성
0x1::aptos_account::create_account를 호출합니다. 실무에서는 주소만 보는 것이 아니라 인증키 파생 규칙까지 맞춰야 계정 관련 실패를 줄일 수 있습니다.
모듈 배포
모듈 바이트코드에 선언된 주소와 실제 송신자 주소가 일치해야 배포가 승인됩니다.
module 0x...::MyModule에 선언된 주소- 트랜잭션 송신자 주소
이 둘이 다르면 배포는 실패합니다. 그 밖에 자주 막히는 지점은 다음과 같습니다.
Move.toml의 모듈 주소 alias 설정 불일치- 타입 인자 누락 또는 오입력
- 테스트 계정과 배포 계정 혼용
업그레이드 정책: compatible과 immutable
Aptos는 같은 주소에서 Move 패키지를 업그레이드할 수 있습니다. 핵심은 정책입니다.
compatible: 하위호환 업그레이드만 허용immutable: 업그레이드 불가
강도는 compatible < immutable이며, 온체인 정책은 더 강한 쪽으로만 바꿀 수 있습니다. compatible에서 지켜야 할 규칙은 다음과 같습니다.
- 기존
struct의 필드와 ability 변경 불가 - 기존
public/entry함수의 시그니처 변경 불가 - 신규 구조체와 신규 함수 추가는 가능
즉, 기존 상태의 해석과 공개 API를 깨지 않아야 합니다.
호환이어도 안전은 아니다
형식상 호환 업그레이드라도 다음 문제는 발생할 수 있습니다.
- 내부 로직 변경으로 의도치 않은 abort 증가
- 가스 비용 급증
- 외부 의존 모듈의 행동 변화
그래서 의존 패키지의 거버넌스 신뢰 모델을 함께 봐야 합니다. 핵심 자산 모듈은 가능하면 immutable을 우선 검토하고, compatible 의존이 불가피하다면 릴리스 전 회귀 테스트와 가스 프로파일링을 필수로 둡니다.
Base gas: instruction, storage, payload
Aptos 트랜잭션 비용은 크게 세 축으로 결정됩니다.
- Instruction gas
- Storage gas
- Payload gas
실무에서 체감이 가장 큰 축은 대부분 storage gas입니다.
Instruction gas
Move 바이트코드 연산별 단가가 정의되어 있고, 함수 호출·분기·참조·벡터 연산이 누적됩니다. 핫패스에서 불필요한 반복 연산을 제거하고, 과도한 동적 분기를 줄이고, 큰 벡터 조작을 최소화하는 최적화는 의미가 있지만, 일반적인 앱에서는 storage 영향보다 작습니다.
Storage gas
스토리지 단가는 per-item과 per-byte로 나뉘며, 특히 생성(create)이 비쌉니다. 최적화 우선순위는 다음과 같습니다.
- 새 item 생성 횟수를 최소화합니다.
- 가능하면 기존 item을 overwrite로 재사용합니다.
- 큰 리소스 구조를 잘게 분할해 쓰기 폭을 줄입니다.
- write를 read와 계산으로 전환할 수 있는지 검토합니다.
"리소스 하나를 크게 들고 자주 수정"하는 모델은 가스가 악화되기 쉽습니다.
Payload gas
트랜잭션 바이트 크기에 비례합니다. 대형 payload는 압축이나 분할을 고려하고, 불필요한 인자와 중복 데이터를 제거합니다. 다만 일반적으로 storage 최적화가 먼저입니다.
통합 체크리스트
설계, 배포, 업그레이드, 가스 운영 단계에서 확인할 항목을 하나로 모았습니다.
설계
- 자산 타입의 ability(
copy,drop,store,key)를 표로 먼저 정의합니다. - 각
entry fun이 요구하는 권한(&signer, capability)을 명시합니다. - 전역 리소스 접근 함수에
acquires를 일관되게 선언합니다. - 리소스 생성·폐기 경로를 모듈 내부로만 강제합니다.
배포
- 배포 전
Move.toml주소 매핑을 고정합니다. - entry function payload를 템플릿화해 재사용합니다.
- 모듈 배포·호출 계정을 환경별(dev/stage/prod)로 분리합니다.
업그레이드
- 핵심 자산 모듈은 가능하면
immutable을 우선 검토합니다. compatible의존 시 릴리스 전 회귀 테스트와 가스 프로파일을 필수로 둡니다.- 업그레이드 영향 범위를 온체인 이벤트 기준으로 모니터링합니다.
- 실패 시 롤포워드 또는 대체 모듈 계획을 사전에 준비합니다.
가스
- 함수별 가스 프로파일을 CI에서 추적합니다.
- 스토리지 item 생성량을 릴리스마다 비교합니다.
- 고비용 write 경로를 별도 대시보드로 모니터링합니다.
- 가스 회귀가 발생하면 데이터 모델부터 재검토합니다.
정리
Move on Aptos의 핵심은 소유권, 권한, 타입을 언어가 강제한다는 점입니다. 데이터는 실제 소유 계정에 두고, 권한은 signer와 capability로 최소화하며, ability로 자산 타입의 동작을 제한하는 축을 먼저 설계하면 기능 추가보다 보안과 운영 안정성이 먼저 좋아집니다. 배포 단계에서는 모듈 주소 일치 규칙과 업그레이드 정책을 명확히 하고, 가스는 storage 최적화를 최우선에 두는 것이 실무에서 효율이 가장 높습니다.