Technology, Tutorials, for Developer, Tool support

React.js와 Unmarshal SDK를 사용하여 Klaytn에서 NFT 컬렉션 갤러리 구축하기

들어가며

블록체인 네트워크에서 직접 데이터를 가져오고 처리하는 작업은 복잡하고 시간이 많이 소요될 수 있습니다. 블록체인 네트워크와의 직접적인 상호작용의 복잡성을 추상화한 실시간 서비스는 개발자와 엔터프라이즈 구축자가 선호하는 솔루션입니다. 이러한 서비스를 이용하면 개발자는 블록체인에서 데이터를 직접 가져오는 것에 대해 걱정할 필요 없이 사용 사례를 구축하는 데 더 많은 시간을 할애할 수 있습니다.

블록체인 데이터에 쉽게 액세스할 수 있는 프로토콜이나 서비스 중 하나가 바로 Unmarshal입니다. Unmarshal을 사용하면 Klaytn을 포함한 20개 이상의 체인에서 블록체인 데이터를 쉽게 쿼리할 수 있습니다. 이 튜토리얼에서는 Unmarshal과 그 제품군을 살펴보고, Unmarshal의 NFT/메타버스 API를 사용해 NFT 갤러리 컬렉션을 구축하는 방법에 대해 자세히 알아보겠습니다.

먼저, 최종 결과물은 아래와 같습니다.

전제 조건

Unmarshal 및 제품군 살펴보기

Unmarshal 개요

Unmarshal은 탈중앙화 애플리케이션(dApp)의 모든 요구사항을 충족하는 포괄적인 API를 위한 원스톱 솔루션으로, 정확하고 신뢰할 수 있는 블록체인 데이터로 dApp 개발자와 사용자에게 힘을 실어줍니다. 탈중앙화 금융(DeFi) 애플리케이션을 구축하려고 하나요? NFT의 세계를 탐구하고 있나요? 아니면 다양한 사용 사례를 살펴보고 있나요? 언마샬은 개발 프로세스를 가속화하고 블록체인 데이터의 잠재력을 최대한 활용하는 데 필요한 API를 제공합니다.

Unmarshal의 제품군에서는 아래와 같은 기능을 고려할 수 있습니다. 

 a. DeFi APIs: 이 API는 토큰 자산, 트랜잭션, 토큰 소유자 등에 대한 멀티체인 데이터를 가져오는 데 도움이 됩니다.
b. NFT/Metaverse APIs: 이 API는 지갑의 NFT 보유량과 트랜잭션을 쿼리하는 데 도움이 됩니다.
c. Notification Service: 언마샬 알림 서비스를 사용하면 여러 디바이스에서 사용자에게 원활하게 알림을 보낼 수 있습니다.

시작하기

이 튜토리얼에서는 언마샬 NFT API를 사용하여 지정된 컨트랙트 주소에 사용 가능한 모든 NFT를 표시하는 NFT 컬렉션 갤러리를 구축하겠습니다. 

React 프로젝트 설정 및 Unmarshal SDK 설치하기

이제 Unmarshal과 제품군에 익숙해진 만큼 구축을 시작할 수 있습니다! 이 섹션에서는 React 앱을 만들고 필요한 종속성을 설치합니다.

먼저 다음 명령을 실행하여 Vite + React 프로젝트 디렉토리를 생성해 보겠습니다.

npm create vite@latest my-nft-gallery -- --template react

프로젝트 디렉토리가 생성되면 내부로 이동하여 필요한 종속성을 설치합니다. 우리는 NFT 계약 주소가 유효한지 확인하기 위해 Ethers.js를 설치하고 TailwindCSS를 사용하여 프론트엔드를 예쁘게 만들어보죠!

cd my-nft-gallery
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
npm install ethers@5.7.2

다음은 React.js 앱에서 강력한 Unmarshal Server 백엔드에 액세스할 수 있는 라이브러리인 Unmarshal SDK를 설치하는 것입니다.

npm install @unmarshal/sdk

추가적으로, ‘tailwind.config.js’와 index.css 파일을 구성해야 합니다.

a.  코드 편집기를 열고 ‘tailwind.config.js’의 내용을 다음 코드로 바꿉니다:

/** @type {import('tailwindcss').Config} */
export default {
  content: [
    "./index.html",
    "./src/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

b. ‘index.css’의 내용을 다음 코드로 바꿉니다:

@tailwind base;

@tailwind components;

@tailwind utilities;

애플리케이션 빌드를 실시간으로 보려면 ‘npm run dev’를 실행합니다.

NFT 갤러리 구축

이 섹션에서는 NFT 데이터를 가져와 로드하고 표시하는 데 필요한 기능과 구성 요소를 구축합니다. 

먼저 src/App.jsx의 코드를 아래의 코드로 교체합니다.

import { useState } from "react";
import { Unmarshal, Chain } from "@unmarshal/sdk";
import { ethers } from "ethers";
import NFTDetails from "../components/NFTDetails";
import Pagination from "../components/Pagination";
const unmarshal = new Unmarshal({
  apiKey: "PASTE API KEY",
});
export default function App() {
  	const [nfts, setNFTs] = useState([]);
  	const [address, setAddress] = useState("");
	const [currentPage, setCurrentPage] = useState(1);
 	const [postPerPage] = useState(20);
	
const fetchNFTsByContractAddress = async (_address, _page) => {
    const res = await unmarshal.NFT.getContractTokenDetails(
      Chain.klaytn,
      _address,
      {page: _page, pageSize: postPerPage}
    );
    console.log(res.data);
    setNFTs(res.data.nft_token_details);
  };
  const handleNFTsByContractAddress = async (event) => {
    event.preventDefault();
    const _contractAddress = event.target.contractAddress.value;
    const resp = ethers.isAddress(_contractAddress);
    if (!resp) {
      alert("Pass a valid contract address");
    }
    setAddress(_contractAddress);
    console.log(_contractAddress, resp);
    fetchNFTsByContractAddress(_contractAddress, currentPage);
  };
  const paginate = (pageNumber) => {
    setCurrentPage(pageNumber)
    if(address) {
      fetchNFTsByContractAddress(address, currentPage);
    }
  }

  return (
    <>
    <h3 className="text-center m-5 font-semibold text-2xl">Klaytn-NFT-Collection-Gallery-Example (Unmarshal) </h3>
      <form
        onSubmit={handleNFTsByContractAddress}
        className="flex flex-wrap flex-row justify-items-center justify-center w-full m-auto"
      >
        <input
          type="text"
          placeholder="Check NFT By Contract Address: Enter a valid contract address"
          name="contractAddress"
          className="text-3xl font-bold rounded-md bg-black text-white m-3 p-5 w-3/4"
        />
      </form>
      <div className="flex flex-row flex-wrap gap-3 w-fit p-10 m-auto justify-between">
        {nfts &&
          nfts.map((item, index) => <NFTDetails key={index} item={item} />)}
      </div>
      { nfts.length > 0 && (<Pagination paginate={paginate}/>) }
    </>
  );
}

Code Walkthrough 

그러면, 위 코드의 기능에 대해 살펴보겠습니다.

Line1부터 시작해서 먼저 필요한 라이브러리와 컴포넌트를 가져왔습니다. 다음으로, NFT 컬렉션 갤러리 개발에 필수적인 네 개의 useState 변수를 만들었습니다. 그 중 하나는 NFT 데이터(예: 이름, 소유자, 토큰 ID, 특성 등)의 값을 보관하는 nfts state 변수입니다. address useState 상태 변수는 사용자가 검색하는 NFT 컨트랙트 주소를 추적하는 데 사용됩니다. 또한, 다른 두 개의 사용 상태 변수는 NFT 데이터를 쉽게 사용할 수 있을 때 표시할 currentPage와 postPerPage를 저장하기 위해 추가되었습니다.

다음으로, 우리는 Unmarshal NFT API의 unmarshal.NFT.getContractTokenDetails() 메서드를 사용하는 fetchNFTsByContractAddress 함수를 만들었습니다. 이 메서드는 chain(이 튜도리얼의 경우는 Klaytn), NFT contract address, PaginationQuery object ({page & pageSize}) 등 세 가지 파라미터를 받습니다. paginationQuery 객체에는 기본적으로 반환하고자 하는 페이지 번호(i.e., page)와 각 페이지에 반환하고자 하는 NFT의 수(i.e., pageSize)가 포함됩니다. 이 예제에서는 postPerPage 값을 20으로 설정하고 페이지를 1로 설정했습니다. 이 값은 자유롭게 수정할 수 있습니다. 마지막으로 이 함수가 호출되면 가져온 NFT 데이터를 nfts  변수에 설정합니다.

나아가,  return() 호출(JSX가 포함된)에서 h3(미니 제목이 포함된)와 양식 태그(NFT 컨트랙트 주소와 관련 이벤트 처리를 사용하는 검색 기능을 포함하는)를 선언했습니다. 검색 양식은 onSubmit 이벤트 핸들러에서 handleNFTsByContractAddress 함수를 받지만, 이 함수는 ethers.js를 사용하여 입력된 주소가 유효한지 확인하고 주소 변수에 NFT 컨트랙트 주소도 설정합니다.

단, 검색이 유효하면 응답의 각 NFT를 매핑하여 NFTDetails 컴포넌트에 매핑한다는 로직에 유의해야 한다는 것입니다. 이상적으로는 src 디렉터리 아래에 components라는 새 폴더를 생성하는 것이 좋습니다. 컴포넌트 폴더가 생성되면 그 안에 NFTDetails.jsxx라는 새 파일을 만들고 아래의 코드를 입력합니다.

import React from "react";

const NFTDetails = ({ item }) => {

  return (

    <div  className="p-5 bg-black text-white">

      <div className="flex flex-row gap-3 justify-between">

        <h1>{item.name}</h1>

        <p>{item.token_id}</p>

      </div>

      <p>{item.actual_owner}</p>

      <img src={item.image_url} alt="" width="400px" />

    </div>

  );

};

export default NFTDetails;

위의 코드는 NFT와 해당 메타데이터를 렌더링하는 NFTDetails 컴포넌트를 반환합니다. 

마지막으로, 페이지 매김 섹션을 렌더링하기 위해 다른 컴포넌트를 만들어야 합니다. 컴포넌트에Pagination.jsx라는 파일을 생성한 다음 다음 코드를 입력합니다.

import React from "react";
const Pagination = ({paginate}) => {
    const pageNumbers = [];
    
    for (let i = 1; i < 250; i++) {
        pageNumbers.push(i);
        
    }
    
    return (
        <nav className="w-4/4 m-auto mt-10">
            <ul className="flex flex-row gap-10 flex-wrap justify-center justify-items-center">
                {pageNumbers.map((number) => (
                    <li key={number} className="m-5"> 
                        <a onClick={() => paginate(number)} href="!#" className="bg-black text-white p-5">
                            {number}
                        </a>
                    </li>
                ))}
            </ul>
        </nav>
    )
}
export default Pagination

위의 코드는 아래의 내용을 수행합니다. 

  • 250(nft 데이터가 반환될 때 사용할 수 있는 총 페이지 수)을 반복하여 pageNumber 변수에 저장합니다. 
  • 반환() 호출(jsx가 포함된 호출)에서 페이지 번호 함수를 호출하는 onClick 이벤트 핸들러를 사용하여 <li></li>를 표시하도록 페이지 번호를 매핑합니다. 

이 시점에서 모든 지침을 올바르게 따랐다면 NFT 컨트랙트 주소를 붙여넣습니다. NFT 갤러리가 멋지게 표시되어야 합니다. 예를 들어, 다음 컨트랙트 주소를 붙여넣으세요:

벨리곰 월드 공식 컬렉션에 속하는 0xce70eef5adac126c37c8bc0c1228d48b70066d03입니다.

또한 이러한 추가 계약 주소를 사용하여 새로운 NFT 갤러리를 테스트할 수 있습니다.

  • Sunmiya Club Official : 0x8f5aa6b6dcd2d952a22920e8fe3f798471d0590
  • Meta Toy Dragonz: 0x46dbdc7965cf3cd2257c054feab941a05ff46488
  • Mutant Kongz & G.rilla Official: 0x3f635476023a6422478cf288ecaeb3fdcf025e9f

결론

Unmarshal SDK를 사용하여 NFT 갤러리를 구축해 보았습니다. 이 튜토리얼에서는 Unmarshal과 그 제품군, 그리고 가장 중요한 Klaytn(Cypress) NFT 컨트랙트를 위해 Unmarshal NFT API를 쿼리하고 React 앱에 표시하는 방법에 대해 알아봤습니다.

여기에서 각 NFT에 대해 특성과 트랜잭션 기록을 표시하는 새 페이지를 추가하는 것과 같은 다른 옵션도 NFT 갤러리에서 살펴볼 수 있습니다. 더 자세한 정보가 필요하시면 Klaytn Documentation Unmarshal Documentation를 참조하세요. 질문이 있으시다면 Klaytn Forum을 방문해주세요.