궁금한 주제를 찾아보세요

비트코인, 스테이블코인, 온체인 데이터처럼 주제로 검색하세요.

다시 읽을 이야기

저장한 글은 이 브라우저에만 보관됩니다.

해설블록체인 기술

EVM storage·memory·calldata는 비용과 수명이 어떻게 다를까

영구 storage, 호출 frame의 memory, 읽기 전용 calldata가 복사·수정·가스와 수명에서 어떻게 다른지 배열 처리 사례로 설명합니다.

난이도 중급주제 카테고리와 개념 밀도 기준
영구 보관 금고·작업 책상·입력 봉투로 구분한 EVM storage·memory·calldata 저장 영역 그림
주제의 이해를 돕기 위한 개념 일러스트
먼저 읽는 핵심

Storage는 영구 상태, memory는 호출별 작업 공간, calldata는 읽기 전용 입력입니다.
참조형 대입은 위치 조합에 따라 alias 또는 전체 복사가 됩니다.
가스 비교는 bytes 길이, memory expansion과 storage의 warm·cold 상태를 함께 봐야 합니다.

저장소(storage)는 계약 계정에 영구히 남는 256비트 키-값 영역으로, 상태를 바꾸는 거래가 끝난 뒤에도 유지됩니다. 메모리(memory)는 메시지 호출마다 새로 생기는 바이트 단위 작업 공간이라 호출이 끝나면 사라지고, 커질수록 확장 가스가 붙습니다. 호출 데이터(calldata)는 외부 호출로 들어온 ABI 바이트를 담는 읽기 전용 영역이어서 원본을 고칠 수 없고 필요한 부분만 읽을 수 있습니다. Solidity 참조형에서 데이터 위치는 단순한 성능 표시가 아니라 별칭(alias)이냐 복사냐를 가르는 규칙입니다. 저장소 포인터를 수정하면 영구 상태가 바뀌고, 저장소 값을 메모리 변수에 대입하면 별도 복사본이 생깁니다.

세 영역은 수명부터 다릅니다

계약 계정마다 있는 저장소는 256비트 슬롯 번호에서 256비트 값으로 이어지는 영구 키-값 공간입니다. 함수가 끝나도 남아 있고, 다음 거래가 같은 상태를 읽습니다. Solidity 상태 변수는 압축 배치, 매핑 해시, 동적 배열 규칙에 따라 슬롯에 놓입니다. 다른 계약의 저장소를 SLOAD로 직접 읽을 수는 없으며, CALL과 DELEGATECALL 중 어떤 문맥이냐에 따라 어느 계정의 저장소인지가 정해집니다.

메모리는 메시지 호출마다 깨끗이 비워진 상태로 주어지고 바이트 단위로 주소를 매기지만, 일반적인 워드 연산은 32바이트씩 다룹니다. 높은 오프셋을 처음 건드리면 확장 비용이 붙고, 크기가 커질수록 선형 항과 제곱 항이 함께 늘어납니다. 호출 데이터는 거래나 외부 호출이 넘겨준 바이트이며 읽기 전용이라 CALLDATALOAD·CALLDATACOPY로 읽습니다.

데이터 위치는 같은 배열을 어디에 놓을지 정하는 표식이 아니라, 언제 사라지고 누가 수정 결과를 보게 되는지 정하는 실행 규칙입니다.

JOBCOIN 해설

그림으로 보기프로토콜 실행의 기본 구조
입력이 실행 규칙을 통과할 때 상태가 바뀌는 프로토콜 개념도
그림과 함께 짚어볼 본문 내용

그림은 이 주제의 공통 개념을 단순화한 설명입니다. 아래 항목에서 이 글의 구체적인 조건과 예외를 함께 읽어보세요.

  1. 세 영역은 수명부터 다릅니다

    계약 계정마다 있는 저장소는 256비트 슬롯 번호에서 256비트 값으로 이어지는 영구 키-값 공간입니다.

  2. 가변성과 복사 규칙을 표로 확인합니다

    외부 함수의 동적 매개변수를 calldata로 선언하면 컴파일러가 처음부터 전체를 메모리로 풀지 않고, 접근할 때 필요한 부분만 읽을 수 있습니다.

  3. 배열 하나도 위치에 따라 하는 일이 달라집니다

    외부 함수가 원소 1,000개짜리 uint 배열을 받아 합계만 낸다고 해 보겠습니다.

설명을 위한 개념도 · 실제 가격·거래 내역·통계가 아닙니다.

가변성과 복사 규칙을 표로 확인합니다

외부 함수의 동적 매개변수를 calldata로 선언하면 컴파일러가 처음부터 전체를 메모리로 풀지 않고, 접근할 때 필요한 부분만 읽을 수 있습니다. 함수 안에서 값을 바꿔야 한다면 메모리 복사가 필요합니다. 공개 함수나 내부 호출에서는 컴파일러 버전과 ABI 경로에 따라 동작이 다를 수 있으니 생성된 중간 표현(IR)과 가스 보고서로 확인합니다.

저장소 참조끼리 대입하면 같은 상태 객체를 가리킬 수 있지만, 메모리로 옮기면 복사본이 생깁니다. 메모리 참조끼리 대입하면 같은 메모리 객체를 공유할 수 있어 한 변수로 원소를 바꾸면 다른 참조에서도 그 변화가 보입니다. 값형은 스택 값 복사가 기본이므로 배열·구조체 같은 참조형 규칙을 그대로 적용하지 않습니다.

EVM 데이터 영역 비교
영역 수명 쓰기 대표 비용 요인
저장소 거래가 끝나도 영구 가능 SLOAD·SSTORE, 첫 접근 여부, 값 변화
메모리 현재 호출 단위 가능 최대 사용 오프셋과 확장
호출 데이터 현재 호출 입력 불가 입력 바이트 비용과 복사·해독
반환 데이터 직전 외부 호출 결과 직접 수정 불가 RETURNDATACOPY 크기
스택 현재 실행 단위 상단 워드 연산 옵코드와 1024 깊이 제한

배열 하나도 위치에 따라 하는 일이 달라집니다

외부 함수가 원소 1,000개짜리 uint 배열을 받아 합계만 낸다고 해 보겠습니다. calldata로 받으면 원본을 그대로 순회하며 읽습니다. 원소마다 값을 바꿔야 해서 uint[] memory로 받으면, ABI 디코더가 배열 길이와 내용을 메모리에 펼쳐 놓으면서 확장 비용을 치릅니다. 이 배열을 상태 변수에 저장하면 슬롯마다 SSTORE가 일어나 가장 큰 지속 비용이 듭니다.

저장소 배열을 메모리 지역 변수로 복사한 뒤 고치면 영구 배열은 바뀌지 않습니다. 반대로 저장소 포인터를 잡고 원소를 고치면 거래가 성공했을 때 상태 루트에 반영됩니다. 코드 리뷰에서는 함수 시그니처만 보지 말고, 대입 양쪽의 데이터 위치와 컴파일러가 만든 복사 루프까지 확인해야 합니다.

  • 이 데이터가 다음 거래에서도 필요한지부터 따집니다.
  • 입력을 고치지 않는다면 calldata를 쓸 수 있는지 확인합니다.
  • 메모리 최대 오프셋과 예상 배열 길이에 상한을 둡니다.
  • 코드 리뷰에서 저장소 포인터와 메모리 복사를 표시해 둡니다.
  • 컴파일러 버전을 고정하고 가스 측정 결과를 비교합니다.

비용은 같은 거래에서 처음 접근하는 콜드 슬롯에서 갈립니다

SSTORE 비용은 슬롯의 원래 값, 현재 값, 새 값과 환급 카운터에 따라 달라집니다. 같은 거래 안에서 처음 접근하는 콜드 슬롯과 이미 접근한 웜 슬롯도 비용이 다릅니다. ‘저장소 쓰기는 늘 20,000 가스’라는 말은 0에서 영이 아닌 값으로 처음 설정하는 일부 경우만 설명합니다.

메모리도 이미 확장한 범위 안에서 다시 접근할 때와 최고 사용 지점을 새로 늘릴 때의 비용이 다릅니다. 호출 데이터 역시 체인의 거래 데이터 요금과 실행 중 복사 비용을 나눠 봐야 합니다. 최적화기가 루프나 경계 검사를 바꿀 수 있으므로 어림 수치 대신 목표 컴파일러·EVM 버전으로 만든 바이트코드를 직접 측정합니다.

안전성은 길이와 별칭 검증에서 시작합니다

공격자가 아주 긴 calldata 배열을 보내면 전체 복사나 루프가 블록 가스 한도 안에서 실패하거나, 서비스의 가스 추정을 바닥내게 만들 수 있습니다. 길이 상한, 페이지 나누기, 머클 증명처럼 입력 크기를 묶어 두는 설계를 씁니다. 어셈블리에서 calldata 오프셋과 길이를 직접 다룰 때는 오버플로와 ABI 범위 검사를 빼먹지 않습니다.

업그레이드 계약은 저장소 배치를 바꾸면 기존 슬롯의 의미를 잃습니다. 메모리 최적화가 옳더라도 영구 변수 순서와 매핑 기준 슬롯은 따로 호환성을 검사해야 합니다. 성능 검토와 업그레이드 안전 검토를 가스 절감 숫자 하나로 합쳐 버리지 않습니다.

자주 묻는 질문

calldata 배열의 원소를 함수 안에서 바꿀 수 있나요?

읽기 전용이라 직접 바꿀 수 없습니다. 고쳐야 한다면 메모리로 복사해 별도 배열로 다룹니다.

메모리는 거래가 진행되는 동안 계속 공유되나요?

아닙니다. 메시지 호출 단위마다 새 메모리가 주어지며, 외부 호출 사이에서는 호출 데이터와 반환 데이터로 값을 주고받습니다.

저장소 변수를 읽기만 해도 가스가 드나요?

체인 위에서 실행하면 SLOAD 비용이 들고, 콜드·웜 접근 여부에 따라 금액이 달라집니다. 체인 밖에서 eth_call로 실행하면 사용자가 수수료를 내지 않지만 실행 규칙은 똑같이 적용됩니다.

더 깊이 읽기

본문에서 다룬 개념과 확인 절차를 다음 글에서 이어서 살펴보세요.

참고한 원문 자료

자료 확인 기준일 2026.09.27
  1. Solidity Documentation — Storage, Memory and Stackdocs.soliditylang.org
  2. Solidity Documentation — Data locationdocs.soliditylang.org
작성 방식과 확인 범위
출처 수집
원문 링크 2개 제공
작성·확인
공식 기관 자료를 근거로 AI 도구를 활용해 작성했고, 운영자가 발행 전에 읽어 확인합니다.
전문가 검토
세무·법률 전문가 검토는 거치지 않았습니다.

투자·세무 판단은 전문가와 상의하세요. 제도와 거래소 안내는 바뀔 수 있으니 원문의 적용 대상과 최신 안내를 함께 확인해 주세요.

이해를 위한 정보 콘텐츠

이 글은 특정 자산의 매수·매도 또는 수익을 권유하지 않습니다. 자료의 발표 시점과 이후 변경 사항을 함께 확인해 주세요.

편집 원칙 보기 →이 기사 정정 제보 →