Solidity에서 mapping이란?
작성자 Alchemy
Solidity의 매핑(Mapping)은 키-값 쌍으로 데이터를 저장하는 해시 테이블로, 여기서 키는 Ethereum이 지원하는 내장 데이터 타입 중 어떤 것이든 될 수 있습니다. 매핑은 Solidity 개발을 학습할 때 이해해야 할 핵심 개념입니다.
이 글에서는 매핑이 무엇인지, 매핑이 어떻게 작동하는지, 매핑과 배열의 차이점을 설명하고, Ethereum 및 Optimism, Arbitrum과 같은 Solidity 호환 블록체인에서 최상의 스마트 컨트랙트를 개발할 수 있도록 매핑의 예시를 제공합니다.
해시 테이블이란?
해시 테이블은 데이터를 연관 방식으로 저장하는 자료구조입니다. 해시 테이블에서 데이터는 배열 형태로 유지되며, 각 데이터 값은 고유한 인덱스 값을 가집니다. 해시 테이블은 배열을 저장 매체로 사용하고, 해시 기법을 이용해 요소를 삽입하거나 찾을 인덱스를 결정합니다.

필요한 데이터의 인덱스를 알고 있으면 매우 빠르게 값을 반환받을 수 있습니다. 이 때문에 해시 테이블은 데이터의 양과 관계없이 삽입과 검색 연산이 매우 빠른 자료구조입니다.
Solidity의 매핑이란?
매핑은 Solidity의 해시 테이블로, 키-값 쌍으로 데이터를 저장하며, 키는 참조 타입을 제외한 내장 데이터 타입 중 하나가 될 수 있고, 값의 데이터 타입은 어떤 타입이든 가능합니다.
매핑은 주로 Solidity와 Ethereum 블록체인에서 고유한 Ethereum 주소를 해당하는 값 타입과 연결하는 데 사용됩니다.
다른 프로그래밍 언어에서 매핑은 딕셔너리(dictionary)에 해당합니다.
해시 테이블과 Solidity 매핑의 차이는 무엇인가요?
매핑은 키 타입과 그에 대응하는 값 타입 쌍을 가진 해시 테이블처럼 작동하며, 다수의 _KeyType을 _ValueType에 대응시킬 수 있다는 점에서 유용합니다. 매핑에는 길이 개념이 없으며, 키나 값이 "설정되어 있다"는 개념도 없습니다. 매핑은 저장소 참조 타입 역할을 하는 상태 변수(state variable)에만 적용할 수 있습니다. 매핑이 초기화되면 가능한 모든 키를 포함하며, 이 키들은 바이트 표현이 모두 0인 값에 매핑됩니다.
Solidity에서 매핑은 다른 변수 타입과 동일한 방식으로 정의됩니다:
Solidity 배열과 매핑의 차이는 무엇인가요?
Solidity 배열은 (예를 들어 for 루프를 사용해) 데이터 그룹을 순회하는 데 더 적합한 반면, 매핑은 알려진 키를 기준으로 값을 가져올 수 있을 때(즉 데이터를 순회할 필요가 없을 때) 더 적합합니다.
Solidity에서 배열을 순회하는 것은 매핑에서 데이터를 가져오는 것보다 비용이 많이 들 수 있고, 개발자가 스마트 컨트랙트 내에 값과 그 키를 함께 저장하고 싶어할 수 있기 때문에, 개발자들은 종종 매핑 안에서 가져올 수 있는 데이터를 참조하는 키 배열을 만들기도 합니다.
큰 배열을 순회하면 트랜잭션 자체의 가치보다 더 많은 Solidity 가스 비용이 들 수 있으므로, 개발자는 Solidity 배열을 지나치게 크게 키우지 않아야 하며, 이 때문에 매핑이 더 가스 효율적인 스마트 컨트랙트 구현 방법이 됩니다.
매핑의 추가적인 특성은 다음과 같습니다:
- 매핑에는 길이가 없습니다.
- 매핑은 키나 값이 설정되어 있다는 개념도 이해하지 못합니다.
- 매핑은 저장소 참조 타입 역할을 하는 상태 변수에만 사용할 수 있습니다.
중첩 매핑(Nested Mapping)이란?
중첩 매핑은 하나의 매핑에서 다른 매핑으로의 매핑입니다. 예를 들어 사용자 이름과 나이가 있고 이 정보를 특정 ID를 통해서만 다른 사람이 조회할 수 있도록 저장하고 싶다면, 이를 Solidity에서 이중 매핑(double mapping)이라고 합니다.
다음은 중첩 매핑의 예시입니다:
이 컨트랙트에서는 User라고 불리는 하나의 중첩 매핑을 구성했습니다. 이 매핑 안에는 두 개의 매핑을 연결했습니다:
- 특정 사용자의 id 정보를 기록하는 매핑
- 특정 사용자의 이름과 나이를 저장하는 매핑
아래 코드 블록은 사용자 정보를 반환하는 간단한 getter 함수입니다.
Solidity에서 매핑을 사용하는 방법
다음은 Solidity에서 매핑을 사용하는 예시입니다. 아래 코드 스니펫의 기능은 다음과 같습니다:
- address를 uint에 매핑하고, 매핑이 항상 값을 반환하도록 보장
- 값이 한 번도 설정된 적이 없다면 기본값을 반환
- 매핑된 주소의 값 업데이트
- 값을 기본값으로 재설정
- address를 다른 매핑에 매핑하는 중첩 매핑 생성
- 초기화되지 않은 경우에도 중첩 매핑에서 값을 가져오기
Solidity 매핑 예시
다음은 Solidity 매핑의 세 가지 예시입니다:
- ERC20 토큰 잔액
- 불리언 로직 사용
- DAO 멤버 조회
1. ERC20 사용자 잔액
이 코드 스니펫은 사용자 주소를 해당 주소의 ERC20 잔액과 매핑합니다.
2. Solidity 매핑 bool 예시
이 코드 스니펫은 후보자 이름을 목록에 나열하고 각 후보자가 받은 투표 수를 반환하도록 설계되었습니다. 이 예시는 멤버들이 조직의 의사결정에 투표하는 DAO에서 활용 사례를 가집니다.
3. 멤버 여부 확인 (DAO)
이 예시는 raisedProposals, stakeholderVotes, votedOn, contributors, _stakeholders_를 매핑하는 Dominion DAO 스마트 컨트랙트에서 가져온 것입니다.
이 코드 예시는 두 개의 Solidity 구조체인 _ProposalStruct_와 _VotedStruct_의 필드를 나열합니다.
문자열의 Solidity 매핑
더 나은 이해를 위해 매핑을 만드는 과정에서 값을 추가해 보겠습니다. 다음 예시에서 우리는:
- 컨트랙트를 생성하고
- 구조체를 정의하고
- 서로 다른 구조체 요소를 선언하고
- 매핑을 생성하고
- 매핑에 값을 추가합니다
Solidity 매핑 FAQ
다음은 Solidity 매핑에 관해 자주 묻는 질문 몇 가지입니다:
- Solidity 매핑의 길이는 무엇인가요?
- Solidity 매핑의 기본값은 무엇인가요?
- Solidity 매핑을 어떻게 공개적으로 볼 수 있나요?
Solidity 매핑의 길이는 무엇인가요?
매핑에는 길이가 없습니다. 키의 데이터는 매핑에 저장되지 않고, 대신 키가 참조하는 값을 저장하기 위해 해당 키의 keccak256 해시가 사용됩니다. 키와 값이 "그 자체로" 존재한다는 개념은 없습니다.
Solidity 매핑 기본값 타입은 무엇인가요?
다음은 Solidity 매핑의 기본값 타입입니다:
- int/uint - 키 타입 = 가능; 값 타입 = 가능
- string - 키 타입 = 가능; 값 타입 = 가능
- byte/bytes - 키 타입 = 가능; 값 타입 = 가능
- address - 키 타입 = 가능; 값 타입 = 가능
- struct - 키 타입 = 불가능; 값 타입 = 가능
- mapping - 키 타입 = 불가능; 값 타입 = 가능
- enum - 키 타입 = 불가능; 값 타입 = 가능
- contract - 키 타입 = 불가능; 값 타입 = 가능
- fixed-sized array - 키 타입 = 가능; 값 타입 = 가능
- dynamic-sized array - 키 타입 = 불가능; 값 타입 = 가능
- multi-dimensional array - 키 타입 = 불가능; 값 타입 = 가능
- variable - 키 타입 = 불가능; 값 타입 = 불가능
Solidity 매핑을 어떻게 공개적으로 볼 수 있나요?
해당 속성이 public이므로, Solidity 컴파일러가 생성하는 getter 함수를 사용하여 접근할 수 있습니다.
관련 개요

블록체인 매직을 만드세요
Alchemy는 가장 강력한 Web3 개발자 제품 및 도구를 리소스, 커뮤니티, 그리고 전설적인 지원과 결합합니다.


