본문 바로가기

코인/코인 개발

ERC-721 (NFT, non-fungible token) 직접 만드는 방법

이번 포스팅에서는 NFT를 직접 만드는 방법을 간단한 예제를 사용해 설명해보려고 합니다. 예제를 단순히 따라 하는 것만으로도 스마트 컨트랙트의 구현 흐름을 이해하는 데 도움이 되리라 생각됩니다 (Metamask는 설치되어 있다고 가정하겠습니다.)

 

먼저 NFT로 만들 대상을 특정 이미지로 선정하고, 이미지를 IPFS에 올려서 보관합니다.

 

IPFS 설치 방법은 운영체제 별로 다르기에 문서를 확인해주시기 바랍니다. 이미 설치가 되어 있다면 이 부분은 지나가실 수 있습니다. 먼저 다음 명령어로 IPFS를 초기화해주고, 실행합니다.

$ ipfs init
generating ED25519 keypair...done
peer identity: 12D3KooWDPLoBZpCPXXuYBv9FsfA1sFWNphfSto4qAeXdWEATxAy
initializing IPFS node at /Users/coinali.me/.ipfs
$ ipfs daemon
Initializing daemon...
go-ipfs version: 0.9.1-dc2715af6
Repo version: 11
System version: amd64/darwin
Golang version: go1.16.6
Swarm listening on /ip4/127.0.0.1/tcp/4001
Swarm listening on /ip4/127.0.0.1/udp/4001/quic
Swarm listening on /ip4/192.168.1.153/tcp/4001
Swarm listening on /ip4/192.168.1.153/udp/4001/quic
Swarm listening on /ip6/::1/tcp/4001
Swarm listening on /ip6/::1/udp/4001/quic
Swarm listening on /p2p-circuit
Swarm announcing /ip4/127.0.0.1/tcp/4001
Swarm announcing /ip4/127.0.0.1/udp/4001/quic
Swarm announcing /ip4/141.156.151.199/udp/4001/quic
Swarm announcing /ip4/192.168.1.153/tcp/4001
Swarm announcing /ip4/192.168.1.153/udp/4001/quic
Swarm announcing /ip6/::1/tcp/4001
Swarm announcing /ip6/::1/udp/4001/quic
API server listening on /ip4/127.0.0.1/tcp/5001
WebUI: http://127.0.0.1:5001/webui
Gateway (readonly) server listening on /ip4/127.0.0.1/tcp/8080
Daemon is ready

 

그런 다음, 이미지를 IPFS에 추가합니다.

 

holden.png

 

$ ipfs add holden.png
added QmSFkPQ2BduvJbiEmLcZuYS7XLQPN4Rfe3etcJiJnToFcT holden.png

 

추가가 완료되고 나면 CID(Content Identifier, 이 경우에는 QmSFkPQ2BduvJbiEmLcZuYS7XLQPN4Rfe3etcJiJnToFcT)를 반환하는데 이 컨텐트는 https://ipfs.io/ipfs/QmSFkPQ2BduvJbiEmLcZuYS7XLQPN4Rfe3etcJiJnToFcT와 같이 "https://ipfs.io/ipfs/" 뒤에 붙여서 확인하실 수 있습니다. 

 

이제 해당 이미지에 대한 메타데이터를 다음과 같이 생성하고 마찬가지로 IPFS에 추가합니다.

{
    "name": "Holden",
    "description": "Holden the Puli",
    "image": "https://ipfs.io/ipfs/QmSFkPQ2BduvJbiEmLcZuYS7XLQPN4Rfe3etcJiJnToFcT"
}
$ ipfs add holden_metadata.json
added QmZuL8NLYdjogzocwiuepcpd9Z1qaaYcrnJ3QvWVujnGNL holden_metadata.json

 

이제 Remix IDE를 열어 다음 ERC721 스마트 컨트랙트를 다음과 같이 작성합니다.

// SPDX-License-Identifier: MIT
pragma solidity 0.8.6;
 
import "https://github.com/0xcert/ethereum-erc721/src/contracts/tokens/nf-token-metadata.sol";
import "https://github.com/0xcert/ethereum-erc721/src/contracts/ownership/ownable.sol";
 
contract ERC721 is NFTokenMetadata, Ownable {
 
  constructor() {
    nftName = "Holden the Puli";
    nftSymbol = "HTP";
  }
 
  function mint(address _to, uint256 _tokenId, string calldata _uri) external onlyOwner {
    super._mint(_to, _tokenId);
    super._setTokenUri(_tokenId, _uri);
  }
 
}

 

nftName과 nftSymbol은 원하는 대로 변경하시면 됩니다. 이제 다음과 같이 컴파일을 해주고 나면 배포할 준비가 됩니다.

 

Compile holden_nft.sol

 

 

Rinkeby 테스트 네트워크를 이용해서 배포해보도록 하겠습니다. 먼저 Rinkeby 테스트 네트워크에 발행에 필요한 ETH가 없다면 Rinkeby Faucet을 통해 얻을 수 있습니다. 얻는 방법은 단순히 트위터에 Metamask 주소를 트윗하고 해당 트윗 URL을 입력해 전달하면 됩니다.

 

Rinkeby Faucet. 출처: faucet.rinkeby.io

 

 

다시 Remix IDE로 돌아와서 다음과 같이 Injected Web3 주소를 사용해 배포(Deploy)합니다.

 

ERC721 스마트 컨트랙트 배포

 

네트워크에서 승인이 완료되면 mint 함수에 다음 매개변수를 전달해 NFT를 발행할 수 있습니다.

아까 IPFS에 등록했던 메타데이터의 주소를 ID 1로 등록해줍니다.

 

  • _to: 발행 대상 주소. (예: 0x5F455Fc973CECaC06c1e4Ca3a874C80BdBA5aA0C)
  • _tokenId: 토큰 ID. (예: 1)
  • _uri: 토큰 URI. (예: https://ipfs.io/ipfs/QmZuL8NLYdjogzocwiuepcpd9Z1qaaYcrnJ3QvWVujnGNL)

 

NFT 발행

 

해당 계약을 수행하고 나면 이제 네트워크에서 확인이 가능합니다.

 

발행 결과. Tx Hash: 0xd672f580967704f90f4a30d48b83d64c7831066fcb11c18de1f0364adc0a22ae
RInkeby Explorer에서 확인한 결과. 출처: rinkeby.etherscan.io

 

컨텐트를 어디에 보관할 것인가와 어떤 네트워크에 발행하느냐의 차이만 있을 뿐, NFT의 발행 방법에는 큰 차이는 없습니다.

궁금한 점은 댓글로 문의주세요.