본문으로 건너뛰기

Move VM 메모리 안전성 vs EVM 재진입성 : Aptos와 Sui의 리소스 모델이 스마트 컨트랙트 취약점의 전체 클래스를 제거하는 이유

· 약 9 분
Dora Noda
Software Engineer

2016년 DAO 해킹 사건은 단 한 번의 오후 만에 이더리움에서 6,000만 달러를 소진시켰습니다. 9년이 지난 2024년에도 재진입 공격(reentrancy attacks)은 22건의 개별 사건을 통해 DeFi 프로토콜에 3,570만 달러의 피해를 입혔습니다. 상태가 업데이트되기 전에 공격자가 계약을 다시 호출하는 동일한 유형의 취약점은 수년간의 개발자 교육, 감사 도구 및 검증된 패턴에도 불구하고 여전히 EVM 생태계를 괴롭히고 있습니다.

Move 언어를 기반으로 구축된 Aptos와 Sui는 근본적으로 다른 접근 방식을 취합니다. 이들은 설계 단계에서부터 전체 카테고리의 취약점을 불가능하게 만듭니다.

근본 원인: EVM 재진입이 발생하는 방식

Move가 왜 다른지 이해하려면, 우선 왜 이더리움에서 재진입이 가능한지 정확히 이해하는 것이 도움이 됩니다.

Solidity 계약은 실행 도중에 외부 계약을 호출할 수 있습니다. 계약 A가 계약 B를 호출하면 실행 권한이 완전히 B로 넘어갑니다. 그러면 B는 A가 내부 상태 업데이트를 마치기 전에 A를 다시 호출하여 "재진입(re-entering)"할 수 있습니다. 만약 A의 출금 로직이 다음과 같다면:

// 취약한 패턴
function withdraw(uint amount) external {
require(balances[msg.sender] >= amount);
(bool success, ) = msg.sender.call{value: amount}(""); // 외부 호출이 먼저 발생
balances[msg.sender] -= amount; // 상태 업데이트가 나중에 발생
}

공격자의 계약은 콜백에서 ETH를 받은 즉시 다시 withdraw를 호출하여 balances[msg.sender]가 차감되기 전에 자금을 빼낼 수 있습니다. 이것이 바로 The DAO에서 일어난 일입니다. 공격자의 계약은 루프 내에서 출금 함수를 360만 번 재귀적으로 다시 호출했습니다.

해결책은 간단해 보입니다. 외부 호출을 하기 전에 상태를 업데이트하는 것입니다 ("Checks-Effects-Interactions" 패턴). 하지만 개발자들은 이를 잊어버리고, 감사자(Auditors)들은 이를 놓칩니다. 이 패턴은 언어 자체가 아닌 인간의 근면함에 의해서만 강제되는 관습일 뿐입니다.

Move의 접근 방식: 리소스는 복제되거나 파괴될 수 없습니다

Move는 타입 시스템 수준에서 이러한 종류의 오류를 방지하도록 처음부터 설계되었습니다. 핵심 개념은 선형 타입 시스템(linear type system)리소스 타입(resource types) 입니다.

Move에서 리소스는 다음과 같은 특성을 가진 특별한 종류의 값입니다:

  • 복사될 수 없음 — 저장 위치 간에 이동만 가능합니다.
  • 폐기될 수 없음 — 명시적으로 소비되거나 어딘가에 저장되어야 합니다.
  • 특정 시점에 단 한 명의 소유자만 가짐 — 매핑이 아닌 VM에 의해 추적됩니다.

이는 추상적으로 들릴 수 있지만, 그 영향은 구체적입니다. 토큰 전송이 어떻게 작동하는지 생각해 보세요:

  • Solidity에서 토큰 잔액은 매핑 내의 uint256입니다. 업데이트 순서가 틀리면 이론적으로 숫자를 조작할 수 있습니다.
  • Move에서 토큰은 계정의 저장소에 존재하는 실제 리소스 객체입니다. 리소스를 한 위치에서 다른 위치로 물리적으로 이동시킵니다. 리소스가 두 곳에 존재하거나 어디에도 존재하지 않는 중간 상태는 없습니다.

Move VM은 소스 수준이 아니라 바이트코드 수준에서 이러한 불변성(invariants)을 강제합니다. 개발자가 버그가 있는 코드를 작성하더라도, VM은 리소스를 복제하거나 자동으로 폐기하려는 모든 트랜잭션을 거부합니다.

Move에서 재진입이 구조적으로 불가능한 이유

재진입에는 두 가지 조건이 필요합니다. 실행 중에 외부 코드를 호출할 수 있는 능력과, 해당 콜백 중에 조작할 수 있는 가변 공유 상태(mutable shared state)입니다. Move는 이 두 가지를 모두 차단합니다.

Move는 Solidity와 같은 방식으로 동적 디스패치(dynamic dispatch)를 허용하지 않습니다. 알 수 없는 코드로 제어권을 넘기는 임의의 외부 호출이 없습니다. 함수는 정적으로 호출되어야 하며, 호출 대상은 컴파일 시점에 알려집니다. 즉, 공격자는 콜백 중에 모듈에 재진입하는 계약을 배포할 수 없습니다. 왜냐하면 모듈이 실행 권한을 알려지지 않은 외부 계약에 넘겨주지 않기 때문입니다.

또한, Sui와 Aptos의 Move 객체 모델은 객체가 함수 내부와 외부로 명시적으로 전달되는 소유권 시스템을 사용합니다. 함수로 "이동(moved into)"된 객체는 함수가 이를 반환할 때까지 다른 어디에서도 접근할 수 없습니다. 단일 트랜잭션에서 동일한 리소스에 대한 동시 액세스는 단순히 불가능합니다.

2025년에 발표된 연구에 따르면 "Move에서는 동적 콜백이 불가능하므로 재진입이 불가능하다. 이는 재진입이 여전히 주요 위협으로 남아 있는 Solidity와의 근본적인 차이점이다"라고 확인되었습니다.

뮤텍스 락(Mutex Locks) 없는 이중 지불 방지

EVM 기반 시스템에서 이중 지불 방지는 세심한 프로그래밍에 의존합니다. 개발자는 상태 업데이트를 부지런히 추적하여 하나의 트랜잭션에서 토큰이 두 번 사용되지 않도록 수동으로 보장해야 합니다.

Move의 선형 타입 시스템은 이중 지불을 구조적으로 불가능하게 만듭니다. 리소스는 복사할 수 없기 때문에 코인을 사용하는 것은 문자 그대로 계정의 저장소에서 코인을 제거하는 것입니다. 첫 번째 사용 후에는 리소스가 더 이상 제어 하에 존재하지 않으므로 트랜잭션에서 동일한 리소스를 두 번 사용할 방법이 없습니다. VM이 이를 강제하며, 이는 관습이 아닌 제약 사항입니다.

이는 Sui의 Capability 객체로도 확장됩니다. Capability 리소스는 한 번 소비되면 다시 사용할 수 없습니다. 이를 Capability가 일반적으로 불리언(boolean) 또는 주소 매핑으로 인코딩된 역할이며 여러 번 확인할 수 있는 EVM 액세스 제어 패턴과 비교해 보십시오.

Sui에서의 한 실제 사례는 미묘한 차이를 강조합니다. 한 DEX에서 출금 로직이 Capability 자체가 아닌 Capability에 대한 가변 참조(mutable reference) 에 단일 사용 제약 조건을 강제하지 못하는 결함이 발견되었습니다. 이는 Move의 리소스 모델이 전체 클래스의 버그를 제거하지만, 개발자가 소유된 리소스가 아닌 참조로 작업할 때 여전히 로직 오류를 발생시킬 수 있음을 보여줍니다. 위협 범위는 극적으로 좁아졌지만 제로는 아닙니다.

정수 오버플로: Move가 기본적으로 해결하는 또 다른 문제

초기 Solidity (0.8.0 이전)에서는 정수 산술 연산 시 오버플로가 발생하면 아무런 경고 없이 값이 순환(wrap around)되었습니다. 이로 인해 공격자가 오버플로 조건을 유발하여 토큰 잔액을 조작할 수 있었으며, 이는 여러 대규모 DeFi 해킹 사건의 원인이 되었습니다.

Solidity 0.8.0 버전에서 자동 오버플로 검사가 도입되었지만, 이는 이미 수년간 피해가 발생한 이후였습니다. Move는 언어 설계 초기부터 이러한 보호 기능을 포함했습니다. 정수 오버플로를 유발하는 모든 트랜잭션은 자동으로 중단(abort)됩니다. 예외 처리는 없으며, 기본적으로 unchecked와 같은 기능도 존재하지 않습니다. 또한 예전 방식으로 작동하는 레거시 컨트랙트 걱정도 필요 없습니다.

형식 검증(Formal Verification): Move Prover vs. EVM 감사

Move의 보안성은 언어를 넘어 도구(tooling)까지 확장됩니다. Move Prover는 언어와 함께 구축된 형식 검증 도구이며, 나중에 덧붙여진 것이 아닙니다.

Move Prover를 사용하면 개발자는 소스 파일 내에 사양 언어(specification language)를 사용하여 명세(spec)를 직접 작성합니다. 이러한 명세는 구현된 코드와 비교하여 수학적으로 검증됩니다. 예를 들어 명세에 "이 함수가 실행된 후에도 전체 코인 공급량은 변하지 않아야 한다"라고 정의할 수 있습니다. 그러면 Prover는 이것이 항상 참임을 확인하거나, 실패하는 구체적인 반례를 제공합니다.

이는 대부분의 Solidity 감사가 이루어지는 방식과는 근본적으로 다릅니다.

항목Move ProverSolidity 감사 도구
검증 유형수학적 증명패턴 매칭 / 퍼징(fuzzing)
커버리지완전함 (명세 범위 내)최선 노력(Best-effort)
통합 방식언어 툴체인의 일부서드파티 도구 (Slither, Certora)
수행 시점개발 단계배포 전 감사
비용무료, 저장소 내 포함고가의 수동 감사

Solidity용 Slither와 같은 도구는 정적 분석을 수행하여 알려진 취약점 패턴을 탐지합니다. Solidity용 Certora Prover는 형식 검증을 지원하며 크로스 트랜잭션 불변성(cross-transaction invariants)을 포함한 광범위한 속성을 표현할 수 있습니다. 하지만 Certora는 별도의 언어로 명세를 작성하고 별도의 파이프라인을 실행해야 하므로, 일상적인 개발 도구라기보다는 전문적인 감사 단계에 가깝습니다.

Move Prover는 긴밀하게 통합되어 있어 Aptos 및 Sui 개발자들이 값비싼 감사를 기다릴 필요 없이 개발 중에 로컬에서 직접 형식 검증을 수행할 수 있습니다. Aptos 프레임워크 자체도 표준 라이브러리에 대한 Move Prover 명세를 함께 제공하므로, 애플리케이션 개발자는 이러한 보안 기반을 그대로 상속받게 됩니다.

잔존 위험: Move가 해결하지 못하는 것

Move의 설계가 모든 보안을 보장하는 만능 해결책은 아닙니다. 실제 Move 컨트랙트 감사를 살펴보면 개발자가 여전히 다음과 같은 실수를 저지를 수 있음을 알 수 있습니다.

  • 비즈니스 규칙의 로직 오류 (가장 흔한 유형)
  • 소유된 리소스(owned resources) 대신 가변 참조(mutable references)를 사용할 때 발생하는 액세스 제어 버그
  • DeFi 프로토콜의 경제적 설계 결함 (가격 오라클 조작, 플래시 론 공격)
  • 여러 모듈이 예상치 못한 방식으로 상호작용할 때 발생하는 교차 모듈 상호작용 버그

2024년의 한 연구에서 652개의 Move 컨트랙트를 수동으로 감사한 결과 8가지 결함 유형이 확인되었으며, 그중 절반은 이전에 보고된 적이 없는 것이었습니다. Solidity보다 공격 표면(attack surface)은 작지만 여전히 존재합니다.

Aptos 및 Sui에서 최상의 보안 상태를 유지하려면 언어 자체의 내장된 보호 기능에만 의존하지 않고 Move Prover 명세 작성, 서드파티 감사, 그리고 경제적 보안 분석을 병행해야 합니다.

2025년 DeFi 빌더들에게 이것이 중요한 이유

수치가 모든 것을 말해줍니다. 2024년에 스마트 컨트랙트 취약점으로 인해 DeFi 분야에서 14억 달러 이상의 손실이 발생했습니다. 그중 재진입성(Reentrancy) 공격으로 인한 피해액은 3,570만 달러에 달했습니다. 이는 동일한 TVL(총 예치 자산)을 가진 Move 기반 체인에서는 구조적으로 발생할 수 없는 카테고리입니다.

금융 애플리케이션을 구축하는 개발자에게 가상 머신(VM)의 선택은 사실상 기본 위협 모델을 선택하는 것과 같습니다. EVM에서 개발한다는 것은 '검사-효과-상호작용(Checks-Effects-Interactions)' 패턴을 필수 규율로 채택함을 의미합니다. 반면 Move에서 개발한다는 것은 재진입성 공격이 위협 모델에서 완전히 사라짐을 의미하며, 팀은 로직 오류와 경제적 설계라는 보안의 본질에 더 집중할 수 있습니다.

이는 결코 작은 차이가 아닙니다. 위협 표면이 작을수록 형식 검증 도구는 더 효과적으로 작동합니다. 감사자들은 이미 잘 알려진 취약점 클래스에 시간을 쏟는 대신 더 깊이 있는 분석을 수행할 수 있습니다. 언어가 중요한 불변성(invariants)을 자동으로 강제할 때, 올바른 코드를 작성하려는 개발자의 인지 부하가 줄어듭니다.

인프라 계층

보안 보장은 개발자가 실제로 해당 체인에서 대규모로 빌드할 수 있을 때에만 의미가 있습니다. 네트워크에 접속하기 위해 직접 Aptos 또는 Sui 노드를 운영하는 것은 하드웨어 프로비저닝, 소프트웨어 업그레이드, 모니터링, 사고 대응 등 상당한 운영 부담을 수반합니다.

BlockEden.xyz는 Aptos 및 Sui에 대해 엔터프라이즈급 API 액세스를 제공하여, 개발자가 노드 인프라 관리 없이 Move의 보안 보장을 활용해 애플리케이션을 구축할 수 있도록 지원합니다. 서비스 둘러보기를 통해 더 안전한 Web3 애플리케이션을 구축해 보세요.

메모리 안전 언어, 구조적 재진입 방지, 통합된 형식 검증의 결합은 Aptos와 Sui를 고도의 보안이 요구되는 DeFi 애플리케이션의 강력한 플랫폼으로 만듭니다. Move는 단순히 보안 스마트 컨트랙트를 작성하기 쉽게 만드는 것을 넘어, 특정 유형의 치명적인 오류를 수학적으로 불가능하게 만듭니다.


참고 문헌: