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
/private
은 library
나 modifier
설계 시 많이 사용됨
📌 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() |
이더 수신 및 비정상 호출 대응 |