본문으로 건너뛰기

Move 패키지 관리

Move 패키지는 Sui blockchain에 단일 객체로 함께 게시하는 Move 모듈의 모음이다. 패키지는 다른 패키지에 의존할 수 있으며, 온체인 identity를 유지한 채 시간이 지나도 upgrade할 수 있다. Move 패키지 manager는 dependency를 관리하고 network에 패키지를 게시하는 데 도움을 준다.

정보

Version 1.63은 Move 패키지 system에 큰 변화를 도입했다. 이 문서는 새 system을 설명한다. 이전 system 문서는 자동 주소 관리를 참조하고, 차이점과 새 system으로 마이그레이션하는 방법은 패키지 관리 마이그레이션을 참조한다.

Package 관련 file

패키지 작성자는 패키지 directory 루트에 manifest file(Move.toml)를 제공해 패키지를 구성한다. 이 파일에는 패키지에 대한 메타데이터와 dependency 목록이 들어 있다.

처음으로 Move 패키지를 build할 때 패키지 management system은 manifest file의 정보를 사용해 패키지 dependency의 source code를 찾는다. system은 dependency의 정확한 version을 lockfile(Move.lock)에 저장한다. system은 이 과정을 _pinning_이라고 부른다.

예를 들어 manifest가 git repository의 branch를 dependency로 지정할 수 있다. 패키지 system은 그 dependency를 특정 commit에 pinning하여 이후 build가 정확히 같은 source를 사용하도록 한다.

협업자, CI job, source code를 검증하려는 사용자가 모두 같은 dependency version을 사용하도록 Move.lock 파일을 source control에 commit해야 한다. 패키지 system은 manifest file이 바뀌거나 sui move update-deps 명령을 실행한 경우에만 dependency를 다시 pinning한다. Move.lock은 수동으로 편집하면 안 된다.

패키지 management system이 사용하는 세 번째 파일은 publication file(Published.toml)이다. 패키지를 게시할 때마다 패키지 system은 온체인 address, upgrade capability address, 패키지 build에 사용한 compiler version 정보 등 publication 메타데이터로 이 파일을 갱신한다. Published.toml 파일은 source control에 commit해야 한다.

마지막으로 test-publish 명령은 일반적으로 Pub.<env-name>.toml로 이름 붙는 ephemeral publication file을 사용한다. 이 파일에는 local network 게시처럼 공유를 의도하지 않은 임시 게시에 대한 정보가 들어 있다. 이 파일은 source control에 commit하면 안 된다.

Dependency 관리

dependency를 사용하면 패키지가 다른 패키지의 코드를 사용할 수 있다.

Dependency 추가

dependency를 추가하려면 manifest의 [dependencies] 섹션에 줄을 추가한다. 예를 들어 mvr 패키지 @potatoes/ascii에 의존하려면 다음과 같이 작성한다:

[package]
name = "example"

[dependencies]
ascii = { r.mvr = "@potatoes/ascii" }

그런 다음 Move source code에서 ascii 패키지의 모듈을 참조한다:

module example::example_module;

use ascii::ascii;
use ascii::char;

이 패키지를 build하면 패키지 system이 ascii 패키지의 source code를 다운로드하여 사용한다. 게시되면 패키지는 ascii Published.toml file에서 참조한 온체인 패키지 객체에 연결된다.

Dependency type 종류

Move 패키지 system은 각기 다른 사용 사례에 맞는 4가지 dependency type을 지원한다:

  • Move registry(mvr) dependency는 ecosystem에서 게시된 패키지에 의존하는 데 권장되는 방식이다.
  • local dependency는 단일 repository에 여러 패키지가 들어 있을 때 사용한다.
  • git dependency는 아직 Move registry에 게시되지 않은 패키지에 의존할 때 사용할 수 있다.
  • system dependency는 Sui에 포함된 built-in 패키지에 사용한다.

이 섹션의 나머지 부분에서는 이러한 dependency type을 자세히 설명한다.

Move registry (mvr) dependency(권장)

다른 패키지에 의존하는 선호 방식은 mvr라고 부르는 Move registry를 사용하는 것이다. Move registry는 게시된 package를 그 source code와 연결하는 온체인 database이다.

mvr 이름이 @example/package인 패키지에 의존하려면 example = { r.mvr = "@example/package" } 섹션에 [dependencies]를 추가한다.

장점:

  • environment(Mainnet Testnet)에 맞는 올바른 version을 자동으로 resolve한다.
  • 패키지 source code가 검증되고 이용 가능함을 보장한다.
  • 게시된 패키지에 의존하는 가장 단순한 방법이다.

Local dependency 방식

local dependency는 같은 repository 안의 다른 패키지에 의존하고 싶을 때 유용하다. 예를 들어 repository에 packages/apackages/b directory에 Move 패키지가 있고 패키지 a가 패키지 b에 의존하길 원한다면 b = { local = "../b" }packages/a/Move.toml를 추가한다.

장점:

  • 개발 중 빠른 반복 작업이 가능하다.
  • 변경 사항을 시험하기 위해 패키지를 게시할 필요가 없다.
  • 관련 패키지를 동기화된 상태로 유지할 수 있다.

Git dependency 방식

git dependency는 git repository에 저장된 패키지에 의존할 때 사용할 수 있다. git dependency에는 repository URL, repository 안에서 패키지를 포함하는 subdirectory, revision(branch, tag 또는 40자 commit hash)이 포함되어야 한다. 예를 들어 usdc 패키지에 dependency를 추가하려면 manifest에 다음을 추가할 수 있다:

[dependencies]
usdc = { git = "https://github.com/circlefin/stablecoin-sui.git", subdir = "packages/usdc", rev = "master" }

manifest file은 TOML로 작성되므로 inline table을 확장해서 쓸 수도 있다. 앞선 예시는 다음과 동일하다:

[dependencies.usdc]
git = "https://github.com/circlefin/stablecoin-sui.git"
subdir = "packages/usdc"
rev = "master"
주의

축약된 commit hash를 사용할 수는 있지만, 그렇게 하면 전체 git history를 다운로드해야 하므로 전체 40자 hash를 포함하는 것보다 효율이 떨어진다.

System dependency 방식

정보

system dependency는 이전 system에는 존재하지 않으며, implicit dependency도 다르게 동작한다.

여러 패키지가 Sui에 built-in으로 포함되어 있다. system dependency type을 사용해 이러한 패키지에 의존할 수 있다. 사용 가능한 system 패키지는 std, sui, sui_system, bridge, deepbook이다.

하지만 다음 사항에 유의해야 한다:

  • std 섹션에 sui를 쓰지 않는 한 implicit-dependencies = false[package] 패키지는 암묵적으로 포함된다.
  • 따라서 이를 명시적으로 포함할 필요는 없다.
  • deepbook system 패키지는 더 이상 사용되지 않는 DeepBook version 2용이다.
  • 새 application은 deepbook = { mvr = "@deepbook/core" }를 추가해 DeepBook version 3를 사용해야 한다.

system dependency를 포함하려면 { system = "<name>" }라고 작성한다. 예를 들어 sui_system을 사용하려면 sui_system = { system = "sui_system" } 섹션에 [dependencies]를 추가한다.

고급 dependency configuration

rename-from, override, modes처럼 4가지 dependency type 모두에 사용할 수 있는 추가 필드가 있다.

Dependency 이름 변경

정보

rename-from은 이전 system에는 존재하지 않는다.

rename-from 필드는 같은 이름을 가진 여러 패키지에 의존할 때 사용한다. 기본적으로 패키지 system은 dependency에 붙인 이름이 dependency가 스스로 부여한 이름과 같은지 검사한다. 하지만 rename-from 필드를 사용하면 사용하는 이름을 바꿀 수 있다. 예를 들어 @a/math@b/math가 모두 math라는 이름의 패키지를 가리킨다면 다음과 같이 작성해 둘 모두에 의존할 수 있다:

[dependencies]
math_a = { r.mvr = "@a/math", rename-from = "math" }
math_b = { r.mvr = "@b/math", rename-from = "math" }

그런 다음 Move code에서는 둘 다 다음처럼 참조할 수 있다:

use math_a::signed;
use math_b::muldiv;

Dependency version override 설정

override flag는 같은 패키지의 서로 다른 version에 의존하는 패키지를 결합할 때 사용한다. Move 패키지 system은 하나의 패키지 안에서 사용되는 각 패키지의 version이 오직 1개이기를 요구한다. 예를 들어 패키지 a가 패키지 bc에 의존하려 하지만 bd의 version 1에 의존하고 cd의 version 2에 의존한다고 가정하자:

패키지 system은 기본적으로 이를 허용하지 않는데, 이는 패키지 a의 code를 실행하려면 d의 version 1과 2가 모두 필요하기 때문이다.

dependency에 override = true를 추가하면 dependency 전체가 지정된 version의 dependency를 사용하도록 강제한다. 앞선 예시에서는 d version 2에 대한 override dependency를 추가할 수 있고, 그러면 b는 version 1 대신 d의 version 2를 사용하게 된다.

패키지를 더 새로운 version으로 override하는 것만 허용된다. 예시에서 d를 downgrade하게 되므로 c version 1에 대한 override dependency를 추가할 수는 없다.

Test-only 및 mode별 dependency

modes 필드를 사용하면 test mode 같은 특정 mode에서만 사용하는 dependency를 추가할 수 있다. modes 필드를 제공하지 않으면 dependency는 모든 mode에 포함된다. 예를 들어 ascii dependency를 testing에만 포함하려면 다음과 같이 작성한다:

ascii = { r.mvr = "@potatoes/ascii", modes = ["test"] }

이 dependency는 sui move test를 실행하거나 어떤 -m test 명령에든 sui move를 전달할 때 포함된다.

정보

현재는 서로 다른 mode마다 서로 다른 dependency를 두는 방법은 없고, mode에 따라 dependency를 포함하거나 생략하는 것만 가능하다.

Environment 구성

정보

이전 패키지 system은 chain ID별로 서로 다른 publication address만 유지한다. 이 섹션의 대부분 기능은 새로 추가된 것이다.

Move 패키지는 보통 Mainnet과 Testnet 양쪽에 게시되며, 각 network마다 서로 다른 version이 게시되는 경우가 많다. Move 패키지 system은 environment를 사용해 이러한 여러 deployment를 관리할 수 있게 한다.

패키지 build는 항상 build environment를 기준으로 수행된다. environment는 어떤 dependency 패키지를 사용할지, 어떤 address를 사용할지, 그리고 network마다 달라지는 기타 정보를 결정한다. command line은 기본적으로 active CLI environment를 사용해 build environment를 선택하지만 -e <env> option으로 이를 override할 수 있다.

기본적으로 사용 가능한 environment는 mainnettestnet이지만, manifest에 [environments] 섹션을 포함하여 추가 environment를 더할 수 있다. 예를 들어 패키지를 Devnet에 public deployment로 유지하고 싶다면 manifest에 devnet 항목을 추가할 수 있다:

[environments]
devnet = "aba3e445"

항목의 오른쪽 값은 해당 network의 chain identifier이다. chain ID는 sui client chain-identifier를 사용해 찾을 수 있다. chain identifier는 dependency가 environment name의 의미에 대해 일치하는지 보장하고, network가 초기화되어 다시 시작될 때 패키지 address를 재설정하는 데 사용된다.

주의

다른 패키지가 그 network에서 여러분의 패키지에 연결할 것으로 예상하는 경우에만 manifest에 environment를 포함해야 한다. local network는 보통 수명이 짧고 private하므로 일반적으로 manifest에 포함하고 싶지 않다. 대신 test-publish 명령을 사용해 local network에 package와 dependency를 게시하는 방법을 고려해야 한다. test-publish 명령은 deployment를 관리하는 데 훨씬 더 큰 유연성을 제공한다.

environment는 같은 chain ID를 가질 수 있으며, 같은 network에서 패키지의 여러 deployment를 유지하고 싶을 때 이것이 유용할 수 있다. 예를 들어 Testnet에서 패키지의 alpha deployment와 beta deployment를 모두 유지하고 싶다면 다음처럼 별도 environment를 추가할 수 있다:

[environments]
testnet_alpha = "4c78adac"
testnet_beta = "4c78adac"

이렇게 하면 패키지 system이 Published.toml에서 각 environment에 대해 별도의 published address를 유지하고, 서로 다른 패키지 version에 대해 서로 다른 dependency를 지정할 수 있게 된다.

Environment별 dependency

manifest의 [dep-replacements.<env>] 섹션을 사용하면 environment마다 dependency를 바꿔 끼울 수 있다. 예를 들어 Mainnet과 Testnet에서 codec library의 서로 다른 branch를 사용하고 싶다면 다음처럼 작성할 수 있다:

[dependencies]
codec = { git = "https://github.com/sui-potatoes/app.git", subdir = "packages/codec", rev = "codec@testnet-v2" }

[dep-replacements.mainnet]
codec = { git = "https://github.com/sui-potatoes/app.git", subdir = "packages/codec", rev = "codec@mainnet-v2" }

mvr를 사용하면 이를 더 쉽게 달성할 수 있는데, git는 build environment에 따라 Mainnet 또는 Testnet version을 자동으로 resolve하기 때문이다:

[dependencies]
codec = { r.mvr = "@potatoes/codec" }
정보

현재 [dependencies][dep-replacements] 사이에서 rev 필드는 병합되지 않는다. 예를 들어 [dep-replacements]에 다른 git 필드만 제공하는 식으로는 사용할 수 없고, git 필드도 함께 포함해야 한다. 또한 subdir 필드를 제공하더라도 revdep-replacements 필드가 복사되지는 않는다.

Environment별 dependency configuration

use-environment 섹션의 dependency에 제공할 수 있는 추가 필드로 published-at, original-id, use-environment가 있으며, 이는 특정 environment에서만 의미가 있다.

testnet_beta 필드는 dependency의 어떤 environment를 사용할지 나타낸다. 예를 들어 use-environment = "testnet_beta" 섹션의 dependency에 [dep-replacements.testnet]를 추가하면 published-at environment의 패키지에 의존할 수 있다.

original-idpublished-at는 dependency의 published address를 override하는 데 사용할 수 있다. 이 필드 중 하나를 포함한다면 둘 다 포함해야 한다.

original-idPublished.toml 필드는 dependency가 published-at file을 제대로 게시하지 않은 경우에만 유용하다. 예를 들어 많은 legacy 패키지는 단 하나의 environment에 대한 address만 포함한다. 이 경우 패키지가 dependency에 대해 사용할 address를 override할 수 있다.

original-id 필드에는 사용하려는 패키지 version의 address가 들어 있어야 한다.

sui move build 필드에는 패키지의 첫 번째 version address가 들어 있어야 하며, 패키지 system은 이를 사용해 두 패키지가 같은 패키지의 서로 다른 version인지 아니면 완전히 다른 패키지인지를 판단한다.

Move 패키지 작업

Package build 및 test

sui move test 또는 ~/.move를 실행할 때마다 system은 update-deps directory에 모든 dependency가 캐시되어 있는지 확인한다. 먼저 lockfile이 최신인지 확인하고 최신이 아니면 build environment에 맞게 모든 dependency를 다시 pinning한다. 그다음 패키지가 cache되어 있는지 확인하고, 없으면 다운로드한다.

system은 pinning 후에 항상 fetch를 수행하므로 manifest가 바뀌었거나 sui move update-deps를 실행해 dependency를 다시 pinning해야 하는 경우가 아니라면 network에 연결할 필요가 없다.

Dependency update 방법

모든 dependency를 다시 pinning하려면 sui client publish를 실행한다. 이 명령은 manifest file을 바꾸지 않으며, 작성한 내용과 호환되는 최신 version을 다시 다운로드하기만 한다.

Publish 및 upgrade

일반적인 패키지 게시와 upgrade(sui client upgrade 또는 Published.toml) 동안 system은 dependency가 주어진 network에 게시되어 있는지와 관련 chain ID가 일치하는지를 다시 확인한다. system은 추가적인 온체인 linkage requirement도 충족하는지 보장한다. 예를 들어 온체인 패키지는 실제로 사용하지 않는 extra dependency를 linkage에 가질 수 있으므로 system은 온체인 linkage를 포함해야 한다.

system은 갱신된 publication 정보를 포함하도록 publication file(sui client ptb)을 업데이트한다. publication file에는 게시된 version이 있는 각 environment에 대한 항목이 있다. 각 항목에는 published address, original ID(패키지의 첫 번째 version address), version number, upgrade capability, 그리고 source validation에 사용할 수 있는 build configuration 정보가 들어 있다. 다음은 publication file 예시이다:

[published.mainnet]
chain-id = "35834a8a"
original-id = "0x9c11913b6be956a7020cb9e120f03f396e52c3b766164c6163569ac9d7fabe06"
published-at = "0x9c11913b6be956a7020cb9e120f03f396e52c3b766164c6163569ac9d7fabe06"
version = 2
toolchain-version = "1.64.0"
build-config = { flavor = "sui", edition = "2024" }
upgrade-capability = "0x34f7cf31a0a12f81252ab947cb51146bc8138fa5adb3f1fe38e244734319d73c"

[published.testnet]
chain-id = "4c78adac"
published-at = "0x9813c40d93200714a1f7c9b9733ebb537e7dc60fd4b29148f7bcc0e857793813"
original-id = "0x9813c40d93200714a1f7c9b9733ebb537e7dc60fd4b29148f7bcc0e857793813"
version = 1
toolchain-version = "1.64.0"
build-config = { flavor = "sui", edition = "2024" }
upgrade-capability = "0x34f7cf31a0a12f81252ab947cb51146bc8138fa5adb3f1fe38e244734319d73c"

다른 패키지가 여러분의 패키지에 의존할 수 있도록 publication file을 source control에 commit해야 한다.

Published.toml 명령을 사용해 publish 또는 upgrade할 수도 있다. 자세한 내용은 PTB 구성하기를 참조한다.

정보

이전 system에서는 Move.lock 정보가 Published.toml에 저장되었다.

Ephemeral publication 임시 게시

정보

이전 패키지 management system은 ephemeral publication을 지원하지 않는다.

설계상 sui client test-publish file은 Mainnet과 Testnet 같은 persistent environment에 대한 publication만 기록해야 한다. local network나 Devnet의 ephemeral publication address는 일반적으로 source control에 commit하면 안 된다.

대신 패키지 manager는 testing을 위한 패키지와 dependency의 ephemeral publication을 지원한다. sui client test-publish --pubfile-path <pubfile> --build-env <env> 명령은 일반적인 publish처럼 동작하지만 system이 패키지의 publication address를 읽고 별도 파일에 기록한다는 점이 다르다.

<env> 명령은 <pubfile> environment에 맞춰 root package를 build하고(build environment 구성 참조), 그다음 ephemeral publication file <pubfile>의 address를 사용해 chain에 게시한다.

Pub.<env-name>.toml을 생략하면 manifest에 정의된 environment와 무관하게 active CLI environment의 이름을 사용한 <env-name>이 기본값이 된다. 이 파일에는 publication에 사용할 address가 들어 있다.

실제로 publish하지 않고 publication용 bytecode만 준비하려면 --pubfile-path <pubfile>sui move build --dump-bytecode-as-base64을 전달할 수도 있다:

sui move build --dump-bytecode-as-base64 --pubfile-path Pub.localnet.toml --build-env testnet

ephemeral publication file의 형식은 다음과 같다:

# generated by move
# this file contains metadata from ephemeral publications
# this file should not be committed to source control

build-env = "mainnet"
chain-id = "localnet chain ID"

[[published]]
source = "/home/User/move/packages/package1"
published-at = "..."
original-id = "..."
upgrade-cap = "..."

[[published]]
source = { git = "...", rev = "...", path = "..." }
published-at = "0x000000000000000000000000000000000000000000000000000000000000cccc"
original-id = "0x000000000000000000000000000000000000000000000000000000000000cc00"
upgrade-cap = "0x000000000000000000000000000000000000000000000000000000000011cc00"

[[published]]
source = { local = "/home/User/move/packages/package2" }
published-at = "0x0000000000000000000000000000000000000000000000000000000000001234"
original-id = "0x0000000000000000000000000000000000000000000000000000000000005678"
upgrade-cap = "0x000000000000000000000000000000000000000000000000000000000022cc00"
주의

ephemeral publication file에는 localnet address와 absolute path처럼 local development environment에서만 관련 있는 정보가 들어 있으므로 source control에 commit하면 안 된다. Pub.*.toml.gitignore file에 추가하는 것을 권장한다.

publication file과 ephemeral publication file은 비슷하지만 서로 다른 정보를 담고 있다:

항목Persistent networks (Published.toml)Ephemeral networks (Pub.<env>.toml)
NetworksMainnet, TestnetLocalnet, Devnet
Contents여러분의 package address만 포함package와 dependency address 포함
Scope하나의 file에서 여러 networkfile당 하나의 network
Commit to source control다른 이들이 여러분의 package에 의존할 수 있으므로 예local development data를 포함하므로 아니오
Created bysui client publishsui client test-publish

Build environment 구성

패키지는 서로 다른 environment에서 서로 다른 dependency를 가질 수 있으므로 ephemeral publication을 위해 패키지를 build할 때는 "real" environment가 있어야 한다. 이 real environment를 build environment라고 하며 --build-env <env> flag로 지정한다.

--build-env <env>를 생략하면 build-env<file> 이름을 기본값으로 사용한다. 그 값도 없으면 system이 error를 낸다. build environment는 system이 패키지 dependency를 어떻게 resolve할지를 결정한다.

예를 들어 패키지의 testnet version을 localnet에 build하고 게시하고 싶다면 CLI의 active environment를 localnet으로 전환한 뒤 --build-env testnet과 함께 실행한다:

sui client env switch localnet
sui client test-publish --build-env testnet

Dependency 임시 publish

ephemeral publication file format은 main 패키지와 함께 dependency를 publish하기 쉽게 설계되어 있다. 이를 수행하는 방법은 manual 방식과 automatic 방식 두 가지가 있다.

dependency를 manual로 publish하려면 모든 dependency를 publish할 때 동일한 ephemeral publication file을 사용한다. 예를 들어 packages/apackages/b directory가 있고 ba에 의존한다고 가정하면 다음을 실행할 수 있다:

cd packages/a
sui client test-publish --build-env testnet --pubfile-path ../Pub.localnet.toml

cd ../b
sui client test-publish --build-env testnet --pubfile-path ../Pub.localnet.toml

a를 publish하면 packages/Pub.localnet.toml file이 a Localnet address entry로 업데이트된다. 그런 다음 b를 publish하면 a에서 packages/Pub.localnet.toml의 address를 가져오고 b Localnet address도 기록한다.

--publish-unpublished-deps command-line 인자를 사용하여 이 process를 automate할 수도 있다. 같은 예에서 다음을 실행할 수 있다:

cd packages/b
sui client test-publish --build-env testnet --publish-unpublished-deps`

이 명령은 a의 각 dependency를 fresh publication으로 만든 다음 a를 publish하고, 모든 address를 Pub.localnet.toml에 기록한다.

System은 ephemeral publication file의 entry를 source 필드로 식별한다. 이러한 필드는 pinned dependency이므로 manifest file에 작성된 dependency와 다를 수 있지만, lockfile의 source 필드와 일치해야 한다.

mvr에 패키지 등록

Package를 publish한 후에는 다른 사람이 쉽게 의존할 수 있도록 Move registry에 추가하는 것을 고려해야 한다. 자세한 내용은 Move registry documentation을 참조한다.