PromleeBlog
sitemap
aboutMe

posting thumbnail
React Native(Expo) 환경에서 EVM 블록체인 지갑 생성하기 (Mnemonic)
generate EVM blockchain wallet in React Native(Expo) environment (Mnemonic)

📅

🚀

들어가기 전에 🔗

이 포스팅은 Expo 52 버전을 기준으로 작성되었습니다.
기본적인 Expo 프로젝트가 설정되어있다고 가정하고 진행하겠습니다.

EVM 이란? 🔗

EVM은 이더리움 블록체인의 핵심 요소로, 스마트 컨트랙트 실행을 담당하는 가상 머신입니다. 스마트 컨트랙트의 보안성과 탈중앙화를 보장하며, 이더리움뿐만 아니라 여러 블록체인에서 EVM을 지원하고 있습니다. 이를 통해 탈중앙화 애플리케이션(DApp) 개발이 가능하며, 블록체인의 확장성과 활용도를 높이는 데 중요한 역할을 합니다.
이토록 널리 쓰이는 EVM은
모든 체인에서 같은 주소
를 사용하며, 이는 모든 블록체인에서 동일한 지갑을 사용할 수 있다는 것을 의미합니다. 이는 사용자가 여러 블록체인을 사용하더라도 동일한 지갑을 사용할 수 있게 해주는 장점을 가지고 있습니다.
우리는 DApp에서 사용자가 EVM 블록체인 지갑을 생성하고, 이를 사용할 수 있도록 구현하는 방법을 알아보겠습니다.

Mnemonic 이란? 🔗

Mnemonic(니모닉)은 암호화폐 지갑의 비밀키를 쉽게 기억하고 복구할 수 있도록 만든 12~24개의 영어 단어 조합입니다. BIP-39 표준을 기반으로 생성되며, 이를 사용하면 비밀키 없이도 지갑을 복원할 수 있습니다. 보안이 중요한 정보이므로 절대 온라인에 저장하지 말고, 안전한 장소에 백업해야 합니다.
우리는 1차적으로 사용자에게 Mnemonic을 생성하고, 이를 통해 지갑을 생성하는 방법을 알아보겠습니다.

ehers.Wallet.createRandom() 을 사용하지 않는 이유 🔗

랜덤한 바이트 기반으로 지갑을 생성하는 createRandom() 함수는 앱 환경에서 각자의 운영체제에 권한을 요청하게 되는데, 이 과정이 복잡하며 레퍼런스가 존재하지 않습니다. 따라서 Expo에서 기보 제공하는 expo-crypto 라이브러리를 사용하여 Mnemonic을 생성하고, 이를 통해 지갑을 생성하는 방법을 알아보겠습니다.
createRandom() 오류
createRandom() 오류

🚀

1. Mnemonic 생성하기 🔗

1.1. 라이브러리 설치하기 🔗

다음 명령어를 통해 expo-crypto와 bip39 라이브러리를 설치합니다. expo-crypto는 Expo에서 제공하는 암호화 라이브러리이며, bip39는 Mnemonic을 생성하는 라이브러리입니다. buffer 라이브러리는 expo-crypto 라이브러리에서 사용되는 라이브러리입니다.
npx expo install expo-crypto
npm install bip39 buffer

1.2. Buffer 사용 설정하기 🔗

expo-crypto 라이브러리를 사용하기 위해 Buffer를 사용할 수 있도록 설정합니다. 저는 app/_layout.tsx 파일에 다음 코드를 추가하여 설정했습니다.
const RootLayout = () => {
	global.Buffer = require('buffer').Buffer;
	// ...
}

1.3. Mnemonic 생성 함수 작성 🔗

다음 코드를 통해 Mnemonic을 생성합니다. 먼저 expo-crypto 라이브러리를 사용하여 랜덤 바이트를 생성하고, 이를 bip39 라이브러리를 사용하여 Mnemonic으로 변환합니다.
저는 활용성을 위해 string 배열로 변환하여 반환하였습니다.
import { Buffer } from 'buffer';
import * as Crypto from 'expo-crypto';
import * as bip39 from 'bip39';
 
const generateMnemonic = async () => {
	const randomBytes = await Crypto.getRandomBytesAsync(16);
	const mnemonic = bip39.entropyToMnemonic(Buffer.from(randomBytes).toString('hex'));
	return mnemonic.split(' '); // string 배열로 변환 
}

🚀

2. 지갑 생성하기 🔗

2.1. ethers.js 설치하기 🔗

다음 명령어를 통해 ethers.js 라이브러리를 설치합니다. ethers.js는 이더리움 블록체인을 사용하기 위한 라이브러리입니다.
npm install ethers

2.2. 지갑 생성 함수 작성 🔗

다음 코드를 통해 Mnemonic을 통해 지갑을 생성합니다. 먼저 Mnemonic을 통해 지갑을 생성하고, 이를 통해 지갑 주소를 반환합니다.
import { ethers } from 'ethers';
 
const mnemonic = ['word1', 'word2', 'word3', 'word4', 'word5', 'word6', 'word7', 'word8', 'word9', 'word10', 'word11', 'word12'];
 
const getAccounts = () => {
	if (!mnemonic.length) return;
	const wallet = ethers.Wallet.fromPhrase(mnemonic.join(' '));
	return wallet; // 지갑 반환
};

2.3. 지갑 사용하기 🔗

다음 코드를 통해 지갑을 사용할 수 있습니다. 지갑을 생성하고, 이를 통해 주소, 개인키, 공개키를 확인할 수 있습니다.
const wallet = getAccounts();
console.log(wallet.address); // 지갑 주소
console.log(wallet.privateKey); // 개인키
console.log(wallet.publicKey); // 공개키
console.log(wallet?.mnemonic?.phrase); // Mnemonic

🚀

3. Expo 앱에 적용하기 🔗

상태관리를 사용하여 페이지에 적용해 보았습니다. Reload 버튼도 추가하여 Mnemonic을 새로 생성할 수 있도록 하였습니다.
/app/index.tsx 코드 보기
/app/index.tsx
import { Buffer } from 'buffer';
 
import * as bip39 from 'bip39';
import { ethers } from 'ethers';
import * as Crypto from 'expo-crypto';
import { useEffect, useState } from 'react';
import { FlatList, Pressable, View, Text } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
 
import { saveMnemonic } from '@/components/SecureStoreHelper';
 
const CreateWallet = () => {
  const [mnemonic, setMnemonic] = useState<string[]>([]);
  const [wallet, setwallet] = useState<ethers.HDNodeWallet>();
 
  function generateMnemonic() {
    const randomBytes = Crypto.getRandomBytes(16);
    const mnemonic = bip39.entropyToMnemonic(
      Buffer.from(randomBytes).toString('hex'),
    );
    setMnemonic(mnemonic.split(' '));
  }
 
  const getWallet = () => {
    if (!mnemonic.length) return;
    const wallet = ethers.Wallet.fromPhrase(mnemonic.join(' '));
    saveMnemonic(mnemonic.join(' '));
    setwallet(wallet);
  };
 
  useEffect(() => {
    generateMnemonic();
  }, []);
 
  useEffect(() => {
    getWallet();
  }, [mnemonic]);
 
  return (
    <SafeAreaView
      style={{
        flex: 1,
        justifyContent: 'flex-start',
        gap: 20,
        padding: 20,
      }}
    >
      <View>
        <FlatList
          data={mnemonic}
          renderItem={({ item, index }) => (
            <View
              style={{
                flex: 1,
                padding: 5,
                alignItems: 'center',
                borderColor: 'gray',
                borderWidth: 1,
                margin: 5,
                borderRadius: 5,
                position: 'relative',
                flexDirection: 'row',
              }}
            >
              <Text style={{ marginHorizontal: 2 }}>{index + 1}</Text>
              <Text style={{ flex: 1, textAlign: 'center' }}>{item}</Text>
            </View>
          )}
          keyExtractor={(item) => item}
          numColumns={3}
        />
      </View>
      <View style={{ gap: 20 }}>
        <Text>Address: {wallet?.address}</Text>
        <Text>Private Key: {wallet?.privateKey}</Text>
        <Text>Public Key: {wallet?.publicKey}</Text>
      </View>
      <Pressable
        onPress={() => {
          generateMnemonic();
        }}
      >
        <Text style={{ color: 'blue' }}>Reload</Text>
      </Pressable>
    </SafeAreaView>
  );
};
 
export default CreateWallet;
지갑 생성 결과
지갑 생성 결과

🚀

결론 🔗

Expo 환경에서 EVM 블록체인 지갑을 생성하는 방법을 알아보았습니다. Mnemonic을 생성하고, 이를 통해 지갑을 생성하는 방법을 알아보았습니다. 이를 통해 사용자가 DApp에서 EVM 블록체인을 사용할 수 있도록 구현할 수 있습니다.

더 생각해 보기 🔗

참고 🔗