Web3 프론트엔드를 구성할 때 가장 중요한 요소 중 하나는 지갑 연결과 스마트 컨트랙트 연동의 안정성과 편의성입니다. 이번 글에서는 @reown/appkit
과 wagmi
, ethers
, viem
을 활용하여 모던한 Web3 dApp 환경을 구성하는 방법을 소개합니다.
특히, Reown에서 제공하는 AppKitButton
을 사용해 지갑 연결 UI를 심플하게 구성하고, 스마트 컨트랙트 연동은 wagmi
를 활용하여 안전하게 처리합니다.
🧱 1. 프로젝트 구조 개요
bash
복사편집
src/
├── appkit/ # wagmi + appkit 설정
│ └── config.js
├── contracts/ # 스마트 컨트랙트 ABI 및 주소
│ ├── CounterABI.json
│ └── address.js
├── hooks/ # wagmi용 커스텀 훅 (읽기/쓰기)
│ ├── useCounterRead.js
│ └── useCounterWrite.js
├── pages/
│ └── CounterPage.jsx # 실제 스마트 컨트랙트 연동 화면
├── App.jsx # 전체 앱 엔트리 포인트
각 폴더 및 파일의 목적은 다음과 같습니다:
폴더/파일 | 설명 |
---|---|
appkit/config.js |
AppKit + wagmi의 핵심 설정을 담당 |
contracts/CounterABI.json |
스마트 컨트랙트 ABI 정의 파일 |
contracts/address.js |
스마트 컨트랙트 주소 정의 |
hooks/ |
컨트랙트 호출을 담당하는 useContractRead , useContractWrite 활용 커스텀 훅 모음 |
pages/CounterPage.jsx |
dApp 메인 화면. 읽기/쓰기 기능 제공 |
App.jsx |
AppKitProvider 및 WagmiConfig로 앱 전체를 감싸는 설정 |
⚙️ 2. AppKit + wagmi 설정
📁 파일: appkit/config.js
import { WagmiAdapter } from '@reown/appkit-adapter-wagmi';
import { mainnet, arbitrum, sepolia } from '@reown/appkit/networks';
import type { AppKitNetwork } from '@reown/appkit/networks';
export const projectId = import.meta.env.VITE_PROJECT_ID || "b56e18d47c72ab683b10814fe9495694"; // localhost 테스트용
export const metadata = {
name: 'AppKit',
description: 'AppKit Example',
url: 'https://reown.com',
icons: ['https://avatars.githubusercontent.com/u/179229932']
};
export const networks = [mainnet, arbitrum, sepolia] as [AppKitNetwork, ...AppKitNetwork[]];
export const wagmiAdapter = new WagmiAdapter({
projectId,
networks,
});
export const config = wagmiAdapter.wagmiConfig;
🧠 설명:
projectId
: reown/appkit 기반 연결을 위한 ID입니다. Reown Cloud에서 발급.WagmiAdapter
: wagmi와 AppKit을 연결하는 설정자 역할.wagmiConfig
: 전체 앱에서 사용할 wagmi 설정을 반환합니다.
🧩 3. App.jsx 설정
📁 파일: App.jsx
import { WagmiConfig } from 'wagmi';
import { AppKitProvider } from '@reown/appkit';
import { wagmiAdapter, config, networks, metadata } from './appkit/config';
import CounterPage from './pages/CounterPage';
function App() {
return (
<WagmiConfig config={config}>
<AppKitProvider adapter={wagmiAdapter} metadata={metadata}>
<CounterPage />
</AppKitProvider>
</WagmiConfig>
);
}
export default App;
🧠 설명:
WagmiConfig
와 AppKitProvider
로 전체 애플리케이션에 Web3 상태(Context)를 적용합니다.
🔐 4. 지갑 연결 버튼 - AppKitButton
사용
Reown은 UI 모달과 연결 기능이 포함된 AppKitButton
을 제공합니다.
사용 예시 (CounterPage.jsx 내부에서 사용):
<AppKitButton />
🧠 설명:
AppKitButton
은 내부적으로 지갑 연결 상태를 감지하고, 연결되지 않았다면 모달을 띄워 사용자가 지갑을 선택하게 유도합니다. 커스텀 버튼 대신 이 컴포넌트를 활용하면 통일성 있는 UI/UX 제공이 가능합니다.
🔍 5. 컨트랙트 읽기 훅 – useContractRead
📁 파일: hooks/useCounterRead.js
import { useContractRead } from 'wagmi';
import { COUNTER_ADDRESS } from '../contracts/address';
import abi from '../contracts/CounterABI.json';
export const useCounterRead = () => {
const { data, refetch } = useContractRead({
address: COUNTER_ADDRESS,
abi,
functionName: 'getCount',
watch: true,
});
return { count: data?.toString() ?? '0', refetch };
};
🧠 설명:
스마트 컨트랙트의 getCount()
를 호출하여 현재 카운터 값을 가져옵니다. watch: true
옵션으로 자동 업데이트도 가능하게 설정되어 있습니다.
✍️ 6. 컨트랙트 쓰기 훅 – useContractWrite
📁 파일: hooks/useCounterWrite.js
import { useContractWrite, useWaitForTransaction } from 'wagmi';
import { COUNTER_ADDRESS } from '../contracts/address';
import abi from '../contracts/CounterABI.json';
export const useCounterWrite = () => {
const { data, write } = useContractWrite({
address: COUNTER_ADDRESS,
abi,
functionName: 'increment',
});
const { isLoading, isSuccess } = useWaitForTransaction({ hash: data?.hash });
return { write, isLoading, isSuccess };
};
🧠 설명:
increment()
함수 호출을 위해 트랜잭션을 생성합니다.useWaitForTransaction()
훅으로 실제 블록체인에 기록될 때까지 대기합니다.
📄 7. 최종 화면 구성 – CounterPage.jsx
📁 파일: pages/CounterPage.jsx
import { useCounterRead } from '../hooks/useCounterRead';
import { useCounterWrite } from '../hooks/useCounterWrite';
import { useEffect } from 'react';
const CounterPage = () => {
const { count, refetch } = useCounterRead();
const { write, isLoading, isSuccess } = useCounterWrite();
useEffect(() => {
if (isSuccess) refetch();
}, [isSuccess]);
return (
<div className="p-6">
<AppKitButton />
<h1 className="text-xl font-bold mt-4">현재 카운트: {count}</h1>
<buttononClick={() => write?.()}
disabled={isLoading}
className="mt-4 px-4 py-2 bg-green-500 text-white rounded"
>
{isLoading ? '처리 중...' : '카운트 증가'}
</button>
</div>
);
};
export default CounterPage;
🧠 설명:
- 버튼 클릭 시
increment()
실행 - 트랜잭션 완료 후 상태값 재조회
AppKitButton
으로 지갑 UI 자동 처리
'BlockChain > Web3' 카테고리의 다른 글
[1] Frontend in Web3 (0) | 2025.04.06 |
---|