웹2와 웹3 아키텍처의 차이
웹3 애플리케이션의 아키텍처에 대해 알아보기 전에 웹2의 아키텍처를 알아야할 필요가 있다.
웹2의 아키텍처
간단한 블로그를 만든다고 가정했을 때의 아키텍처는 다음과 같다.

웹2의 아키텍처에는 프론트엔드, 백엔드, 데이터베이스가 거의 필수라고 볼 수 있다. 그리고 이 모든 코드는 중앙화된 시스템에 의해 관리된다.
웹3의 아키텍처
웹3는 기존 웹2의 중앙화된 시스템에서 벗어나 탈중앙화된 시스템을 추구한다. 따라서, 웹2와 달리 웹3에는 중개자가 없고, 중앙 집중식 데이터베이스, 벡엔드도 없다. 이 자리를 ‘블록체인’이 대신하게 된다.
여기서 ‘블록체인’이란 인터넷의 수많은 익명 노드(anonymous nodes)들이 유지 관리하는 분산 상태 기계(decentralized state machine)으로 네트워크에 참여자들이 공동으로 유지 관리하게 된다. 블록체인을 활용한 웹3 디앱 아키텍처는 다음과 같다.

웹2와 비교했을 때 프론트엔드만 동일하고 ‘블록체인’이 백엔드와 데이터베이스를 대체한 것을 확인할 수 있다.
Web2와 Web3 차이

출처: 루디움 - [Aidenteti crew] 로글스 스터디 프로그램
앞서 웹3에서 프론트엔드는 블록체인과 상호작용한다고 언급했다. 블록체인과 상호작용하기 위해서는 크게 2가지 방법이 있다.
1번의 경우, 직접 노드를 운영하기까지 더 많은 개발 지식이 필요하기도 하고, 높은 초기 비용 및 유지보수 문제가 있다. 따라서, 이번 글에서는 Infura나 Alchemy와 같은 노드 서비스를 통해 블록체인과 소통하는 방법에 대해 설명하겠다.

Infura와 Alchemy는 블록체인 애플리케이션 개발 시 필수적인 인프라 서비스를 제공하여, 개발자가 복잡한 노드 운영과 인프라 관리를 대신할 수 있게 도와주는 제공자(Provider) 역할을 한다. 본인이 직접 노드를 운영하지 않는 한 블록체인에 있는 데이터를 읽거나 쓰기 위해서는 이러한 인프라 서비스를 활용해야 한다.
프론트엔드가 블록체인과 상호작용할 때는 주로 상태를 읽거나 상태를 쓸 때 사용된다.
터미널에서 다음 명령어를 실행하여 새로운 React 프로젝트를 만든다.
npx create-react-app project
cd myproject
2. Ethers.js 설치
스마트 계약과 상호작용하기 위해 Ethers 라이브러리를 설치한다.
npm install ethers
JavaScript 파일에서 Ethers 모듈을 불러옵니다.
import { ethers } from "ethers";
MetaMask를 통해 이더리움 네트워크에 접근할 수 있는 제공자(provider)와 서명자(signer)를 설정한다.
MetaMask 연결 버튼을 만들어 사용자에게 연결을 요청한다. MetaMask가 설치되어 있지 않으면 기본 읽기 전용 제공자를 사용한다.
import { ethers } from "ethers";
const App = () => {
let signer = null;
let provider;
const connectMetamask = async () => {
if (window.ethereum == null) {
console.log("MetaMask not installed; using read-only defaults");
provider = ethers.getDefaultProvider();
} else {
provider = new ethers.BrowserProvider(window.ethereum);
signer = await provider.getSigner();
}
}
return (
<>
<button onClick={connectMetamask}>MetaMask 연결</button>
</>
);
}
export default App;
특정 JSON RPC URL을 사용하여 커스텀 제공자를 설정할 수 있다.
const url = '<http://my-node.com>';
provider = new ethers.JsonRpcProvider(url);
제공자를 통해 블록 넘버, 계정 잔액 등을 조회할 수 있다.
const blockNum = await provider.getBlockNumber();
const balance = await provider.getBalance("내 주소");
const formattedBalance = ethers.formatEther(balance);
서명자를 사용하여 이더리움을 전송할 수 있다.
const tx = await signer.sendTransaction({
to: "상대 주소",
value: ethers.parseEther("1.0") // 1.0 이더 전송
});
스마트 계약과 상호작용하기 위해 ABI와 계약 주소가 필요
import { Contract } from "ethers";
const abi = [ /* 스마트 계약 ABI */ ];
const contractAddress = "스마트 계약 주소";
const contract = new Contract(contractAddress, abi, provider);