NFT에 대하여

JiJay
11 min readFeb 13, 2022

최근 NFT에 대한 관심이 뜨겁다. 대표적인 NFT 마켓 플레이스인 Opensea는 현재 가장 많은 Gas를 소비하고 있으며(Etherscan 기준) NFT에 대한 관심이 많아졌던 2021년 여름부터 NFT 민팅을 빨리하기 위해서 Gas Price를 높임으로써 순간적으로 이더리움 네트워크 전반의 Gas Price가 높아지는 현상도 자주 발생했다. 즉, NFT에 대한 관심이 많아지면서 이더리움 네트워크의 혼잡도(Congestion)가 높아졌고 이로 인해 많은 수수료가 부과된 것이다.

또한, 이름을 들어본 웬만한 기업들에서는 NFT 관련 산업을 추진 중이거나 준비하고 있으며 어느 순간부터 NFT 관련 사업을 하지 않으면 구시대적인, Web2의 이미지를 갖게 되었다.(Web3는 무엇이며 존재하는가..?) 해외의 대표적인 NFT 프로젝트인 BAYC나 크립토 펑크에서는 그림 하나가 8000 ETH에 거래되기도 한다.

이렇게 NFT는 현재 우리 사회에서 가장 핫한 주제가 되어 개인들의 NFT에 대한 투자도 많아지고 있다. 걱정스러운 부분은 NFT라는 키워드만 있으면 일단 투자를 해보는 사람들이 많아지고 있다는 점이다. 이로 인해 러그풀(프로젝트를 중단하고 투자금을 들고 사라지는 사기)나 의미 없는 NFT로 인해 피해를 보는 사용자들도 다수 발생하고 있다. 한가지 알아야할 부분은 NFT가 기술적으로 뛰어나거나 특별한 무엇인가가 아니라는 점이다. 이번 글에서는 NFT 전반에 대해 설명함으로써 적어도 NFT가 무엇인지 알고 NFT 열풍에 참여하도록 하려 한다.

NFT란?

먼저, NFT의 정의에 대해 알아보자. NFT는 Non-fungible token의 줄임말로 직역하면 대체 불가능 토큰이다. NFT는 token이다. 즉, 우리가 일반적으로 거래소에서 거래하는 가상 화폐와 같은 토큰이다. 그렇다면 대체 불가능하다는 뜻은 무엇일까? 현실 세계에서 내가 가진 1만원과 독자가 가진 1만원은 차이가 없다. 즉, 대체가 가능하다. 내가 가진 1만원과 독자가 가진 1만원을 교환하든 말든 편의점에서는 같은 1만원의 가치의 상품을 제공할 것이다. 나의 1만원은 독자의 1만원으로 대체가 가능하다. 대체 불가능은 위 상황의 반대로 생각하면 된다. 내가 가진 NFT는 독자가 가진 NFT로 대체가 불가능하며 각 NFT에 대한 소유권을 확인할 수 있다. 예를 들어, 같은 1만원이라도 각 지폐의 일렬번호는 다르며 고유 번호이다. 일렬번호를 활용하는 세상이라면 내가 가진 1만원은 독자가 가진 1만원으로 대체가 불가능하다.

NFT의 정의에서 알 수 있듯이 NFT는 소유권을 확일할 수 있는 토큰이다. 내가 가진 NFT는 해당 NFT를 발행한 체인에서 유일하며 대체 불가능하다. 디지털에서 유일하다는 것은 언뜻 보기엔 모순적으로 보인다. 디지털의 특성 자체가 비트(bit)들의 모임(=데이터)을 쉽게 복제가 가능하다는 점이기 때문이다. 따라서, NFT는 디지털 세상에서 희소성을 인정 받을 수 있는 기술이며 자연스럽게 희소성이 중요한 예술 시장에서 많이 사용되기 시작했다. 또한, NFT는 블록체인 기술이 사용 되기 때문에 이더리움과 같이 안전한 체인에서는 해킹이 위험도 거의 없다. 디지털 세상에서, 안전하게 소유권을 주장할 수 있으며 희소성을 인정 받을 수 있다는 특징 덕분에 NFT는 많은 관심을 받게 되었다.

NFT의 원리

그렇다면 NFT의 원리는 무엇일까? 정말 간단하다. 0번 토큰을 하나만 발행하며 이후에는 1번, 2번, … 식으로 유니크한 값을 사용하여 각 토큰의 소유자를 저장하는 방식이다. 위에서 0번, 1번의 값을 tokenId라고 한다. 즉, tokenId가 unique한 값이며 각 tokenId 별로 소유자가 정해진다.

function mint(address to) {  // tokenId가 고유한 값인지 확인
require(!_exists(tokenId), "ERC721: token already minted");
// 고유한 tokenId의 소유자를 저장
_owners[tokenId] = to;
// tokenId를 1 증가
tokenId = tokenId + 1;
}

위 코드는 NFT를 민팅(주조)하는 Pseudocode이다. 간단히 살펴보면 tokenId가 고유한지 확인하고 고유하다면 해당 tokenId의 소유자를 저장하고 tokenId를 1 증가시킨다. 사실상 위 코드가 NFT의 전부다. NFT는 결국 고유한 tokenId에 맞게 발행되는 토큰인 것이다. 이후 10번 토큰에 대한 소유자를 조회한다면 딱 하나의 주소가 나올 것이며(한명) 이 주소가 10번 토큰에 대한 소유자 인 것이다.

여기서 중요한 점은 위 코드에 이미지나 특성들이 들어가있지 않다는 점이다. NFT의 본질은 고유한 tokenId별로 발급되는 토큰이지 이미지나 특성을 저장하기 위한 토큰이 아니라는 것이다. 만약, 루브르 박물관에서 X 주소의 컨트랙의 0번 토큰의 소유자가 모나리자의 소유자라고 발표한다면 위 코드로 충분히 가능하다. 굳이, 모나리자 그림을 NFT에 넣지 않아도(애초에 불가능하다) 모나리자 그림의 소유자를 확인할 수 있는 것이다. 따라서, Opensea에서 흔히 보는 이미지나 특성은 NFT의 본질이 아니다. 다만, 현재 NFT의 표준은 이미지와 특성들을 포함한 메타데이터가 호스팅된 URI를 컨트랙 안에 포함시킬 수 있어 Opensea 같은 마켓 플레이스나 메타마스크 같은 지갑에서 해당 NFT의 이미지나 특성을 불러올 수 있는 것이다.

이미지 자체를 NFT에 넣지 못하는 이유는 아직 이더리움의 블록 크기가 80k정도로 이미지를 저장하기 충분하지 못하기 때문이다.

NFT는 이미지를 보거나 사용하기 위한 기술이 아닌 소유권을 확인할 수 있는 대체 불가능한 토큰이다.

NFT의 표준

ERC721

이더리움에서 NFT의 표준은 ERC 721이다. EIP 721Openzepplin에서 코드 및 인터페이스를 확인할 수 있다. 핵심적인 로직은 위에서 언급했지만 tokenId가 고유한 값이여야하며 각 tokenId 별로 소유자를 기록한다는 것이다. 오프 체인에서 NFT를 사용하기 위해서는 tokenId 별로 metadata를 불러와야하는데 이때 사용하는 함수가 tokenURI이다. tokenURI은 metadata json 파일이 호스팅 된 HTTP 또는 IPFS URL을 반환해야하며 Opensea 같은 마켓플레이스는 이 URL를 통해 JSON 파일을 받아 화면에 보여주는 것이다. tokenId는 baseUrl를 설정해서 prefix로 사용하고 tokenId를 id처럼 사용해도 되고 ERC721URIStorage를 상속받아 tokenId별로 tokenURI를 설정해도 된다.

https://docs.opensea.io/docs/metadata-standards

위 사진은 오픈시에서 지원하는 메타데이터의 형식인데 해당 형식에 맞게 파일을 호스팅하고 호스팅 된 주소를 컨트랙에 잘 넣으면 Opensea에서 데이터를 불러 올 수 있다. 위 예제에서는 google api를 사용한 것으로 보이는데 AWS S3나 github의 정적 파일 호스팅 기능이나 Pinata와 같은 IPFS를 사용해도 된다. 자세한 내용은 Opensea 개발자 사이트에 자세히 나와있다.

ERC1155

ERC 1155는 ERC 20과 ERC 721 사이에 있는 표준이라고 생각하면 편하다. 즉, 대체 가능한 토큰과 대체 불가능한 토큰 모두 지원한다는 뜻이다. 기존에는 ERC 721 컨트랙을 배포하여 NFT로 사용하고 대체 가능한 토큰을 발행하려면 새로운 컨트랙을 배포해야했다. NFT 1155는 하나의 컨트랙으로 두가지 모두 발행 및 관리가 가능하다. 이로 인해 가스비를 아낄 수 있고 관리의 복잡도를 낮출 수 있다.

ERC 1155는 하나의 컨트랙으로 여러 토큰들을 관리하기 때문에 각 토큰들을 구별하는 id가 존재한다. 이때 id는 토큰의 종류를 나타내는 id로 balanceOf 함수를 호출할 때도 어떤 토큰의 잔고인지 알아야되기 때문에 id를 인자로 넘긴다.

balanceOf(address account, uint256 id)

주의할 점은 이때의 id는 ERC 721의 id와는 다르다. 애초에 ERC 721에서는 토큰이 한 종류이며 대체 불가능하기 때문에 balance는 1일 수 밖에 없다.

ERC 721에서 balanceOf 함수는 해당 주소가 가지는 다른 토큰들의 개수다. 0번 토큰 한개, 2번 토큰 한개가 있다면 balanceOf는 2를 반환한다.

반면, ERC 1155에서는 id별로 다른 balance를 가질 수 있으며 총 balance가 1인 id는 곧 NFT가 된다.

https://docs.openzeppelin.com/contracts/3.x/erc1155

다음은 Openzepplin에 나와있는 ERC 1155의 예시다. 예시에 나와있듯이 ERC 1155는 게임에서 다양한 아이템들을 나타내는데도 사용된다. 만약, ERC 1155를 사용하지 않는다면 각 아이템별로 컨트랙을 배포해야 됐을 것이다.

위 예제에서 THORS_HAMMER 토큰(id : 2)는 1개가 mint 되었기 때문에 자동으로 NFT가 된다.

ERC 721과 마찬가지로 메타데이터가 호스팅 된 URI를 컨트랙에 넣을 수 있는데 uri 함수를 통해 조회할 수 있으며 오픈시에서도 ERC 1155의 uri 함수를 통해 이미지 및 특성을 불러온다. 위 예제에서 uri은 https://game.example/api/item/{id}.json인데 {id}에 토큰의 id를 0으로 padding된 0x가 없는 lowercase hexadecimal 형식으로 변환하고 넣으면 호스팅 된 주소가 되어야한다. 즉, id를 lowercase hexadecimal로 변환하고 64자리에서 부족한 부분은 0으로 채우는 것이다. 예를 들어 id가 57라면 0000000000000000000000000000000000000000000000000000000000000039로 변환되어 https://game.example/api/item/0000000000000000000000000000000000000000000000000000000000000039.json에 메타데이타가 호스팅 되어 있어야한다.

메타데이터 형식은 세부적으로는 조금씩 다르나 Opensea의 ERC 721의 메타데이터 형식을 사용해도 무방하다.

ERC 1155를 사용할 경우 메타데이터를 호스팅 할 때 위 규칙에 맞게 호스팅하는 것이 중요하다.

ERC 1155는 이외에도 다양한 토큰들을 하나의 컨트랙에서 관리할 수 있어 여러개의 잔고를 한번에 확인하거나 전송할 수 있어 가스비를 아낄 수 있고 보안 토큰 전송 기능이 추가되어 사용자가 토큰을 잘못된 주소로 보내지 않도록 도와준다.

ERC 721, ERC 1155 모두 NFT의 표준으로 간주되기 때문에 어떤 표준을 쓰더라도 큰 상관은 없다. 다만, ERC 1155는 ERC 721보다 더 많은 기능이 있기 때문에 큰 이유가 없다면 ERC 1155를 사용하는 것을 추천한다.

클레이튼에서의 NFT

클레이튼에서는 NFT 관련해서 KIP 17이라는 별도의 표준이 존재한다. KIP 17은 ERC 721에서 파생되었으며 다양한 확장 옵션들을 제공한다. 다만, EVM 호환이 되기 때문에 ERC 721, ERC 1155을 이더리움에서처럼 사용이 가능하다. 주의할 점은 클레이튼의 지갑이나 마켓 플레이스가 KIP 17 표준을 따른다면 NFT의 이미지나 특성이 안보일 수 있다. 그럴 경우 KIP 17 표준에 맞게 개발하거나 KIP 17의 인터페이스에 맞게 함수나 변수를 수정해야한다.

마무리

글을 작성하다보니 개발쪽으로 너무 치우친 것 같다. 개발을 모르는 분들은 코드 관련된 부분은 무시하셔도 좋다. 중요한 것은 NFT가 어떤 개념이고 어떤 특성 때문에 현실 세계에서 사용되고 있는지를 파악하는 것이다. 코드는 그러한 개념과 특성을 컴퓨터 언어로 변환한 것 뿐이다. NFT에 대해 정리하면 아래와 같다.

  1. NFT는 소유권이 확인 가능한 대체 불가능한 토큰이다.
  2. NFT는 예술 작품이나 그림을 위한 것은 아니라 디지털 세계에서 안전하게 소유권을 확인할 수 있는 특성 때문에 예술 시장에서 많이 사용되고 있다.
  3. 이더리움에서 NFT의 표준에는 ERC 721과 ERC 1155가 있으며 클레이튼에서도 사용 가능하다. 단, 지갑이나 마켓 플레이스와의 호환성을 검토해야한다.
  4. 이더리움 블록 크기 제한 때문에 NFT 자체에 이미지를 넣을 순 없다. NFT에 메타데이터가 호스팅 된 URI를 넣어 클라이언트(지갑, 사이트)에서 데이터를 불러올 수 있게 한다.

앞으로 더 많은 기업들이 NFT에 참여하고 다양한 NFT 프로젝트들이 나올 것이다. NFT에 대한 확실한 이해를 바탕으로 앞으로 나올 무수히 많은 서비스와 프로젝트에 대해 본인만의 판단을 내리고 투자를 하길 바란다.

실제 NFT를 작성하고 배포하는 과정은 이후 포스팅에서 다룰 예정이다. 이더리움 공식 홈페이지에 잘 설명되어 있으니 참고하길 바란다.

Reference

잘못된 내용이 있다면 댓글로 알려주시길 바랍니다.

--

--