이더리움 솔리디티: 메모리 vs 스토리지 & 구조체 내부의 배열을 초기화 하는 방법
이 글은 Georgios Konstantopoulos가 쓴 Ethereum Solidity: Memory vs Storage & How to initialize an array inside a struct를 번역한 글입니다. 오역이 있으면 Private Note 기능으로 알려주세요!
Loom Network의 텔레그램(약 15,000명의 사람들이 있어요! — 한국 텔레그램은 여기로 오세요 😉)에서 사람들은 룸의 로드맵, 블록체인 이론, 이더리움 관련 질문 및 솔리디티 트러블 슈팅과 같은 다양한 주제의 질문을 합니다.
struct
안에서 struct
내부의 array
를 초기화하는 방법을 묻는 구체적인 질문이 있었습니다. 이 질문을 한 사람은 자신의 코드를 제공했고, 왜 실행되지 않는지 궁금해했습니다. 저도 여기에 대한 답을 바로 생각해낼 수 없었기에 이 글에서 이 주제를 간단하게 이야기해보려 합니다.
앞서 언급한 실행되지 않는 코드는 아래에서 확인할 수 있습니다. 스스로 해결해보시는 것을 추천합니다(CryptoZombies에서 그동안 연습해왔죠?).
답을 찾으려면 계속 읽어보세요.
위의 Fiddle에서 memory
는 변수 room
을 선언하기 위해 필요한 키워드입니다. Room room
과 같이 선언했다면, 컴파일러가 다음과 같은 에러를 리턴할 것입니다:
TypeError: Type struct StructArrayInitWrong.Room memory is not implicitly convertible to expected type struct StructArrayInitWrong.Room storage pointer.
몇 가지 이론
컨트랙트의 storage
변수는 컨트랙트의 상태를 정의하고, sendTransaction 콜을 통해서면 상태를 변경할 수 있습니다[1].
memory
변수는 호출 함수 내부에서만 존재하는 임시 변수입니다(그 밖에서는 정의할 수 없죠). 해당 함수를 탈출하면 지워지고, 일반적으로 storage
변수들을 사용하는 것보다 저렴합니다 — 가스 비용에 대한 자세한 내용은 여기를 참고하세요.
여러분의 이해를 돕기 위해 컨트랙트의 상태에 영향을 주기 위해 함수 안에서 storage
변수를 사용하는 방법에 대한 예제를 하나 살펴도록 하죠.
아래의 Fiddle에서, x
의 사본을 함수 g()
로 전달했기 때문에, 상태 변수 x
는 실행 후에도 값이 변하지 않고 남아 있습니다(이것이 우리가 pure
키워드를 사용하는 이유죠).
반면에, 함수 h()
에 있는 y
는 storage
로 선언되었습니다. x
가 참조에 의해 전달되었다는 것이지요. 결과적으로, 함수 h()
를 호출한 뒤에 상태 변수 x
는 수정됩니다.
여러분은 함수 f()
를 호출하여 결과를 테스트해볼 수 있고, y[2]
의 값을 확인할 수 있습니다. 함수 h()
가 호출된 뒤에 함수 g()
가 호출되어도 상태 변수의 값은 변하지 않습니다.
이론은 이만하면 충분하고, 원래 질문에 답해봅시다.
구조체를 초기화할 때 players
배열을 초기화할 수 없으므로, 다음 단계를 수행해야 합니다:
- 비어있는
players
배열로room
구조체를 초기화합니다 — 여기와 이 fiddle에 설명된 것처럼 말이죠. room
을rooms
배열로 Push 합니다.room
의players
배열의 가장 끝에msg.sender
를 Push 합니다(rooms.length-1
은 항상 배열의 가장 마지막 요소를 가리킵니다).
아래는 실행되는 코드의 Fiddle입니다:
여기서 트릭은 new address[](0)
가 빈 주소 배열을 위한 메모리를 할당한다는 것입니다. 초기화 이후에는, room
은 rooms
에 추가되고, 스토리지 변수의 일부가 되는 것이죠. 이는 players
배열에서 작업하고 값을 Push할 수 있도록 해줍니다.
참고: 만약에 우리가 new uint[](8)
을 사용했다면, 8개의 숫자 0을 가지고 있는 배열을 얻었을 것입니다. 이 fiddle에서 테스트해볼 수 있습니다.
오늘은 여기까지입니다. 이것으로 우리가 스토리지/메모리와 관련된 오해를 풀었다면 좋겠습니다. 함수에서 사용하는 방법도 함께 말이죠. 우리의 텔레그램 채널에 여러분의 질문을 올려주세요! 몇 개의 메시지로 답을 하기 어렵다면 질문에 관련된 글을 올리겠습니다(또는 크립토좀비 강의로 말이죠!)
Loom Network는 고성능 디앱을 확장하기 위한 멀티체인 상호운용 플랫폼입니다 — 이미 상용 가능한 상태이며, 감사 및 실제 테스트를 거쳤습니다.
Loom 베이스체인에 여러분의 디앱을 한 번 배포하고 나면, 오늘날 모든 주요 블록체인에 걸쳐 가능한 가장 광범위한 사용자 기반에 접근할 수 있습니다.
Loom Network를 처음 접하시나요? 여기서 시작하세요.
LOOM 토큰을 스테이킹해서 베이스체인을 보호하는 데 참여하고 싶으신가요? 여기서 그 방법을 알아보세요.
우리가 하는 일이 마음에 드시나요? 그렇다면 어서 우리의 프라이빗 메일링 리스트에 가입하고, 우리가 계속 전달하는 모든 업데이트를 계속 받아보세요.