Solana web3.js v2와 Codama: Anchor IDL 기반의 SPL 토큰 파이프라인 전환 가이

삼코딩

@samcoding

Solana web3.js v2와 Codama: Anchor IDL 기반의 SPL 토큰 파이프라인 전환 가이드

Solana web3.js v2와 Codama: Anchor IDL 기반의 SPL 토큰 파이프라인 전환 가이드

솔라나 핵심 자바스크립트 SDK인 web3.js v2는 기존의 객체지향형 빌더에서 벗어나 순수 함수형 파이프라인 모델을 도입했습니다. 이 변화는 대대적인 번들 크기 감소와 성능 향상을 이끌어냈지만, 기존 앤커(Anchor) 프로그램 클라이언트 및 SPL 토큰 라이브러리와의 호환성 단절이라는 과제를 남겼습니다. 본 가이드에서는 새로운 함수형 파이프라인 환경에서 @solana-program/token 패키지를 사용해 토큰을 제어하고, 코다마(Codama)로 IDL에서 v2용 초경량 타입 안전 클라이언트를 생성하는 실무 패턴을 다룹니다.

SPL 토큰과 모듈형 명령어: @solana-program/token 도입하기

기존에 사용하던 @solana/spl-token 라이브러리는 무겁고 상태를 내포하는 클래스 기반 설계 때문에 web3.js v2의 새로운 순수 함수형 모델과 호환되지 않습니다. 대안으로 제공되는 @solana-program/token 혹은 @solana-program/token-2022 패키지는 번들러가 미사용 코드를 완전히 제거할 수 있도록 트리 셰이킹 최적화 환경을 제공합니다.

이 패키지를 사용하면 클래스 인스턴스를 무겁게 선언할 필요가 없습니다. 연관 토큰 계정 주소를 계산하는 findAssociatedTokenPda 같은 유틸리티나, 토큰 전송을 안전하게 실행하는 getTransferCheckedInstruction 같은 개별 모듈형 함수를 필요할 때만 가져와 호출하는 구조로 전환됩니다.

다음은 @solana-program/token 패키지에서 안전한 전송 명령어를 빌드하는 전형적인 자바스크립트 흐름입니다. BigInt 단위를 사용하여 고정 소수점 연산 오류를 방지하고, 명확히 선언된 주소 체계를 활용해 명령어를 구성합니다.

typescript
import { address } from '@solana/web3.js';
import { getTransferCheckedInstruction } from '@solana-program/token';

// 가상의 계정 주소 정의
const source = address('4z314cx6GMvLsaeN7G9S9nU8U4F8uQ9U7u8U7u8U7u8U');
const mint = address('EPjFW3dpC7EDD8G189eWY9GxXwj5E1bBN7e9pjd99X8w');
const destination = address('7u8U7u8U7u8U7u8U7u8U7u8U7u8U7u8U7u8U7u8U7u8U');
const authority = address('9u9U9u9U9u9U9u9U9u9U9u9U9u9U9u9U9u9U9u9U9u9U');

// BigInt를 사용한 transfer-checked 명령어 빌딩
const transferCheckedInstruction = getTransferCheckedInstruction({
    source,
    mint,
    destination,
    authority,
    amount: 100000000n, // 소수점 6자리 기준 100 토큰
    decimals: 6,
});

이처럼 구성된 명령어 객체는 web3.js v2의 순수 트랜잭션 메시지에 자유롭게 병합될 수 있어, 복잡한 다중 명령 트랜잭션을 설계할 때 유연성이 극대화됩니다.

Anchor IDL 통합: Codama를 통한 Modern v2 클라이언트 생성

기존 @coral-xyz/anchor 클라이언트는 구형 web3.js v1 구조에 결합되어 있어 v2의 순수 함수형 파이프라인에서 직접 호출할 수 없습니다. 이 단절을 극복하기 위해 솔라나 재단은 공식 IDL 표준 규격을 기반으로 하는 클라이언트 생성기인 코다마(Codama)를 제공합니다. 코다마는 기존 Anchor IDL 파일을 해석하여 web3.js v2 모델과 완벽하게 호환되는 초경량 TypeScript 클라이언트를 빌드해 줍니다.

코다마는 CLI 도구를 통해 프로젝트 환경에 맞게 쉽게 설정할 수 있습니다. 먼저 CLI 패키지를 설치한 뒤 초기화 명령을 실행합니다.

bash
# 코다마 CLI 설치
pnpm install @codama/cli

# 설정 파일 생성 및 대화형 초기화
pnpm codama init

초기화 과정이 완료되면 프로젝트 루트에 다음과 같은 codama.json 파일이 생성됩니다. 이 설정 파일에 Anchor IDL 경로와 출력 디렉터리를 명시합니다.

json
{
  "idl": "target/idl/my_program.json",
  "scripts": {
    "js": [
      {
        "from": "@codama/renderers-js",
        "args": ["clients/js/src"]
      }
    ]
  }
}

설정이 끝나면 렌더러를 구동하여 클라이언트 코드를 최종 빌드합니다.

bash
# 정의된 스크립트를 실행하여 v2용 TS 클라이언트 생성
pnpm codama run js

이렇게 빌드된 클라이언트는 기존의 무거운 클래스 기반 인스턴스 대신, 트리 셰이킹이 즉시 가능한 경량 비동기 명령어 빌더 함수들을 제공합니다. 예를 들어 getTakeOfferInstructionAsync 같은 비동기 헬퍼 함수는 PDA 계정 간의 복잡한 관계를 렌더링 시점에 내부적으로 자동 계산하여 web3.js v2가 이해하는 온체인 명령어로 변환해 줍니다. 이 덕분에 복잡한 비즈니스 로직을 가진 스마트 계약이라도 파이프라인 안에서 손쉽게 연동할 수 있습니다.

pipe()를 활용한 트랜잭션 결합 및 서명 워크플로우

수집한 SPL 토큰 명령어와 코다마로 자동 생성한 프로그램 명령어를 하나의 유기적인 트랜잭션으로 묶으려면 pipe 함수를 사용해야 합니다. Solana web3.js v2는 기존의 상태 전이식 빌더 모델 대신 순수 함수형 파이프라인 방식을 채택하여 모든 트랜잭션 가공 단계를 데이터의 불변 흐름으로 처리합니다.

createTransactionMessage로 빈 트랜잭션을 시작한 다음, 수수료 지불자와 블록해시 수명 주기를 순차적으로 설정하고 앞서 생성한 명령어 배열을 결합하는 흐름을 다음과 같이 작성할 수 있습니다.

typescript
import { 
  pipe, 
  createTransactionMessage, 
  setTransactionMessageFeePayerSigner, 
  setTransactionMessageLifetimeUsingBlockhash, 
  appendTransactionMessageInstructions, 
  signTransactionMessageWithSigners 
} from '@solana/web3.js';

// 1. 파이프라인을 통한 트랜잭션 메시지 구축
const transactionMessage = pipe(
  createTransactionMessage({ version: 0 }),
  (tx) => setTransactionMessageFeePayerSigner(feePayerSigner, tx),
  (tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
  (tx) => appendTransactionMessageInstructions([
    transferInstruction, // @solana-program/token에서 생성한 토큰 전송 명령어
    customProgramInstruction // 코다마 클라이언트로 빌드한 커스텀 명령어
  ], tx)
);

// 2. 완성된 트랜잭션 메시지에 서명 적용
const signedTransaction = await signTransactionMessageWithSigners(transactionMessage);

완성된 트랜잭션 메시지는 signTransactionMessageWithSigners를 거치며 즉시 전송이 가능한 형태로 전환됩니다. 이 함수는 파이프라인 내부에서 주입된 서명자 정보를 식별하여 필요한 서명을 일괄 적용합니다. 이처럼 함수형 컴포지션을 활용하면 불필요한 클래스 인스턴스 참조 없이 트랜잭션의 상태 변화를 안전하고 예측 가능하게 제어할 수 있습니다.

정리: 더 가볍고 유연해진 Solana 프론트엔드 설계

web3.js v2와 코다마의 조합은 단순히 문법을 바꾸는 것을 넘어, dApp의 성능과 개발자 경험을 동시에 개선하는 실질적인 설계 변화입니다. @solana-program/token을 활용한 트리 셰이킹과 코다마 기반의 IDL 파이프라인 자동화는 프론트엔드 번들 크기를 획기적으로 줄여주며 유지보수 부담을 최소화합니다. 이제 레거시 클라이언트의 제약에서 벗어나, 순수 함수형 파이프라인으로 더욱 가볍고 유연한 솔라나 프론트엔드 환경을 구축해 보시기 바랍니다.


참고 링크

No comments yet.