OpenSea(NFT마켓 애플리케이션) 개발하기

1

🤔

세계 최대의 web3, NFT 마켓인 OpenSea를 클론코딩, 스마트컨트렉트, 기능구현을 목표로 프로젝트를 진행하였다. 실제로 스마트컨트렉트부터 UI구현까지 기능 이해를 목표로 프로젝트에 참여하였다. 실제로 크게는 프론트와 백엔드를 웹에서 나눠서 진행을 하겠지만 블록체인에서는 Remix를 활용한 스마트컨트렉트와 리액트를 활용한 프론트로 나눠서 진행을 하였다.

OpenSea란?
is the world's first and largest web3 marketplace for NFTs and crypto collectibles. Browse, create, buy, sell, and auction NFTs using OpenSea today.

https://opensea.io/ <참조>

🙏 기술 스택

  • Node.js
  • React
  • Solidity / Remix
  • Github
  • IPFS(InterPlanetary File System)

🙏 기능구현

  1. MetaMask 지갑연동
  2. NFT 확인
  3. NFT 전송

이밖에도 OpenSea와 유사한 UI구현을 목표로 진행하였다.

  1. 메인 화면 구성

  1. Explore 구현

    1. Wallet 구현 (실제로 메타마스크 연결 후 화면전환 )

    2. 지갑 연동 후, NFT 확인 및 전송

      🌐 Code Detail

      1. UI 구현

      App.js

      import Profile from "./pages/Profile";
      import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
      import Main from "./components/Main";
      import Stats from "./pages/Stats";
      import Explore from "./pages/Explore";
      import Trade from "./pages/Trade";
      import Wallet from "./pages/Wallet";
      import Resources from "./pages/Resources";
      import Nav from "./components/Nav";
      
      function App() {
        return (
          <>
            <Router>
              <Nav></Nav>
              {/* 1. Switch -> Routes */}
      
              <Routes>
                {/* 2. component -> element, element형태로 넘겨야함 <Home /> */}
                <Route path="/" element={<Main />} />
      
                <Route path="/trade" element={<Trade />} />
                <Route path="/explore" element={<Explore />} />
                <Route path="/stats" element={<Stats />} />
                <Route path="/profile" element={<Profile />} />
                <Route path="/wallet" element={<Wallet />} />
                <Route path="/resources" element={<Resources />} />
              </Routes>
            </Router>
          </>
        );
      }
      
      export default App;

      리액트 라우터를 활용한 페이지 구현을 진행하였다.

      2. 스마트컨트랙트 구현 & NFT 이미지 (IPFS)

      NFT이미지를 IPFS에 퍼블릭으로 올린 후 Remix에서 민팅을 진행 !

      // SPDX-License-Identifier: MIT
      pragma solidity ^0.8.7;
      
      import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
      import "@openzeppelin/contracts/utils/Counters.sol";
      import "@openzeppelin/contracts/access/Ownable.sol";
      import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
      import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
      
      contract cozNFTs is ERC721URIStorage, Ownable, ERC721Enumerable {
          using Counters for Counters.Counter;
          Counters.Counter private _tokenIds;
      
          constructor() public ERC721("cozNFT", "NFT"){}
      
          function _beforeTokenTransfer(
              address from,
              address to,
              uint256 tokenId
          ) internal
            override(ERC721, ERC721Enumerable) {
              super._beforeTokenTransfer(from, to, tokenId);
          }
      
          function _burn(
              uint256 tokenId
          ) internal
            override(ERC721, ERC721URIStorage) {
              super._burn(tokenId);
          }
      
        function supportsInterface(bytes4 interfaceId)
              public
              view
              override(ERC721, ERC721Enumerable)
              returns (bool)
          {
              return super.supportsInterface(interfaceId);
          }
          function tokenURI(
              uint256 tokenId
          ) public view
            override(ERC721, ERC721URIStorage) returns (string memory) {
              return super.tokenURI(tokenId);
          }
          
          function mintNFT(address recipient, string memory tokenURI) public onlyOwner returns (uint256) {
              _tokenIds.increment();
      
              uint256 newItemId = _tokenIds.current();
              _mint(recipient, newItemId);
              _setTokenURI(newItemId, tokenURI);
      
              return newItemId;
          }
      }

      특정 컨트랙트에 있는 함수를 사용하기 위해서는 컨트랙트의 ABI가 필요! 코드를 컴파일하고, 컨트랙트의 ABI를 복사합니다. src 폴더 안에 erc721Abi.js 파일을 생성하고 작성 후 import 진행 !

      3. 지갑 조회

      EIP-1139를 통해 지갑 소프트웨어는 웹 페이지에 자바스크립트 객체 형태로 window.ethereum
      객체를 제공한다.

      npm install web3

      Trade.js

      const Wallet = () => {
        const [tokenAddress, setNewErc721Addr] = useState("");
        const [account, setAccount] = useState("");
        const [erc721list, setErc721list] = useState([]); // 자신의 NFT 정보를 저장할 토큰
      
        const [web3, setWeb3] = useState();
        useEffect(() => {
          if (typeof window.ethereum !== "undefined") {
            // window.ethereum이 있다면
            try {
              const web = new Web3(window.ethereum); // 새로운 web3 객체를 만든다
              setWeb3(web);
            } catch (err) {
              console.log(err);
            }
          }
        }, []);

      요구조건) **이더리움 객체 가져오기**

      connectWallet()
      함수를 실행하는 이벤트를 추가, 메타마스크로부터 계정을 연결하고, 계정 주소를 상태로 저장

      window.ethereum.request({method: 'eth_requestAccounts'})
      는 메타마스크 지갑과 연결된 계정 정보를 받는 JSON-RPC Call API

      4. NFT 조회 및 보내기

      ERC721 컨트랙트 주소를 입력받아, 해당 컨트랙트에서 발행받은 토큰을 가져와봅시다.

      먼저, 주소를 입력받습니다. newErc721addr 상태는 입력받은 컨트랙트 주소를 저장합니다. 컨트랙트 주소를 입력하고 버튼을 누르면 addNewErc721Token() 이 실행됩니다.

      🤪 회고

      First Project

      Keep(장점, 유지할 점)

      실패, 다양한 경험? 내가 피하고 가장 체력소모가 많았던 일들이 장점이 될 줄은 미쳐 생각못했다. 실패와 실패를 통한 팀원들과 코드 분석과 다양한 견해들을 나눠보면서 힘들때 의지하고 고민해보면서 실패들은 쌓여서 경험을 만들어주고 경험은 쌓여서 실력을 만들어준다. 어려워서 넘기고 지나치던 일들이 어느순간 익숙함으로 다가올때 성장을 하였다는 것을 느꼈다.

      Problem(단점, 변경 또는 버릴 점)

      사실 프로젝트를 진행하기에 부족한 실력, 정전, 네트워크 문제 등 여러 고난이 많았다. 심지어 처음으로 GIt을 활용하여 프로젝트를 진행하는데도 많은 시행착오를 겪었다. 프로젝트를 진행하면서 기본적으로 준비해야할 부분들을 가볍게 여기고 준비를 못했던 점들이 이밖에도 많았던거같다. 가볍게 생각하지말자. 성장하자.

      Try(시도할 점, 앞으로의 행동)

      프로젝트를 앞으로도 다양하게 진행을 할것이기 때문에 무엇보다 실력을 쌓아야겠다는 생각을 크게했다. 팀원들에게나 나에게도 개발자로서 프로젝트를 하기 위해서는 기본적인 개발실력을 갖추고 진행한다면 프로젝트를 진행하면서 모두 많은 성장을 이룰 수 있겠다는 확신이 든다. 리액트, 솔리디티, Express, CSS 부족한 점 채우기 !

      Detail )

      리액트 ⇒ UI표현, 리덕스을 클론코딩으로 학습하기 !

      Express ⇒ 기본강의 다시듣기 !

      CSS ⇒ 이번에 작업한 팀원 코딩 분석 !

      <깃헙>
      https://github.com/codestates/beb-04-CloseSea

1개의 댓글

comment-user-thumbnail
2022년 6월 17일

메타를 멋지게 만들어 가시는군요 👍 😆 👍

답글 달기