✅ 2. 상태 변수와 데이터 타입
EVM의 스토리지 비용, 가스 최적화, 데이터 모델링과 밀접한 관련
📌 1. 상태 변수(⛓️ Storage Variables)
uint public totalSupply;
- 블록체인에 영구 저장되는 변수
- 컨트랙트의 persistent state(영속 상태)를 나타냄
- EVM의
storage에 기록 → 가스 비용 높음
✅ 특징
- 함수 바깥,
contract 내부에 선언
public을 붙이면 자동으로 getter 함수 생성
- 영구 저장(storage) : 블록체인에 데이터 기록
→ 트랜잭션마다 업데이트 기록
📌 2. Solidity 기본 데이터 타입
| 타입 |
설명 |
예시 |
uint, int |
정수형. uint256 기본 |
uint public x = 100; |
bool |
불리언 (true/false) |
bool isActive = true; |
address |
이더리움 주소 |
address public owner; |
string, bytes |
문자, 이진 데이터 |
string name = "Alice"; |
enum |
상태값 열거형 |
enum Status { Open, Closed } |
array, mapping, struct |
복합 자료형 |
아래에서 자세히 설명 |
🧠 uint vs uint256?
- 동일함.
uint는 uint256의 alias
uint8, uint16, ..., uint256으로도 세분화 가능 (메모리 최적화 시 유용)
📌 3. 메모리 위치 지정자: storage, memory, calldata
Solidity에서는 변수의 저장 위치를 명시해야 함. (특히 참조 타입)
| 위치 |
설명 |
사용 시점 |
주의점 |
storage |
블록체인에 영구 저장 |
상태 변수 |
가스 비용 매우 큼 |
memory |
함수 실행 중 임시 저장 |
값 복사 시 (읽기/쓰기) |
함수 끝나면 사라짐 |
calldata |
읽기 전용 입력 데이터 |
external 함수 파라미터 (gas-efficient) |
가스 비용 최적화 |
🧠 요약
- storage: 블록체인 → 영구 → 느리고 비쌈
- memory: RAM → 임시 → 빠름
- calldata: 입력받은 데이터 → 읽기만 → 가장 가볍고 싸다
예시
function setName(string memory _name) public {
name = _name;
}
storage
string public name; // ⛓️ storage에 저장 (영구)
- 컨트랙트 내 상태 변수
- 항상 블록체인에 저장됨 → 수수료 발생
memory
function setName(string memory _name) public {
name = _name; // _name은 메모리 → name은 스토리지에 저장
}
- 함수 파라미터에서 memory 사용
- 임시로 RAM에 복사 → 수정 가능
- 함수 끝나면 사라짐
calldata
function updateName(string calldata _newName) external {
name = _newName; // calldata → storage 복사
}
- external 함수에서 입력받는 데이터
- 읽기 전용 (변경 불가)
- 가스 절약 효과 큼
📌 4. 변수 수식자: public, private, internal, external
| 수식자 |
접근 가능 영역 |
Remix 버튼 |
public |
어디서든 접근 가능 |
✅ 생성됨 |
private |
해당 컨트랙트 내부만 |
❌ |
internal |
내부 + 상속 컨트랙트 |
❌ |
external |
외부 호출만 가능 |
✅ (함수만 사용 가능) |
🧠 public 상태변수는 자동으로 getter 함수 생성됨
uint public count;
// → count()라는 getter 함수 자동 생성
📌 5. constant와 immutable
constant
uint constant MAX_SUPPLY = 1000;
- 컴파일 타임 상수
- 상태변수지만 EVM bytecode에 포함됨 → storage를 차지하지 않음
immutable
uint immutable launchTime;
constructor() {
launchTime = block.timestamp;
}
- 생성자(constructor)에서만 1회 설정 가능
- 컴파일 시 값은 모르지만 배포 시 고정됨
constant와 달리 런타임에 결정 가능
✅ [실무 예제]
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract Example {
string public name; // storage
uint public totalSupply = 1000; // 상태 변수
address public immutable owner; // 배포 후 고정
constructor() {
owner = msg.sender;
}
function setName(string memory _name) public {
name = _name;
}
function getSender() external view returns (address) {
return msg.sender;
}
}
🧠 실무 팁 정리
| 팁 |
설명 |
public 변수는 자동 getter 생성 |
굳이 함수로 만들 필요 없음 |
memory는 함수 안에서만 사용 |
외부 입력을 임시 저장 |
constant와 immutable은 가스 절약에 유리 |
상태 변수 대신 최대한 활용 |
storage를 줄이면 가스비 절감 |
구조체, 매핑 조합 시 특히 고려 |
string은 memory 필수 |
함수 파라미터로 받을 때 항상 명시 |
✅ [2단계 요약]
| 키워드 |
역할 |
uint, bool, address |
기본 자료형 |
string, bytes |
동적 데이터 |
storage |
블록체인에 저장됨 |
memory |
함수 실행 중 임시 사용 |
constant, immutable |
변경 불가 변수, 가스 절약 |
public, private 등 |
접근 제어자 |
댓글