블록체인 학습
0 XP

require 문

require 는 함수가 계속 실행되기 위한 조건을 검사하는 가장 기본적인 도구입니다. 조건이 거짓이면 트랜잭션 전체를 되돌리고(revert), 그때까지 변경된 상태를 모두 취소합니다. 사용자 입력 검증과 권한 확인에 가장 널리 쓰이는 안전장치입니다.

문법과 동작

require(조건, "에러 메시지");

조건이 true 면 다음 줄로 진행하고, false 면 즉시 중단하며 두 번째 인자의 메시지를 반환합니다. 두 번째 인자는 선택이지만, 실패 원인을 디버깅하려면 항상 메시지를 넣으세요.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
 
contract Bank {
    mapping(address => uint256) public balance;
 
    function deposit() public payable {
        // 0보다 큰 금액만 입금 허용
        require(msg.value > 0, "amount must be positive");
        balance[msg.sender] += msg.value;
    }
 
    function withdraw(uint256 amount) public {
        // 1) 검사 — 잔액이 충분한지
        require(balance[msg.sender] >= amount, "insufficient balance");
        // 2) 상태 변경 — 외부 호출보다 먼저 갱신
        balance[msg.sender] -= amount;
        // 3) 외부 호출 — 송금은 call 로
        (bool ok, ) = payable(msg.sender).call{value: amount}("");
        require(ok, "transfer failed");
    }
}

송금은 transfer 가 아니라 call{value: ...}("") 로 하고 반환값을 require 로 확인합니다. transfer 는 수신자에게 2300 gas 만 전달해, 멀티시그나 스마트 컨트랙트 지갑처럼 수신 처리에 가스를 더 쓰는 주소로는 송금이 실패합니다. 컴파일러도 deprecated 경고를 냅니다. 재진입은 위 예제처럼 검사 → 상태 변경 → 외부 호출 순서(Checks-Effects-Interactions)로 막습니다. 위 예제에 함께 나온 payable(Ether 를 받을 수 있다는 표시)과 msg.value(함께 보내진 금액, wei), 그리고 송금 방식의 자세한 비교는 Chapter 12 에서 다룹니다. 여기서는 require 가 어떤 값을 검사하는지만 보면 됩니다.

가스 환불과 사용 위치

require 가 실패하면 그때까지 쓴 가스는 소모되지만, 아직 쓰지 않은 가스는 호출자에게 환불됩니다. 잘못된 입력 하나 때문에 호출자가 가스를 전부 잃지는 않는다는 뜻입니다. 검사 비용을 아끼려면 require 를 함수 맨 앞에 두어, 실패할 거라면 일찍 중단(early revert)하세요.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
 
contract Sale {
    uint256 public price = 1 ether;
 
    function buy() public payable {
        require(msg.value == price, "send exact price"); // 가장 먼저 검증
        // 검증 통과 후에만 비싼 로직 실행
    }
}

require(msg.sender == owner, "only owner") 처럼 msg.sender 검사와 묶으면 권한 제어도 한 줄로 끝납니다.

require 는 "이 조건이 맞아야만 계속 진행한다"는 가장 자주 쓰이는 안전장치입니다.

Code Editor
에디터를 불러오는 중...
실행 결과

Run 버튼을 눌러 코드를 실행하세요.