이전 블로그를 이어나가겠다.
남은 작업은 두 가지다. eth-lightwallet 모듈을 이용하여 API 를 만든다.
- 니모닉 코드 발행 (requestMnemonic 함수)
- 새 지갑주소 발행 (requestAcccount 함수)
const requestMnemonic = () => {
const mnemonic = lightwallet.keystore.generateRandomSeed();
setMnemonicResult(mnemonic);
}
App.js 상단에 eth-lightwallet 을 lightwallet 변수에 정의했었다.
import lightwallet from 'eth-lightwallet';
해당 모듈은 다양한 암호화 함수들을 지원한다. 자세한 내용은 npm 을 참조하길 바라겠읍니다..
const mnemonic = lightwallet.keystore.generateRandomSeed();
우리가 사용한 함수는 keystore.generateRandomSeed() 이다. 이 함수는 니모닉 코드(Seed) 를 랜덤하게 발행한다. 이 시드는 HD 지갑주소들을 발행하는데 중심이 된다.
위 함수를 직접 만드려면 꽤 복잡한 과정을 거쳐야 할 것이다.
먼저 랜덤한 해시값을 행성하고, 그 값을 12등분 한 후 내가 미리 만들어준 단어리스트와 맵핑을 해야 한다. 단어리스트는 많을수록 좋을 것이며 위 BIP39 제안에서는 2048 words 를 사용한 것을 확인할 수 있다.
어쨌든 우리는 이미 잘 만들어져있는 모듈을 활용하여 니모닉을 발행할 수 있다.
setMnemonicResult(mnemonic);
생성된 니모닉 코드를 state 에 최종적으로 저장한다.
이제 RequestMnemonicForm.js 의 버튼(Button) 을 클릭하면 니모닉 코드가 발행되고, 그 결과는 Mnemonic.js 콤포넌트로 뿌려질 것이다.
const requestAccount = (mne, pwd) => {
lightwallet.keystore.createVault({
password: pwd,
seedPhrase: mne,
hdPathString: "m/0'/0'/0'"
}, function (err, ks) {
ks.keyFromPassword(pwd, function (err, pwDerivedKey) {
ks.generateNewAddress(pwDerivedKey, 1);
let address = (ks.getAddresses()).toString();
let keystore = ks.serialize();
setAccountResult({ keystore, address });
});
});
}
callback 함수가 많아서 좀 복잡해보이는데, 하나씩 뜯어보자.
lightwallet.keystore.createVault({
password: pwd,
seedPhrase: mne,
hdPathString: "m/0'/0'/0'"
}, function (err, ks) {
//생략
});
하나의 키스토어 패키지를 생성한다. createValut (valut 는 천장이라는 뜻이다) 함수는 니모닉코드(seedPhrase), 솔트값(password), HD지갑경로(hdPathString) 를 인자로 받아 callback 함수를 실행한다.
callback 함수에서는 생성된 keystore (ks) 를 활용할 수 있다.
function (err, ks) {
ks.keyFromPassword(pwd, function (err, pwDerivedKey) {
//...
});
}
createValut() 를 통해 keystore (ks) 를 생성하였고, 이제 ks.keyFromPassword() 함수를 통해 키 쌍(key-pair) 를 생성한다. 이것이 실제로 블록체인 지갑주소가 되는 것이다.
ks.keyFromPassword 는 발행된 키(pwDeriveKey) 를 출력하는 callback 함수를 실행한다.
function (err, pwDerivedKey) {
ks.generateNewAddress(pwDerivedKey, 1);
let address = (ks.getAddresses()).toString();
let keystore = ks.serialize();
setAccountResult({ keystore, address });
}
공개키(address) 와 키스토어(keystore) 를 적절한 형태로 변환해준다. 마지막으로 state 에 해당값들을 저장하면 개발이 완료된다.
npm start
애플리케이션을 실행하여 동작을 테스트해보자.
먼저 니모닉 코드를 발행해야 하고, 발행된 니모닉 코드를 입력 인자로 하여 지갑주소를 생성해 본다.
이 과정은 실제 메타마스크(Metamask) 의 과정과 완전히 동일하다.
물론 코드상에는 HDpath 를 명시해두었고 따로 counting 을 하지 않기 때문에 다수의 지갑주소를 생성하는 테스트는 어렵다.
아무튼 아래 화면과 같이 최종 동작하는 것을 확인할 수 있다.
추천 받은 회고 방법론을 통해 지금까지 한 내용을 정리해 보겠다.
회고 방법론 : KPT (KEEP, PROBLEM, TRY)
그 동안 수업을 통해 배운 내용(react) 을 직접 개발에 적용해 보았다는 점에서 스스로 자랑스럽다. 특히 이미 존재하는 react 코드를 수정하는 것이 아닌, 처음부터 한땀한땀 직접 작성해 본 내가 뿌듯하다.
교재(니모닉 코드 개발) 의 내용과 과거에 학습한 내용을 조합하여 고민하면서 만들어 보니 머릿속으로 정리가 잘 되었다.
앞으로도 react 를 활용한 프로젝트를 한다 치더라도 겁이 나지 않는다. 한 번이 어렵지 두 번부터는 쉽다고 하지 않는가?
개발 업무를 할 때 늘 두려웠던 것은 새로운 프레임워크 혹은 기술을 적용하는 것이었다. (나는야 개꼰대)
왜냐하면 이미 익숙한 방법이 있고 그걸로 하면 그냥 잘할 수 있는데, 굳이 고생을 사서 할 필요가 없기 때문이다. (물론 나중엔 더 도움이 되는 걸 알지만 당장 귀찮고 겁시 난다)
그런 태도가 나의 성장을 가로막는 것 같다.
비록 허접하고 아주 기초적인 react 활용이었지만, 첫 시도였고 자신감이 생겨서 만족한다. 앞으로도 수업에서 배웠던 다양한 방법들을 프로젝트에 모두 녹여내고 싶다.
CSS 를 너무 모르고, 원리를 알려고 하지 않는 버릇이 또 보인 것 같다.
Account.js 콤포넌트에서 결과를 뿌려줄 때 keystore 의 값이 매우 길다.
이 결과값이 행바꿈을 하지 못하는 문제가 발생하고 있는데 (오른쪽 화면 밖으로 글씨가 나간다),
1시간 동안 이것저것 해보다 포기했다. jpx 와 관련이 있는 것인지 잘 모르겠지만 App.css 를 좀 고쳐보다가 화가 나서 포기하게 되었다.
옛날에 HTML & CSS 로 무언가를 만들 때는 bootstrap 이라는 라이브러리에 대부분을 맡기는 편이었다. 그러다보니 이런 문제가 발생하면 해결을 잘 못하는 것 같다.
개발자는 비개발자에게 결과물을 보여주거나 설득을 하려면 'showing' 을 잘해야 하는데 그 필수인 CSS 에 약하다는 것은 큰 문제인 것 같다.
이번 애플리케이션의 경우도 CSS 에 자신이 있다면 10분 정도만 할애해도 훨씬 깔끔하게 화면을 구성할 수 있을텐데 (더 큰 문제는 의지가 없다) 참 아쉬운 부분이다. 개선하고 싶다.
다음 프로젝트에서는 보다 REACT 를 풍부하게 활용하고, CSS 를 더 공부하여 예쁜 애플리케이션을 만들어 보겠다.
그런 과정이 불필요하다고 생각하지 말고 사용자 입장에서 프론트앤드를 구성해 보겠다.
한편 이번 블로깅의 주제는 프론트가 아니라 블록체인 니모닉 지갑이었다. eth-lightwallet 을 사용하고 과정도 어렵지 않다보니 주객이 전도된 느낌이 든다.
암호학은 정말 어려운 주제이고, wallet 은 블록체인에서 핵심적인 부문이라 할 수 있겠다. 암호화폐 지갑개발 그 자체가 블록체인 기술에서 큰 영역이라 생각한다.
eth-lightwallet 에서 제공하는 다양한 기능을 테스트해보고, 모듈 없이 직접 개발을 시도해 봐야 겠다.(그러려면 개념 이해가 선행되야 한다ㅠㅠ)
여기까지 '니모닉 지갑 개발하기' 블로깅을 마친다.
읽어주셔서 감사합니다.