Klaytn을 이용하여 NFT 활용하기: 발행부터 판매까지
11월 16일부터 3일간 온라인으로 진행된 카카오 개발자 컨퍼런스 if(kakao)2021가 올해도 성황리에 막을 내렸습니다. GroundX에서도 많은 개발자 분들이 참여해 다양한 서비스와 기술에 대한 지식을 공유해주셨습니다. 오늘 포스팅에서는 GroundX Klip Drops 개발 팀장 Colin이 소개해주신 NFT를 사고 팔 수 있는 마켓 플레이스를 구현하는 내용을 살펴보겠습니다.
최근 NFT의 부상과 함께 디지털 아트가 큰 주목을 받고 있습니다. 블록체인 기술을 기반으로 각 작품의 진위여부와 희소성이 확실하게 증명될 수 있고, 거래 내역 또한 안전하게 기록되기 때문입니다.
하지만 무엇보다 중요한 것은 창작자의 입장에서도 기존 갤러리에 지불했던 막대한 중개료를 부담할 필요없이 직접 판매를 통해 정당한 수익을 얻을 수 있다는 점으로, 문화 산업적으로도 긍정적인 함의를 지닙니다. 게다가 작품의 최초 거래 후 재판매 시에도 판매액의 일정 비율을 창작자가 청구할 수 있도록 하는 이른바 “추급권”도 적용되는 추세로, 예술 창작자들에 대한 대우가 점점 개선될 것이라 기대되고 있습니다.
그렇다면 서비스를 개발하는 입장에서 중요하게 고려해야 할 것은 무엇일까요? NFT의 발행, 전송, 판매, 전시 등이 있을 텐데요, 오늘은 이중 핵심이라고 할 수 있는 추급권과 NFT 마켓플레이스 구현에 대해 자세히 알아보겠습니다.
추급권 구현
앞서 언급했듯, 추급권은 작품의 재판매 시 판매액의 일정 비율이 원창작자에게 돌아가도록 해주는 권리입니다. 대부분의 NFT 마켓플레이스에서 구현되고 있는 기능이지만, 표준화가 이루어지지 않았기 때문에 다른 마켓플레이스 간 호환이 되지 않습니다. 이에 따라 호환 가능한 추급권 표준 구현을 위해 2021년 7월 이더리움의 ERC-2981이 발표된 바 있습니다.
이 표준을 살펴보면, 토큰 ID(tokenID)와 판매 가격(salePrice)을 파라미터로 전달했을 때 추급권자의 주소(receiver)와 지급 금액(royaltyAmount)이 반환되는, 최소한의 스펙만 구현한 미니멀리스트 형식임을 볼 수 있습니다.
따라서 추급권자 수가 한 명으로 한정되어 있고, 추급권이 적용되지 않은 기존 NFT는 어떻게 취급할 것인지 다루고 있지 않다는 점이 아쉽습니다.
그래서 이러한 문제점들을 보완한 추급권을 구현했고, 그 주요 특징은 다음과 같습니다.
- 다수 추급권자 허용
- 추급권 미적용/적용 NFT 포괄을 위한 Gateway 컨트랙트
- NFT 마켓플레이스에서의 추급권 적용 설계
아래에서 더 자세히 설명하도록 하겠습니다.
동작 원리
먼저 추급권의 동작 원리를 단순화하면 다음과 같습니다.
- 마켓플레이스에서 RoyaltyRouter라고 불리는 Gateway 컨트랙트를 사용하여 원하는 NFT의 추급권 정보를 저장하고 있는 컨트랙트의 주소를 조회합니다.
- 그렇게 추급권 정보가 탐색되면, getRoyalty() 함수를 호출하여 실제 추급권 정보를 얻어올 수 있습니다.
그런데 여기서 1) NFT와 추급권 컨트랙트가 별개로 구현된 경우, 그리고 2) NFT 자체에 추급권이 구현된 경우를 구분해야 합니다. 전자의 경우 해당 KIP-17 컨트랙트와 추급권 컨트랙트를 연결시키는 과정이 선행되어야 하기 때문입니다.
NFT와 추급권이 별개로 구현된 경우
NFT와 추급권이 별개의 컨트랙트로 존재하는 경우에는 RoyaltyRouter의 overrideAddress()를 통해 두 컨트랙트를 연결시킬 필요가 있습니다. 아래 RoyaltyRouter 컨트랙트의 인터페이스를 살펴보면, nftContract
와 royaltyContract
주소를 전달하는 것을 볼 수 있습니다.
overrideAddress 과정을 거쳐서 KIP-17 주소(nftContract)와 추급권 정보가 들어 있는 컨트랙트 주소(royaltyContract)가 연결이 되었습니다. 바로 아래 이미지에 보이는 RoyaltyInfo가 바로 그 추급권 정보가 포함된 컨트랙트입니다. 이제 컨트랙트가 RoyaltyRouter 컨트랙트의 getRoyalty함수를 호출할 경우, 전달된 nftContract 주소에 해당하는 KIP-17 컨트랙트와 연결된 RoyaltyInfo 컨트랙트가 호출되어 추급권 정보가 자동으로 반환됩니다.
추급권 정보가 저장되어 있는 RoyaltyInfo의 인터페이스는 아래와 같습니다. 두 함수를 보면 추급권자가 다수임을 알 수 있습니다.
NFT 자체에 추급권 스펙이 구현된 경우
NFT, 즉 KIP-17 컨트랙트와 추급권 스펙이 결합되어 있는 경우를 살펴보겠습니다. 컨트랙트 인터페이스는 아래와 같습니다.
이 경우 마켓플레이스에서 RoyaltyRouter 컨트랙트의 getRoyalty()함수를 호출하면 해당 KIP-17+추급권 컨트랙트(위 예시에서 IKIP17RoyaltyInfo)가 호출되고, 추급권 정보가 반환됩니다.
NFT 마켓플레이스 구현
개요
아래에서는 NFT 마켓플레이스 구현 예시를 살펴보겠습니다.
위 슬라이드 내용을 설명하자면, 우선 NFT가 경매 방식이 아닌 고정가격 판매 방식(FixedPriceExchange)으로 판매된다고 가정하였습니다(아래 이미지의 Exchange와 동일합니다). 그 다음 판매 대금 정산을 위한 KIP-7 컨트랙트, NFT 마켓플레이스인 만큼 클레이튼의 NFT 표준인 KIP-17 컨트랙트와의 연동도 필요합니다. 또 추급권 구현을 위해서는 앞서 살펴본 RoyaltyRouter 컨트랙트도 필요하며, 마지막으로 환불 기능 구현을 위해 Escrow 컨트랙트도 있어야 합니다.
고정가격 NFT 매매를 위한 컨트랙트의 인터페이스는 아래와 같습니다.
getSaleInfo()는 가격 등 판매 정보를 알려주는 함수이며, putOnSale()은 NFT 판매 등록을 할 수 있는 함수입니다. cancelSale()을 이용해서 판매 취소를 할 수도 있습니다. 그리고 마지막 두 함수는 구매를 위한 함수로서, buyInKLAY()는 KLAY로, onKIP7Received는 KIP-7 토큰으로 결제할 때 사용하는 함수입니다.
시나리오
NFT 발행
가장 먼저 Minter에 해당하는 NFT의 창작자가 아래와 같이 NFT를 발행합니다.
2. NFT 판매 등록
이제 해당 NFT를 구매한 사람이 이것을 재판매한다고 해보겠습니다. 그런데 판매 등록을 하기 전에 해당 토큰의 전송 권한을 Exchange 컨트랙트에 부여해야 합니다. KIP-17 컨트랙트에 정의된 approve()를 이용하면 해당 기능을 수행할 수 있습니다. 이 절차가 선행되어야 구매자에게 NFT가 즉시 전송될 수 있습니다.
3. NFT 구매
마지막으로 NFT 구매가 동작하는 것을 설명드리겠습니다.
- 구매자(Buyer)가 KIP-7 컨트랙트로 transfer()를 호출하여 판매 대금을 Exchange 컨트랙트로 전송합니다.
- 위 전송의 결과로 KIP-7 컨트랙트가 Exchange 컨트랙트의 onKIP7Received()를 호출합니다.
- Exchange 컨트랙트는 Royalty Router 컨트랙트를 통해 추급권 정보를 받아 옵니다.
- 이렇게 받은 정산 정보 및 판매 대금은 Escrow 컨트랙트로 전달됩니다.
- Exchange 컨트랙트가 구매자에게 NFT를 전달합니다. (앞서 approve함수 호출이 선행되어야 합니다)
- 일정 시간 후 판매자(Seller)가 Escrow를 종료하면 대금 정산이 이루어집니다.
- KIP-7 컨트랙트의 transfer()를 통해 추급권자인 원발행자(Minter)에게 판매액의 일정 비율이 전달되고, 나머지는 판매자에게 전달됩니다.
이상으로 추급권 및 NFT 마켓플레이스 구현에 대해 알아봤습니다.
오늘 소개된 내용이 포함된 전체 발표는 Klaytn을 이용하여 NFT 활용하기: 발행부터 판매까지에서 직접 들어보실 수 있습니다. 해당 포스트 및 발표에서 사용된 코드는 아래 Git 리포지토리에서 확인할 수 있습니다.
https://github.com/kjhman21/klaytn-contracts/tree/royalty-registry
MIT license이나 보안검수를 마친 컨트랙트는 아니니, 상업적 이용에는 주의 부탁드립니다.
이 글의 내용이나 기타 관련 질문이 있으시다면 Klaytn Developers Forum에 남겨주세요.
그러면 다음 포스팅에서도 흥미로운 내용으로 찾아뵙겠습니다. 감사합니다.