Blockchain

[Solidity] 3. 함수(Function) 정의와 실행 흐름

clolee 2025. 4. 17. 22:26

✅ 3. 함수(Function) 정의와 실행 흐름

스마트컨트랙트는 대부분 함수를 통해 외부와 상호작용


📌 1. 함수 기본 구조

function functionName(parameterList) accessModifier functionType returns (returnType) {
    // 함수 내용
}

예시:

function setValue(uint _x) public {
    value = _x;
}

📌 2. 함수 접근 제어자 (Visibility)

키워드 설명 호출 가능 위치
public 외부 + 내부 ✅ Remix 버튼 생성
external 외부 전용 ✅ Remix 버튼 생성 (내부 호출 불가)
internal 내부 + 상속 컨트랙트 ❌ 외부 호출 불가
private 현재 컨트랙트만 ❌ 완전 캡슐화

✅ 실무 팁

  • external가스 비용이 더 적게 드는 경우가 많음 (calldata 사용)
  • internal/privatelibrarymodifier 설계 시 많이 사용됨

📌 3. 함수 속성 (Function Types)

키워드 설명 블록체인 상태
view 상태 읽기만 가능 ❌ 변경 없음
pure 상태 읽기조차 없음 ❌ 완전 독립
payable 이더를 받을 수 있음 ✅ 수신 가능

🔍 예제

function getValue() public view returns (uint) {
    return value;
}

function add(uint a, uint b) public pure returns (uint) {
    return a + b;
}

function deposit() public payable {
    // msg.value로 이더 수신
}

📌 4. 함수 반환값 (returns)

function getBalance() public view returns (uint) {
    return address(this).balance;
}
  • returns 키워드는 반환 타입을 명시
  • 여러 값 반환도 가능: returns (uint, string memory)

📌 5. msg.sender, msg.value, address(this)

키워드 설명
msg.sender 함수를 호출한 외부 주소
msg.value 전송된 이더 양 (wei 단위)
address(this) 현재 컨트랙트의 주소
address(this).balance 현재 컨트랙트에 보관된 이더 양

📌 6. fallback() vs receive()

함수 조건 설명
receive() msg.data 없음 + msg.value 있음 단순 이더 수신용
fallback() msg.data 있음 존재하지 않는 함수 호출 시
receive() external payable {
    // 이더 받기 전용
}

fallback() external payable {
    // 없는 함수 호출 시
}

📌 7. 함수 호출 방식 정리

호출 방식 설명 예시
내부 호출 컨트랙트 내 다른 함수 호출 foo();
외부 호출 주소 통해 호출 otherContract.bar();
delegatecall 호출자의 컨텍스트 유지 addr.delegatecall(...)
low-level call raw 바이트로 함수 호출 addr.call(data)

📌 8. 함수 오버로딩

Solidity는 함수 이름이 같고 인자 수나 타입이 다르면 허용합니다.

function setData(uint _x) public { ... }
function setData(string memory _x) public { ... }

✅ 실전 예제

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract Bank {
    address public owner;
    uint public balance;

    constructor() {
        owner = msg.sender;
    }

    // 이더 받기
    function deposit() public payable {
        balance += msg.value;
    }

    // 잔액 조회 (읽기 전용)
    function getBalance() public view returns (uint) {
        return balance;
    }

    // 단순 계산 (순수 함수)
    function calculate(uint a, uint b) public pure returns (uint) {
        return a + b;
    }

    // 이더 송금
    function withdraw(address payable to, uint amount) public {
        require(msg.sender == owner, "Only owner");
        to.transfer(amount);
        balance -= amount;
    }
}

🧠 실무 팁 정리

항목
view/pure는 외부 호출 시 가스비 없음 단, 내부 호출 시는 가스 발생
payable이 없으면 이더 수신 불가 msg.value가 있어도 revert됨
함수에 external 지정 + calldata 사용 가스 최적화에 유리
msg.sender 기반 권한 체크 필수 실수로 누구나 호출 가능해질 수 있음
fallback()는 조심해서 사용 보안 취약점 원인이 될 수 있음

✅ [3단계 요약]

개념 설명
function 컨트랙트의 실행 단위
view, pure, payable 상태 접근 여부 및 수신 가능 여부 결정
public, external 접근 제어
msg.sender, msg.value 호출자 정보 및 송금 금액
receive() / fallback() 이더 수신 및 비정상 호출 대응