- NFT 마켓플레이스는 사용자가 NFT를 직접 만들고, 생성한 NFT를 확인하고, NFT를 다른 지갑으로 거래, 전송할 수 있는 플랫폼이다.
🐚 NFT 마켓플레이스는 서비스 이용을 위해서 메타마스크와 같은 암호화폐 지갑과의 연결이 필요하다.- NFT 마켓플레이스 프로젝트를 진행하기 위해서 세계 최대 규모의 이더리움 기반 NFT 거래 플랫폼인 OpenSea를 참고하였다.
- 이 프로젝트에 사용된 스마트 컨트랙트는 이더리움의 테스트 네트워크인 Ropsten에서 배포되었고, 이 사이트이 기능 역시 Ropsten 네트워크 위에서 동작한다.
🐚 따라서, BelugaSea의 민팅, 전송 기능을 이용하기 위해서는 Ropsten 네트워크의 테스트 이더가 필요하다.
기본적인 NFT 민팅 기능에 대해서는 이견의 여지가 없었다.
제일 먼저 이슈가 되었던 사항은 스마트 컨트랙트에 관한 문제였다.
NFT의 기능을 온전히 사용하기 위해서는 해당 NFT의 스마트 컨트랙트를 사용할 수 있어야 했고, 우리는 이를 제대로 활용하기 위해서 하나의 스마트 컨트랙트로 NFT를 발급하고 관리하도록 하였다.
NFT의 메타데이터를 호스팅하기 위해서 IPFS를 이용하기로 하였다.
IPFS의 사용 범위를 고민하는 과정이 있었는데, 단순 이미지만을 IPFS로 업로드 할 지, 아니면 그 뿐만 아니라 메타 데이터도 IPFS로 업로드 하여 마치 JSON의 형태처럼 사용할 수 있을지에 대한 고민이 있었고, IPFS를 통해서 이미지와 메타 데이터를 모두 처리하기로 결정했다.
🐡 IPFS로 이미지만 처리한 뒤, 헤로쿠(Heroku)로 메타 데이터를 저장하는 방법이 고려되었으나, IPFS로 메타 데이터를 저장할 수 있다는 것을 알게 되고, 굳이 헤로쿠를 사용할 이유가 없다고 생각되어 사용하지 않았다.
🐡 NFT의 정보 입력, 이미지 삽입 후 민팅 버튼 클릭 -> 이미지를 IPFS에 업로드 후 링크를 리턴 받는다 -> 이미지 링크와 다른 정보들(메타 데이터)를 IPFS에 저장하고, 최종 토큰 URI를 리턴 받는다 -> 이 URI와 사용자의 지갑 주소를 이용하여 스마트 컨트랙트 민팅 함수를 실행한다.
역할을 분담하는 과정에서 서버의 필요성이 대두되었다.
경매를 통해서 거래를 구현하거나, 좋아요 버튼으로 선택한 NFT만 보여주는 페이지 등의 기능을 위해서는 서버가 필요하다고 생각하였다.
하지만 일단 주어진 일주일의 기간동안, 필수적인 기능들이 있는 서비스를 제공하는 최소 기능 제품(Minimum Viable Product, MVP)을 완성시키는 것이 우선이라고 판단하였다.
또한, 구성원들 중에서 서버 개발자를 희망하는 사람도 없었기에, 프론트엔드를 중심으로 스마트 컨트랙트를 적용한 클라이언트 dApp을 만들기로 결정하였다.
빠른 화면 구성을 위해서 React UI tools인 mui를 사용하기로 하였다.
스마트 컨트랙트의 연결과 사용을 위해서 web3 라이브러리를 사용하기로 했다.
react-router-dom을 통해서 라우팅과 동적 라우팅을 구현하기로 했다.
ipfs-http-client를 통해서 IPFS관련 기능을 구현하기로 했다.
개발 과정에서 화면을 구성하기 위해서 데이터가 필요했고, OpenSea의 API를 통해서 NFT를 화면에 리스트 업할 수도 있었으나, 이렇게 보여지는 NFT들을 실제로 기능을 이용할 수 없었기에 팀원들이 임의로 NFT를 민팅해준 것을 바탕으로 초기 화면을 구성하였다.
스마트 컨트랙트의 총 토큰 발행량을 기준으로 각각의 tokenId를 통해서 NFT 정보를 가져오는 구조를 사용하였는데 민팅되는 NFT의 양이 증가하면서, 모든 NFT를 확인할 수 있는 페이지가 너무 느려지게 되었다.
이에 따라서, 페이지를 구분하여 하나의 페이지에서는 10개의 NFT만 보여주고 그때 화면에 보여지는 NFT들만 불러오는 방식으로 페이지 구조를 변경하였다.
(pagination)
프로필에서 자신이 소유한 NFT만 확인할 수 있도록 NFT 리스트 화면을 구성하였는데, 이 부분에서는 모든 NFT의 소유주를 각각 확인한 뒤 현재 로그인된 지갑의 주소와 비교하여 일치하는 NFT만 보여지도록 하였다.
NFT의 이름으로 검색하여 해당 검색어를 지니는 이름의 NFT만 보여주는 화면도 구현하였는데, 이 또한 모든 NFT의 이름을 확인한 뒤, 검색어와 이름이 match되는 NFT만 보여주는 방법으로 구성하였다.
다만, 프로필 정보나 검색으로 NFT를 보여주는 페이지는 불가피하게 모든 발급된 NFT를 확인하는 과정이 필요하여 페이지를 구성하는데 걸리는 시간이 길어지게 되었다.
NFT를 보여주는 화면에서 가장 최신으로 만들어진 NFT를 먼저 보여주도록 수정하고, 사용자가 원하는 순서대로 NFT를 먼저 확인할 수 있도록 new와 old 라디오 버튼을 만들어 각 버튼을 클릭시 최신 순서 혹은 오래된 순서대로 NFT가 정렬되어 보여지도록 하였다.
동적 라우팅을 바탕으로 검색 리스트나 모든 NFT를 보여주는 리스트, 혹은 프로필에서 자신이 소유한 NFT를 보여주는 리스트 어디에서도 NFT를 클릭하면 해당 NFT의 세부적인 정보를 보여주는 화면으로 이동할 수 있게 하였다.
web3 라이브러리를 통해서 스마트 컨트랙트의 토큰을 전송하는 함수를 사용해, NFT 세부 정보 컴포넌트의 토큰 전송 기능을 구현하였다.
NFT 세부 정보 페이지에서 이미지 클릭시, 원본 크기의 이미지를 확인할 수 있도록 처리하였다.
실제 web3를 이용한 클라이언트 dApp을 만들 수 있는 경험이었다.
스마트 컨트랙트를 활용하는 방법에 대한 여러가지 생각을 할 수 있었고, web3를 이용하여 쉽게 블록체인 네트워크에 배포된 스마트 컨트랙트에 접근할 수 있었다.
팀원들의 코드를 보고 내가 짠 코드와는 또 다른 스타일의 코드를 배울 수 있어서 좋은 경험이 되었다.
추가적으로 시간이 있었다면, 이더리움으로 구현한 기능들을 caver.js를 통해 클레이튼 네트워크에서도 작동할 수 했을텐데 아쉬웠다.
서버를 따로 구현하지 않았기에, 경매를 통한 거래나 좋아요 표시를 한 NFT만 보여주는 기능 등의 추가적인 기능에 대해서는 아쉬움이 있었다.
mui를 사용하여 pagination이나 버튼, input 컴포넌트의 디자인 등 좋은 부분이 있었지만, mui를 사용하니 CSS의 분리가 잘 되지 않아서 코드가 길어지는 부분이 있었다.
직접 styled-componenet를 통해서 파일을 분리해 사용하는 것이 더 파일 구조나 실제 컴포넌트 코드로 봤을 때 더 깔끔할 것 같다.
아무래도 라우팅을 하는 부분 등 다른 팀원들과 같은 파일을 수정해야 할 일이 생기면서, 깃 충돌이 많이 발생했었다.
충돌이 발생하였을 때 처음에는 당황하였지만 팀원들과 함께 차분히 충돌된 코드를 확인하고 적용함으로써, 잘 merge할 수 있었다. 그 뒤로 충돌은 비교적 쉽게 해결한 것 같다.
깃 레포지토리의 이슈기능을 활용하고자 노력했지만, 더 잘할 수 있지 않았을까 하는 아쉬움이 남고 위키등 추가적인 기능으로 더 레포지토리를 잘 꾸밀 수 있지 않았을까 싶다.
처음에는 netlify로 배포를 시도했으나, 빌드에 에러가 발생하여 수정 후 vercel에서 배포를 진행하였다.
프로젝트 깃허브 레포지토리를 완성 후 visibility를 private에서 public으로 수정하였는데, 그 결과로 fork한 레포지토리의 연결이 끊어졌다.
그에 대한 내용을 검색해보니, fork한 레포지토리와 본래 레포지토리는 같은 visibility 상태가 아니면 fork가 끊기는 것 같다.
처음에는 리스트 화면을 flex로 구성하였는데, OpenSea는 grid로 구성되어 있고 화면의 크기에 따라 개별 컴포넌트의 크기가 변경되는 모습을 보고 나 역시 grid 레이아웃으로 변경하여 사용자 경험을 개선하기로 하였다.
그리하여 grid로 화면을 구성할 수 있었는데, 각 개별 컴포넌트의 크기 조절은 미흡했던 것 같다.
이를 계기로 grid 레이아웃에 대해서 더 흥미가 생기고, 더 사용하고 배워 봐야겠다고 생각했다.