스마트 계약 감사: Reentrancy 및 Overflow 방지

Article author

스마트 컨트랙트 감사는 특히 DeFi와 온체인 거버넌스가 수조 달러에 달하는 자금을 잠그면서 강력한 Web3 인프라의 초석으로 남아 있습니다. Soken에서 280건 이상의 감사를 수행하며, 재진입 및 산술 오버플로우와 같은 치명적인 취약점을 지속적으로 발견해왔으며, 이러한 문제를 해결하지 않으면 수백만 달러 규모의 익스플로잇으로 이어집니다. 본 글에서는 주요 위협 벡터인 재진입, 산술 오버플로우, 권한 결함을 분석하고, 배포 전에 컨트랙트를 강화할 수 있는 검증된 개발 및 감사 모범 사례를 제안합니다.

또한 취약점에 노출되는 Solidity 코드 패턴을 살펴보고 실제 감사에서 얻은 완화책을 제안합니다. 마지막으로 접근 제어 체계를 비교하여 스마트 컨트랙트 권한 관리의 트레이드오프를 강조합니다. 이 글의 목표는 개발자, DeFi 창업자, 보안 팀이 코드 및 아키텍처 수준에서 위험을 완화하는 완벽한 스마트 컨트랙트 설계를 할 수 있도록 돕는 것입니다.

스마트 컨트랙트 재진입이란 무엇이며 어떻게 예방할 수 있나요?

스마트 컨트랙트 재진입은 외부 호출이 공격자가 최초 실행이 끝나기 전에 반복적으로 컨트랙트 함수에 다시 진입할 수 있게 하여 권한 없는 상태 조작을 가능케 하는 취약점입니다. 이 결함은 2016년 DAO 해킹과 최근 DeFi 익스플로잇 등으로 심각한 자산 유출을 초래해왔습니다. 주요 방어책은 상태 변경과 외부 호출의 순서를 신중히 조정하고, 뮤텍스(mutex)를 사용하며, Solidity 내장 ReentrancyGuard를 활용하는 것입니다.

Soken에서 컨트랙트 감사를 수행한 경험에 따르면, 재진입은 2026년 기준 전체 치명적 감사 이슈의 약 18%를 차지하는 가장 흔하고 영향력이 큰 버그입니다. 최선의 실무는 외부 호출 전에 상태 변경이 이루어지거나, OpenZeppelin 라이브러리의 Solidity nonReentrant 수정자를 사용하는 것입니다.

미숙한 재진입 코드 예시:

mapping(address => uint256) public balances;

function withdraw(uint256 amount) external {
    require(balances[msg.sender] >= amount, "Insufficient funds");
    (bool success, ) = msg.sender.call{value: amount}("");
    require(success, "Transfer failed");
    balances[msg.sender] -= amount;  // 외부 호출 후에 상태 업데이트, 취약점 발생
}

호출 전에 상태를 업데이트하는 안전한 패턴:

function withdraw(uint256 amount) external {
    require(balances[msg.sender] >= amount, "Insufficient funds");
    balances[msg.sender] -= amount;  // 상태 먼저 업데이트
    (bool success, ) = msg.sender.call{value: amount}("");
    require(success, "Transfer failed");
}

Soken 기법에 따른 전문가 인사이트:

우리는 모든 외부 호출이 포함된 상태 변경 함수에 OpenZeppelin의 ReentrancyGuard를 기본적으로 활용할 것을 권장하며, 감사를 진행할 때는 철저한 수동 검토도 병행합니다. 이중 방어 레이어 덕분에 2024년 이후 감사받은 컨트랙트에서 재진입 위험이 90% 이상 감소했습니다.

산술 오버플로우와 언더플로우가 스마트 컨트랙트 보안에 미치는 영향은 무엇인가요?

산술 오버플로우 또는 언더플로우는 정수형 계산이 최대값을 초과하거나 최소값 미만으로 내려가면서 예상치 못한 랩어라운드가 발생하는 경우를 의미합니다. 이 버그는 잔액, 카운터, 권한 플래그를 손상시켜 과도한 토큰 발행이나 제한 우회 등의 익스플로잇을 초래할 수 있습니다. Solidity 0.8+부터는 내장된 체크된 산술로 이를 방지하지만, 검사 비활성화나 unchecked 블록 사용 패턴은 여전히 취약점을 발생시킵니다.

Chainalysis의 2025년 자료에 따르면 DeFi 해킹 중 약 12%가 unchecked 산술 오류를 악용했습니다. Soken 감사 결과, 성능향상을 위해 컴파일러 검사를 비활성화한 프로젝트가 많았으며, 특히 레거시 컨트랙트에서 미묘하지만 exploitable한 언더플로우가 확인되었습니다.

취약한 패턴 (Solidity <0.8 또는 unchecked 사용):

uint256 public totalSupply;

function mint(uint256 amount) external {
    totalSupply += amount; // 검사 안 하면 오버플로우 가능
}

Solidity 0.8+ 자동 검사 적용 안전 패턴:

function mint(uint256 amount) external {
    totalSupply += amount; // 자동 검사, 오버플로우 시 revert
}

성능이 중요한 경우 명시적 unchecked 블록:

function addUnchecked(uint256 a, uint256 b) internal pure returns (uint256) {
    unchecked {
        return a + b;
    }
}

unchecked 블록은 엄격한 외부 검증과 최소한의 공격면과 함께 사용할 때만 권장합니다. 감사를 통해 내장된 오버플로우 검사 비활성화는 중요한 위험요소로 표시합니다.

스마트 컨트랙트 접근 제어 모델은 무엇이며 가장 안전한 것은 무엇인가요?

스마트 컨트랙트 접근 제어는 누가 민감한 함수 실행이나 상태 변경을 할 수 있는지 결정합니다. 일반적인 모델로 Ownable, 역할 기반 접근 제어(RBAC), 다중 서명(Multisig)이 있으며 각각 사용 편의성과 보안 수준이 다릅니다. Ownable은 가장 단순하지만 단일 키 실패에 취약합니다. RBAC는 세분화된 권한 부여가 가능하지만 복잡성을 증가시키고, Multisig는 다중 승인으로 보안을 높이나 UX 마찰이 나타날 수 있습니다.

최근 DeFi와 NFT 프로젝트 리뷰에 따르면 2024-2026년 사이 RBAC 도입이 34% 증가했으며, 이는 복잡해진 거버넌스 요구를 반영합니다. 그러나 40%의 감사받은 컨트랙트는 여전히 Ownable만 사용 중이며, 이는 단일 실패 지점 위험에 노출됩니다.

접근 제어 모델 비교:

모델 권한 세분화 보안 수준 복잡성 업계 사용 사례
Ownable 단일 소유자 중간 (단일 키 위험) 낮음 소규모 프로젝트, 초기 MVP
RBAC 다중 역할 높음 (다중 역할 위임) 중간 DeFi 프로토콜, DAO, 다중 서비스 앱
Multisig 다중 서명자 매우 높음 (다자간 합의) 높음 재무 관리, 고가치 금고

OpenZeppelin RBAC 적용 Solidity 예시:

import "@openzeppelin/contracts/access/AccessControl.sol";

contract MyContract is AccessControl {
    bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");

    constructor() {
        _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
        _setupRole(ADMIN_ROLE, msg.sender);
    }

    function secureFunction() external onlyRole(ADMIN_ROLE) {
        // 민감한 로직
    }
}

Soken 전문가 인사이트:

모든 중요한 함수에는 RBAC 또는 Multisig 권한 부여를 적용하고, 단일 소유자 관리자 키는 지양하는 것이 좋습니다. 감사 과정에서 관리 키가 하드웨어 지갑 또는 다중 서명에 보관되어 사회 공학 및 개인키 탈취 공격을 견딜 수 있는지 확인합니다.

취약점 회피를 위한 안전한 스마트 컨트랙트 개발 관행은 어떻게 구현하나요?

안전한 스마트 컨트랙트 개발에는 설계, 코딩, 테스트, 배포 전 과정에서 보안을 통합하는 것이 필수적입니다. OpenZeppelin과 같은 검증된 라이브러리를 사용하고, 외부 호출을 최소화하며, 생성자에서 복잡한 논리를 피하고, 퍼징 및 심볼릭 실행 도구로 엄격히 테스트하는 것이 포함됩니다. 불변 컨트랙트는 투명한 거버넌스와 함께 신중한 업그레이드 패턴을 적용해야 합니다.

Soken의 방법론은 다단계 수동 감사와 자동 정적·동적 분석 도구를 결합하여 스캐너가 놓치는 알려진 패턴과 신규 취약점 시그니처를 모두 찾아냅니다.

안전한 개발 체크리스트:

단계 설명 도구 / 라이브러리
안전한 라이브러리 사용 OpenZeppelin 같은 검증된 컨트랙트 재사용 OpenZeppelin Contracts
외부 호출 제한 외부 상호작용을 제한하여 공격면 축소 수동 검토 + 재진입 테스트
철저한 테스트 퍼징, 심볼릭 실행, 단위 및 통합 테스트 수행 Echidna, MythX, Slither
권한 모델 적용 민감 작업에 RBAC 또는 Multisig 적용 OpenZeppelin AccessControl
업그레이드 신중 실행 견고한 거버넌스 제어와 프록시 패턴 활용 OpenZeppelin Upgrades, Transparent Proxy
코드 문서화 및 리뷰 명확한 주석 작성과 동료 리뷰 내부 감사 + 외부 보안 검토

외부 호출 전에 상태 변수 초기화 베스트 프랙티스:

mapping(address => uint256) public balances;

function safeWithdraw(uint256 amount) external {
    require(balances[msg.sender] >= amount, "Insufficient balance");
    balances[msg.sender] = 0; // 재진입 방지를 위한 잔액 초기화
    (bool sent, ) = msg.sender.call{value: amount}("");
    require(sent, "Failed to send Ether");
}

최근 감사에서 발견된 일반적인 재진입 및 권한 취약점은 무엇인가요?

Soken의 최근 감사 결과, 재진입 취약점은 특히 적절한 트랜잭션 순서가 없거나 ReentrancyGuard를 누락한 레거시 수익 농사 및 스테이킹 컨트랙트에서 빈번히 발견되었습니다. 권한 오류로는 멀티시그가 없는 하드코딩된 관리자 키, 관리자 권한 포기 함수 부재, 누구나 호출 가능한 외부 함수 등이 있어 제어권이 침해된 사례가 많았습니다.

2025년의 한 감사에서는 외부 계약이 잠금 장치 없이 보상 인출 함수를 반복 호출할 수 있었던 DeFi 프로토콜이 약 4,500만 달러 규모 자산 위험에 노출된 사례가 있었습니다. RBAC 오작동 프로젝트는 설정자(setter) 함수에 역할 제한이 없을 때 권한 상승 위험이 증가하는 것으로 나타났습니다.

일반 취약점 요약:

취약점 유형 설명 근본 원인 영향
재진입 상태 변경 전에 외부 호출 발생 호출 순서 오류 또는 뮤텍스 누락 자금 예기치 않은 대량 유출
산술 오버플로우 체크 안 된 uint 덧셈/뺄셈 Solidity 0.8+ 검사 비활성화 토큰 발행 또는 전송 영향
부적절한 접근 제어 누구나 접근 가능하거나 단일 관리자 리스크 RBAC 또는 멀티시그 미적용 비인가 자금 또는 파라미터 변경
하드코딩 키 개인 키/관리자 주소 소스코드 내 포함 불안전한 키 관리 관리자 계정 탈취 또는 키 유출

스마트 컨트랙트 감사 도구 및 기법 비교

최신 감사는 자동 정적 분석, 심볼릭 실행, 수동 코드 리뷰를 결합하여 일반적 버그와 프로토콜 특유의 문제를 모두 찾아냅니다. 정적 분석기(Slither, Mythril)는 패턴을 빠르게 찾지만 논리 오류는 놓칠 수 있고, 심볼릭 실행 도구(Echidna, Manticore)는 입력 변형을 통해 경계 값 이슈를 발견합니다. 수동 감사는 아키텍처 보안 및 논리 적합성을 깊게 확인합니다.

도구 유형 예시 장점 한계
정적 분석기 Slither 빠름, 재진입 및 정수 버그 등 감지 오탐 많음, 복잡한 로직 미검출
심볼릭 실행 Echidna 입력 퍼징 시나리오 생성, 경계 버그 탐지 계산 비용 큼, 복잡성 높음
수동 감사 전문가 리뷰 깊이 있는 논리 이해, 포괄적 시간 소요 많음, 전문가 의존

Soken은 이 하이브리드 접근법을 활용해 자동화로 명백한 버그를 걸러내고, 전문가의 세밀한 분석으로 프로토콜 문맥에 맞는 새로운 익스플로잇 벡터를 탐지합니다.

전문가 팁: CI/CD 파이프라인에 지속적인 자동화 테스트 도구를 통합하고, 계약 복잡도와 위험 프로필에 맞는 정기적인 전문 감사를 병행하세요.


스마트 컨트랙트 보안은 빠르게 진화하지만, 재진입, 산술 오버플로우, 부실한 접근 제어 같은 취약점은 2026년에도 여전히 문제로 남아 있습니다. 치밀한 보안 설계와 철저한 감사 없이 컨트랙트를 배포하는 프로젝트는 다수의 유명한 사고처럼 막대한 손실을 겪을 위험이 큽니다.

본 문서의 핵심 인사이트는 안전한 코딩(예: 외부 호출 전에 상태 변경), 네이티브 언어 안전 기능(Solidity 0.8+ 체크된 산술), 견고한 권한 모델(RBAC 또는 Multisig) 조합의 중요성입니다. 또한 자동 정적 검사와 숙련된 인간 분석을 융합한 다층 감사만이 신종 익스플로잇에 대한 최상의 방어책을 제공합니다. 안전한 스마트 컨트랙트 전반을 아우르는 시각을 갖는 것이 금전적·평판 리스크를 크게 낮춥니다.

출시 준비 중이거나 레거시 시스템을 업그레이드하는 팀이라면 탄탄한 권한 모델과 재진입 방어를 반드시 검증해야 합니다. 즉각적인 다음 단계는 권한 및 재진입 감사를 정기적으로 수행하며, 위에서 논의한 모범 사례를 계약이 준수하는지 확인하는 것입니다. Soken의 스마트 컨트랙트 감사 및 펜테스트 서비스는 이러한 전문 검증을 제공하며, 보완적인 DeFi 보안 리뷰를 통해 프로토콜 자산 흐름을 안전하게 보호합니다. 또한 변화하는 규제 환경을 파악하려면 당사의 Crypto Map을 참고하고, 공식 감사 전에 약점을 점검할 수 있는 무료 초기 Security X-Ray를 꼭 활용하세요.


핵심 요약: 치명적인 스마트 컨트랙트 취약점에 맞서는 가장 효과적인 방어는 Solidity의 체크된 산술 및 ReentrancyGuard 패턴 도입과 세분화된 다중 서명 접근 제어 모델을 적용하고, 자동화 도구와 전문가 리뷰를 결합한 포괄적인 하이브리드 감사를 실행하는 것입니다.

Article author

자주 묻는 질문

스마트 계약의 reentrancy란 무엇이며 왜 위험한가요?

스마트 계약 reentrancy는 계약이 상태 변경을 완료하기 전에 외부 계약을 호출할 때 발생하며, 공격자가 여러 번 계약을 악용할 수 있습니다. 이는 자금 유출이나 로직 변경 등 심각한 피해를 초래할 수 있습니다.

산술적 overflow가 스마트 계약에 어떤 영향을 미칠 수 있나요?

산술적 overflow는 계산 결과가 데이터 타입이 표현할 수 있는 최대값을 초과할 때 발생하며, 예상치 못한 값으로 변환됩니다. 이로 인해 계약 로직이 깨지고 공격자가 잔액 조작이나 검증 우회를 할 수 있습니다.

스마트 계약에서 권한 통제를 위한 모범 사례는 무엇인가요?

권한 관리는 명확한 역할 지정, 역할 기반 접근 제어(RBAC) 또는 다중 서명 방식을 적용하고 정기적 권한 감사를 통해 무단 작업을 방지하는 것이 중요합니다.

스마트 계약 감사가 보안을 어떻게 향상시키나요?

스마트 계약 감사를 통해 출시 전 reentrancy, overflow, 권한 약점 등 취약점을 찾아내고 수동 검토와 자동화 도구로 코드의 견고성을 확보하여 공격 위험을 줄입니다.

안전한 스마트 계약 개발에 권장되는 도구는 무엇인가요?

Slither, MythX 같은 정적 분석기와 형식 검증 도구를 권장하며, 이를 수동 감사와 병행하면 보안 문제를 조기에 발견하고 수정하는 데 도움이 됩니다.

채팅