신규: Helius가 Light Protocol을 인수했습니다
Gill로 Solana 스마트 컨트랙트 개발하기
블로그/개발

Gill로 Solana 앱을 구축하는 방법

@useDecal 개발 중, 전 @SolanaFndnX의 Nick FrostbutterLinkedIn의 Nick Frostbutter
읽는 데 9분

Gill은 최신 JavaScript/TypeScript 기반 Solana 개발 도구 라이브러리입니다. Decal의 공동 창립자 Nick Frostbutter가 Solana Foundation 개발자 관계 팀에서 근무할 때 처음 개발했습니다. Gill은 JavaScript 기반 애플리케이션의 개발자 경험을 크게 개선하는 것을 목표로 합니다.

Gill은 개발 생산성을 높이는 적절한 수준의 추상화와 저수준 프리미티브를 모두 제공합니다. 개발자는 원하는 접근 방식을 유연하게 선택할 수 있습니다.

경량 추상화는 Solana와 흔히 상호작용할 때 필요한 복잡성과 반복 코드를 크게 줄입니다. 저수준 프리미티브는 애플리케이션 로직을 더 세밀하게 제어해야 하거나 원하는 개발자에게 "탈출구"를 제공합니다.

이 글에서는 "Gill 라이브러리"의 기본 개념과 포함된 기능, gill 시작 방법, @solana/kit(이전 명칭 "web3.js v2")와의 차이점을 살펴봅니다.

Gill이란?

Gill은 브라우저, 서버, 모바일 등 모든 JavaScript 기반 환경에서 Solana 애플리케이션을 개발할 수 있는 현대적인 TypeScript 라이브러리입니다.

Gill 라이브러리는 초급자부터 고급 사용자까지 모든 수준의 Solana 개발자를 위해 설계되었습니다. 고수준 추상화와 저수준 프리미티브를 하나의 패키지로 제공하므로, 추상화가 지원하지 않거나 더 고급 기능이 필요할 때 쉽게 활용할 수 있습니다. 

가장 큰 장점은 무엇일까요? 

Gill은 완전한 트리 셰이킹을 지원합니다. 번들러가 코드베이스에서 사용하지 않는 프리미티브와 추상화를 자동으로 제거합니다.

Gill의 핵심 목표는 개발자 경험을 개선하는 것입니다. 일반적인 Solana 개발 작업을 단순화하고 반복 코드를 제거하면서도, 개발자가 원하거나 필요할 때 저수준 기능을 사용할 수 있도록 합니다. 개발자가 고수준 추상화나 저수준 프리미티브 중 하나에만 제한되어서는 안 됩니다. 상황에 맞는 방식을 쉽게 선택할 수 있어야 합니다.

Gill 설치하기

Gill은 NodeJS/Bun, 브라우저, React Native를 비롯해 거의 모든 JavaScript 환경의 JavaScript 또는 TypeScript 기반 프로젝트에 설치할 수 있습니다.

코드
npm install gill

Gill 라이브러리는 TypeScript를 강력하게 지원하며 대부분의 애플리케이션에서 별도 설정 없이 작동합니다. 다만 프로젝트별 구성에 따라 Gill과 더 원활하게 작동하도록 조정해야 할 수 있습니다. 자세한 내용은 Gill의 TypeScript 지원 문서를 확인하세요.

Gill과 @solana/kit 비교

Gill 라이브러리는 @solana/kit 위에 직접 구축되었습니다. 이는 기존 @solana/web3.js를 더 높은 성능으로 대체하기 위해 Anza가 개발한 새로운 저수준 JavaScript 프리미티브입니다.

Kit은 이러한 저수준 프리미티브만 제공합니다. 따라서 개발자는 모든 것을 수동으로 구성해야 하며, 장황한 반복 코드로 애플리케이션이 불필요하게 커집니다.

여기서 Gill이 등장합니다.

Gill은 Kit과 동일한 저수준 프리미티브와 일반적인 작업을 간소화하는 적절한 수준의 추상화를 호환 가능한 단일 인터페이스로 제공합니다. Gill로 전반적인 작업을 단순화하면 장황한 반복 코드 대신 애플리케이션의 비즈니스 로직에 더 집중할 수 있습니다.

Gill과 Kit 코드 예제 비교

다음 코드 스니펫은 동일한 기능을 유지하면서 코드를 간소화하는 방법을 보여줍니다. 경우에 따라 기능을 더 추가할 수도 있습니다. 거의 모든 애플리케이션은 블록체인 연결 설정과 트랜잭션 생성이라는 두 가지 작업을 수행해야 합니다.

@solana/kit로 블록체인 연결을 생성하는 방법은 다음과 같습니다.

코드
import {
  devnet,
  createSolanaRpc,
  createSolanaRpcSubscriptions,
  sendAndConfirmTransactionFactory,
} from "@solana/kit";

const rpc = createSolanaRpc(devnet("https://api.devnet.solana.com"));

const rpcSubscriptions = createSolanaRpcSubscriptions(
  devnet("wss://api.devnet.solana.com"),
);

const sendAndConfirmTransaction = sendAndConfirmTransactionFactory({
  rpc,
  rpcSubscriptions,
});

Gill의 createSolanaClient 함수를 사용하면 같은 로직을 더 간단하게 구현할 수 있습니다.

코드
import { createSolanaClient } from "gill";

const { rpc, rpcSubscriptions, sendAndConfirmTransaction } = createSolanaClient({
  urlOrMoniker: "devnet",
});

이제 위 예제에서 두 라이브러리 중 하나로 생성한 rpc 객체를 사용해 간단한 RPC 요청을 보낼 수 있습니다.

코드
// get the latest blockhash from your RPC provider
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();

@solana/kit에서 기본 최적화(컴퓨트 버짓 명령어 사용)를 적용하고 메모 명령어를 포함하는 간단한 트랜잭션을 생성하는 방법은 다음과 같습니다.

코드
import {
  pipe,
  createTransactionMessage,
  setTransactionMessageFeePayerSigner,
  appendTransactionMessageInstructions,
  setTransactionMessageLifetimeUsingBlockhash,
} from "@solana/kit";
import { getAddMemoInstruction } from "@solana-program/memo";
import {
  getSetComputeUnitLimitInstruction,
  getSetComputeUnitPriceInstruction,
} from "@solana-program/compute-budget";

const transaction = pipe(
  createTransactionMessage({ version: "legacy" }),
  (tx) => setTransactionMessageFeePayerSigner(signer, tx),
  (tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
  (tx) =>
    appendTransactionMessageInstructions(
      [
        getAddMemoInstruction({
          memo: "gm world!",
        }),
        getSetComputeUnitLimitInstruction({ units: 5000 }),
        getSetComputeUnitPriceInstruction({ microLamports: 1000 }),
      ],
      tx,
    ),
);

gill를 사용하면 같은 로직을 다음과 같이 크게 단순화할 수 있습니다.

코드
import { createTransaction } from "gill";
import { getAddMemoInstruction } from "gill/programs";

const transaction = createTransaction({
  version: "legacy",
  feePayer: signer,
  instructions: [
    getAddMemoInstruction({
      memo: "gm world!",
    }),
  ],
  latestBlockhash,
  computeUnitLimit: 5000,
  computeUnitPrice: 1000,
});

두 라이브러리를 더 자세히 비교하려면 Gill 문서의 Gill과 @solana/kit 비교를 확인하세요.

Kit에서 Gill로 마이그레이션하려면 무엇이 필요한가요?

@solana/kit 라이브러리를 사용하는 애플리케이션은 매우 간단하게 gill 패키지로 마이그레이션할 수 있습니다.

  1. gill 설치
  2. 모든 @solana/kit import를 gill로 교체
  3. @solana/kit 제거

Gill에는 가장 일반적인 Solana Program Library(SPL) 클라이언트도 직접 포함되어 있으므로 해당 패키지 import 역시 Gill로 교체할 수 있습니다. Gill은 gill/programs import 경로에서 바로 사용할 수 있는 다음 SPL 클라이언트를 포함합니다.

  • @solana-program/system
  • @solana-program/memo
  • @solana-program/compute-budget
  • @solana-program/address-lookup-table
  • @solana-program/token-2022(토큰 프로그램 클라이언트에 관한 아래 참고 사항 확인)

이러한 SPL 프로그램 클라이언트에 단일 gill 패키지를 사용하려면 다음 단계를 따르세요.

  1. 위에 나열된 @solana-program/* 패키지 import를 gill/programs로 교체
  2. 위에 나열된 @solana-program/* 패키지 제거

import를 업데이트하면 애플리케이션에서 즉시 "Gill Core" 라이브러리를 사용할 수 있습니다. 이제 사용 가능한 gill 추상화를 활용해 블록체인 연결 및 트랜잭션 생성 같은 장황한 Kit 반복 코드를 손쉽게 리팩터링할 수 있습니다.

Gill에는 어떤 구성 요소가 포함되나요?

Gill 라이브러리는 몇 가지 핵심 구성 요소로 나뉩니다.

  • 핵심 기능("Gill Core"라고도 함)
  • 서버 런타임 전용 헬퍼(예: NodeJS 및 Bun)
  • 프로그램 클라이언트
  • 트랜잭션 빌더
  • 디버그 모드

Node.js 헬퍼 함수

gill 패키지에는 JavaScript 서버 런타임 전용 유틸리티가 여러 개 포함되어 있습니다. gill 패키지에 포함되지만 트리 셰이킹을 개선하기 위해 별도의 import 경로를 사용합니다. 이러한 유틸리티를 사용하면 키페어를 파일이나 ENV 변수에서 쉽게 불러오고 저장할 수 있습니다.

코드
import { ... } from "gill/node"

로컬 파일 시스템에서 키페어 파일을 쉽게 불러오는 방법은 다음과 같습니다. Solana CLI 키페어도 같은 방식으로 불러올 수 있습니다.

코드
import { loadKeypairSignerFromFile } from "gill/node";

// default file path: ~/.config/solana/id.json
const signer = await loadKeypairSignerFromFile();
console.log("address:", signer.address);

ENV 변수에서 base58로 인코딩된 키페어를 불러올 수도 있습니다.

코드
import { loadKeypairSignerFromEnvironmentBase58 } from "gill/node";

// loads signer from base58 keypair stored at `process.env[variableName]`
const signer = await loadKeypairSignerFromEnvironmentBase58(variableName);
console.log("address:", signer.address);

트랜잭션 빌더

Gill은 여러 프로그램과 동시에 상호작용하는 일반적인 트랜잭션을 쉽게 생성할 수 있도록 다양한 "트랜잭션 빌더"를 제공합니다. 이러한 작업에 필요한 서명 준비 완료 트랜잭션을 간편하게 구성할 수 있습니다.

각 트랜잭션 빌더는 하나의 작업에만 초점을 맞춥니다. 따라서 여러 반복 코드를 손쉽게 추상화하면서 최적화된 트랜잭션을 생성할 수 있습니다.

Gill이 제공하는 트랜잭션 빌더의 예시는 다음과 같습니다.

  • buildCreateTokenTransaction - 메타데이터가 있는 토큰 생성
  • buildMintTokensTransaction - 대상 지갑으로 토큰 민팅
  • buildTransferTokensTransaction - 대상 지갑으로 토큰 전송

각 트랜잭션 빌더에는 Gill 추상화의 개발 유연성을 높이는 "명령어 빌더"가 함께 제공됩니다.

디버그 모드

Gill에서 "디버그 모드"를 활성화하면 트랜잭션 문제 해결에 도움이 되는 추가 정보를 자동으로 기록할 수 있습니다.

애플리케이션의 불필요한 로그를 최소화하기 위해 디버그 모드는 기본적으로 비활성화되어 있습니다. 유연한 컨트롤러를 통해 코드 자체, NodeJS 백엔드, 서버리스 함수, 웹 브라우저 콘솔 등 코드가 실행되는 대부분의 환경에서 디버그 모드를 활성화할 수 있습니다.

디버그 모드를 활성화하려면 다음 중 하나를 true 또는 1로 설정하세요.

  • process.env.GILL_DEBUG
  • global.__GILL_DEBUG__
  • window.__GILL_DEBUG__(예: 웹 브라우저 콘솔에서 설정)
  • 또는 원하는 디버그 로그 수준을 수동으로 설정(문서 참고)

자세한 내용은 Gill 디버그 모드 문서를 확인하세요.

Gill 개발을 지원하는 도구

@gillsdk/react

Gill 라이브러리에는 또 다른 패키지인 @gillsdk/react가 포함되어 있습니다. React 기반 프런트엔드 애플리케이션의 개발자 경험을 크게 개선하도록 설계된 React 훅 모음입니다. 인기 있는 반응성 라이브러리 TanStack Query 위에 구축되어 기존 애플리케이션에서도 더 쉽게 활용할 수 있습니다.

@gillsdk/react 패키지는 아직 초기 단계이며 활발히 개발되고 있습니다. 현재 Solana 애플리케이션에 유용한 여러 React 훅을 제공합니다.

  • useAccount - 주소의 계정 정보 가져오기
  • useBalance - 계정 잔액 가져오기(단위: lamports)
  • useLatestBlockhash - 최신 블록해시 가져오기
  • useSignatureStatuses - 서명 상태 가져오기
  • useProgramAccounts - 프로그램 계정(GPA) 가져오기
  • useTokenMint - 디코딩된 토큰의 Mint 계정 가져오기
  • useTokenAccount - 지정된 Mint와 소유자(또는 ATA)의 토큰 계정 가져오기

Codama

Codama는 Solana 프로그램의 IDL을 바탕으로 다른 애플리케이션에서 사용할 클라이언트 라이브러리(예: JavaScript, Rust)를 생성하는 도구입니다. Codama는 Solana 명령어를 구성하는 모든 복잡한 과정을 IDL, 구성 파일, 함수 import로 처리합니다.

Gill의 createCodamaConfig 함수를 사용하면 Gill과 Codama를 손쉽게 통합할 수 있습니다. Gill 유지관리자는 Codama CLI의 직접 지원을 포함해 Gill<>Codama 통합을 더욱 개선하기 위해 적극적으로 작업하고 있습니다.

Codama가 생성한 TypeScript 프로그램 클라이언트는 기본적으로 @solana/kit를 사용하지만, Solana 프로그램의 Codama 구성 파일에서 쉽게 변경할 수 있습니다. createCodamaConfig 함수를 사용하면 Codama 구성에서 gill로 간단하게 업그레이드할 수 있습니다.

다음은 gill를 사용하는 Solana 프로그램 TypeScript 클라이언트를 생성하는 codama.js 파일의 예시입니다.

코드
import { createCodamaConfig } from "gill";

export default createCodamaConfig({
  idl: "program/idl.json",
  clientJs: "clients/js/src/generated",
});

Codama로 Solana 프로그램 클라이언트 생성하기에 대한 전체 가이드는 Gill 문서에서 확인할 수 있습니다.

Gill의 미래

Gill 라이브러리의 미래는 밝으며 앞으로 할 일이 많습니다. 공식 Gill 문서 사이트가 막 출시되었고, 라이브러리의 월간 다운로드 수는 20,000회에 가까워지고 있습니다.

현재 Gill 로드맵에 포함된 자세한 내용은 GitHub Projects 페이지에서 확인할 수 있습니다. 현재 주요 계획은 다음과 같습니다.

  • Solana Pay 사양 직접 지원
  • Digital Assets Standard(DAS) API 사양 네이티브 통합
  • Token Extension 기반 토큰 지원 개선
  • Address Lookup Tables 지원 개선
  • 더 포괄적인 문서

Gill 라이브러리에 포함된 @gillsdk/react 패키지는 아직 초기 단계이며 서로 다른 9개의 React 훅을 제공합니다. 일반적인 모든 Solana RPC 메서드 지원과 wallet-ui와의 긴밀한 통합을 포함해, 개발자가 React 기반 애플리케이션에 반응성을 쉽게 추가할 수 있도록 계속 확장되고 있습니다.

흥미로운 사실이 있습니다. 개발자가 애플리케이션에서 Gill의 최적화와 개발자 경험 개선 사항을 더 쉽게 활용할 수 있도록 Gill을 Anchor 프레임워크에 직접 통합할 계획입니다. 어쩌면 Gill이 Anchor v2의 기본값이 될 수도 있습니다. :shhh:

Gill에 기여하는 방법

Gill 라이브러리는 오픈 소스(MIT 라이선스)이며 기여자를 환영합니다. 라이브러리 기여에 관심이 있다면 열려 있는 이슈를 살펴보고 직접 해결해 보세요.

새로운 기능이나 개선 사항을 제안하려면 PR 코드를 작성하기 전에 먼저 이슈를 열어 유지관리자와 논의를 시작하세요.

추가 리소스

다음 링크에서 Gill에 관한 자세한 정보와 리소스를 확인하세요.

Helius 구독하기

최신 Solana 개발 소식을 확인하고 새 게시물 알림을 받아보세요