---
title: "Yul에서 packed storage 변수를 읽고 쓰는 방법"
description: "Yul에서 Packed Storage 변수를 읽고 쓰는 방법 이해하기"
---

# Yul에서 packed storage 변수를 읽고 쓰는 방법

[Yul](http://www.alchemy.com/overviews/what-is-yul)은 [스마트 컨트랙트](https://www.alchemy.com/overviews/solidity-smart-contract) 내부에서 어셈블리 언어 형태를 작성하는 데 사용할 수 있는 중간 수준 프로그래밍 언어입니다. Yul의 문법과 storage 동작 방식을 배운 뒤에는, Yul에서 packed storage 변수를 읽고 쓰는 방법을 이해하는 것이 중요합니다.

## **Yul에서 packed storage 변수를 읽고 쓰는 방법**

var5를 4로 바꾸고 싶다고 가정해봅시다. var5가 slot 3에 위치한다는 것을 알고 있으므로, 다음과 같이 시도해볼 수 있습니다:

getValInHex\(3\)을 사용해보면 slot 3이 다음과 같이 다시 쓰여진 것을 볼 수 있습니다:

`0x0000000000000000000000000000000000000000000000000000000000000004`

문제는 이제 var4가 0으로 다시 쓰여졌다는 것입니다. 이번 섹션에서는 packed 변수를 읽고 쓰는 방법을 다루는데, 그 전에 Yul 문법에 대해 조금 더 알아볼 필요가 있습니다.

이런 연산들이 익숙하지 않아도 걱정할 필요 없습니다. 지금부터 예제와 함께 하나씩 살펴보겠습니다.

먼저 and\(\)부터 시작해보겠습니다. 두 개의 bytes32 값을 and\(\) 연산자에 적용해서 어떤 결과가 나오는지 확인해보겠습니다.

출력 결과를 보면 다음과 같습니다:

`0x0000000000000000000000009acc1d6aa9b846083e8a497a661853aae07f0f00` 

and\(\)가 하는 일은 양쪽 입력의 각 비트를 보고 값을 비교하는 것이기 때문입니다.

두 비트가 모두 1이면 \(이진수 관점에서: 활성 또는 비활성\) 해당 비트를 그대로 유지합니다.

그렇지 않으면 0으로 설정됩니다.

이번에는 or\(\)의 코드를 봅시다.

이번 출력 결과는 다음과 같습니다:

`0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff`

이는 둘 중 하나의 비트라도 활성화되어 있는지 확인하기 때문입니다.

mask 변수를 다음과 같이 바꾸면 어떻게 되는지 살펴봅시다:

`0x00ffffffffffffffffffffff0000000000000000000000000000000000000000`

보시다시피 출력 결과가 다음과 같이 바뀝니다:

`0x00ffffffffffffffffffffff9acc1d6aa9b846083e8a497a661853aae07f0f00`

첫 바이트가 0x00인 것에 주목하세요. 두 입력 모두 첫 바이트에 활성화된 비트가 없기 때문입니다.

xor\(\)는 조금 다릅니다. 한쪽 비트는 활성\(1\)이고 다른 쪽 비트는 비활성\(0\)이어야 합니다.

**다음은 코드 예시입니다:**

출력 결과는 다음과 같습니다:

`0xffffffffffffffffffffffff0000000000000000000000000000000000000000`

핵심 차이는 0x00과 0xff가 정렬된 위치에서만 출력의 활성 비트가 나타난다는 점입니다.

shl\(\)과 shr\(\)은 서로 매우 비슷하게 동작합니다. 둘 다 입력된 비트 수만큼 입력값을 시프트합니다. shl\(\)은 왼쪽으로, shr\(\)은 오른쪽으로 시프트합니다.

코드를 살펴봅시다!

출력:

ans1: `0x0000ffff00000000000000000000000000000000000000000000000000000000`

ans2: `0x00000000000000000000000000000000000000000000000000000000ffff0000`

먼저 ans1을 살펴보겠습니다. 16비트\(2바이트\)만큼 shr\(\)를 수행합니다. 보시다시피 마지막 두 바이트가 0xffff에서 0x0000으로 바뀌고, 첫 두 바이트는 오른쪽으로 두 바이트만큼 시프트됩니다. 이를 알면 ans2는 자명합니다. 비트가 오른쪽 대신 왼쪽으로 시프트되는 것뿐입니다.

**var5에 쓰기 전에, 먼저 var4와 var5를 읽는 함수를 작성해봅시다.**

출력 결과는 예상대로 1과 2입니다.

var4를 가져오려면 다음과 같이 값을 설정하는 mask만 사용하면 됩니다:

`0x0000000000000000000000000000000000000000000000000000000000000001`

그런 다음 1과 같은 uint128을 반환합니다.

var5를 읽을 때는 var4를 오른쪽으로 시프트해서 걷어내야 합니다.

그러면 다음과 같이 남고, 이를 반환할 수 있습니다:

`0x0000000000000000000000000000000000000000000000000000000000000002`

storage slot 하나에 두 개 이상의 변수가 packed되어 있는 값을 읽으려면 시프트와 마스크를 함께 사용해야 하는 경우도 있다는 점에 유의해야 합니다.

**자, 이제 드디어 var5의 값을 4로 바꿀 준비가 되었습니다!**

첫 단계는 storage slot 3을 로드하는 것입니다.

다음으로 mask를 만들어야 합니다.

var4를 읽을 때와 마찬가지로, 값을 다음과 같이 분리하고자 합니다:

`0x0000000000000000000000000000000000000000000000000000000000000001`

다음 단계는 새 값이 var5의 slot 위치에 맞게 다음과 같은 형태가 되도록 포맷하는 것입니다:

`0x0000000000000000000000000000000400000000000000000000000000000000`

var5를 읽을 때와 달리, 이번에는 값을 왼쪽으로 시프트합니다.

마지막으로 or\(\)를 사용해 값을 32바이트 hexadecimal로 결합하고, 그 값을 slot 3에 저장합니다.

getValInHex\(3\)을 호출해서 작업을 확인할 수 있습니다.

이는 다음과 같은 결과를 반환하며, 이는 우리가 예상한 값입니다:

`0x0000000000000000000000000000000400000000000000000000000000000001`

좋습니다. 이제 packed storage slot을 읽고 쓰는 방법을 알게 되었습니다! 다음으로 Yul에서 [Memory](http://www.alchemy.com/overviews/yul-memory), [Storage](http://www.alchemy.com/overviews/yul-storage), [Smart Contract Calls](http://www.alchemy.com/overviews/yul-contract-calls)가 어떻게 동작하는지 알아보세요.
