JD의 블로그

[마스터링 이더리움] 2장 이더리움 기초 본문

블록체인

[마스터링 이더리움] 2장 이더리움 기초

GDong 2021. 10. 21. 01:20

지난 번에는 이더리움이 무엇인지에 대해서 살펴봤다면 이번에는 이더리움에 대해 보다 깊게 알아보고, 지갑 사용 방법과 트랜잭션 생성 방법, 기본 스마트 컨트랙트 수행 방법을 다뤄본다.

 

이더리움의 화폐 단위

이더리움의 화폐 단위는 이더(Ether)라고 불리며 'ETH'를 사용한다. 

이더는 더 작은 단위로 세분화되어 웨이(wei)라는 가능한 가장 작은 단위까지 내려간다. 1개의 이더는 100경 웨이다. 

이더리움은 화폐가 아니다. 이더리움은 시스템이고 이더가 화폐다. 그렇지만 잘못 이해하고 이더리움을 화폐처럼 얘기하는 사람들이 있다.

 

이더의 가치는 항상 이더리움 내부에서 웨이로 표시된 부호 없는 정수값으로 표시한다. 1이더를 거래할 때, 그 트랜잭션은 1000000000000000000웨이 값으로 인코딩해서 표기한다. 이더의 다양한 단위에는 컴퓨터와 암호학 분야의 위대한 인물에게 경의를 표하는 구어와 SI 이름을 같이 사용한다. 

 

이더리움 지갑

'지갑'이라는 용어는 많은 것을 뜻할 수 있지만 여기서 말하는 지갑은 이더리움 계정을 관리하는 데 도움이 되는 소프트웨어 애플리케이션이라는 의미로 사용한다. 즉 이더리움 지갑은 이더리움 시스템의 관문(Gateway)다. 지갑은 사용자의 키를 보관하고, 사용자를 대신하여 트랜잭션을 생성하고 브로드캐스트 할 수 있다. 이더리움 지갑은 그 기능과 디자인이 다양하다. 일부는 초보자에게 적합하고 일부는 전문가에게 더 적합하다. 

 

지갑을 변경하기 위해서는 이전 지갑에서 새 지갑으로 자금을 보내거나 개인키를 내보내고 새 키로 가져오는 트랜잭션만 수행하면 된다. 

 

이 책에서는 예제로 사용할 수 있는 세 가지 유형의 지갑으로 모바일 지갑, 데스크톱 지갑 및 웹 기반 지갑을 선택했다. 

 

지갑 애플리케이션이 작동하려면 개인키에 대한 접근 권한이 있어야 하므로 신뢰하는 소스에서 지갑 애플리케이션을 다운로드해서 사용하는 것이 중요하다. 인기가 높을수록 더 신뢰할 수 있지만, 모든 계란을 하나의 바구니에 담는 것을 피하고 이더리움 계정을 2개의 지갑에 분산시켜 놓는 것이 좋다.

 

스타터 지갑으로 좋은 것은 다음과 같다.

  • 메타마스크(MetaMask)
    • 메타마스크는 브라우저에서 실행되는 브라우저 확장 지갑이다. 다양한 이더리움 노드와 테스트 블록체인에 연결할 수 있어서 사용하기 쉽고 테스트하기 편리하다. 메타마스크는 웹 기반 지갑이다.
  • 잭스(Jaxx)
    • 잭스는 안드로이드, iOS, 윈도우, 맥OS, 리눅스를 비롯한 다양한 운영체제에서 실행되는 다중 플랫폼 및 다중 화폐 지갑이다. 단순하고 사용하기 쉽도록 설계되어 새로운 사용자를 위한 좋은 선택이다. 잭스는 어디에 설치하느냐에 따라 모바일 또는 데스크톱 지갑이 된다.
  • 마이이더월렛(MyEtherWallet, MEW)
    • 마이이더웰렛은 모든 브라우저에서 실행되는 웹 기반 지갑이다. 
  • 에메랄드 지갑(Emerald Wallet)
    • 에메랄드 지갑은 이더리움 클래식 블록체인과 함께 작동하도록 설계되었지만, 그 밖의 이더리움 기반 블록체인과도 잘 동작한다. 오픈 소스 데스크톱 애플리케이션이며, 윈도우, 맥OS 및 리눅스에서 작동한다. 

통제와 책임

통제와 책임은 이더리움과 같은 개방형 블록체인에서 탈중앙화된 시스템으로 작동하기 때문에 중요한 요소다. 한 가지 중요한 측면은 이더리움의 각 사용자가 자금 및 스마트 컨트랙트에 대한 접근을 제어하는 자체 개인키를 관리하고 제어할 수 있어야 한다는 것이다. 

기본 원칙은 하나의 개인키가 하나의 "계정"과 동일한 것이라고 생각하면 쉽다. 

 

통제에는 큰 책임이 따른다. 개인키를 분실하면 자금 및 컨트랙트에 대한 접근 권한을 잃게 된다. 어느 누구도 접근 권한을 회복하도록 도와줄 수 없으며, 자금은 영원히 잠겨있게 된다. 

 

지갑 만들기

Chrome extension에 MetaMask를 치면 메타마스크 애플리케이션을 크롬에 추가할 수 있다. 

처음 들어가면 계정을 생성할 수 있는데 패스워드를 설정하면 메타마스크가 지갑을 생성하고 12개의 영어 단어로 구성된 니모닉 백업을 표시해준다. 메타마스크 또는 컴퓨터에 어떤 문제가 생기면, 이 단어들을 호환되는 지갑에서 사용할 수 있다. 

니모닉 백업을 확인하고 나면 이더리움 계정의 세부 정보를 볼 수 있게 된다.

 

이더리움 계정의 세부 정보

계정 페이지에는 계정 이름과 이더리움 주소 그리고 이 계정과 다른 계정을 시각적으로 구별할 수 있는 다채로운 아이콘이 표시된다.

 

네트워크 변경

메타마스크 계정 페이지에서 여러 이더리움 네트워크 중 선택할 수 있다. 기본적으로 메타마스크는 메인 네트워크에 연결을 시도한다. 그 외에 공개 테스트넷이나 원하는 이더리움 노드, 또는 자신의 컴퓨터에서 사설 블록체인을 실행하는 노드를 선택할 수 있다. 

 

  • 메인 이더리움 네트워크 
    • 주된 공개 이더리움 블록체인. 실제 ETH, 실제 가치 및 실제 결과
  • 롭스텐 테스트 네트워크
    • 이더리움 공개 테스트 블록체인 및 네트워크. 이 네트워크상의 ETH는 가치가 없다.
  • 코반 테스트 네트워크
    • 권한증명과 함께 아우라 합의 프로토콜을 사용한 이더리움 공개 테스트 블록체인 및 네트워크. 이 네트워크상의 ETH는 가치가 없다. 코반 테스트 네트워크는 패리티에서만 지원된다. 그 밖의 이더리움 클라이언트는 권한 기반 검증의 증거를 위해 나중에 제안된 클리크 합의 프로토콜을 사용한다.
  • 린케비 테스트 네트워크
    • 권한증명과 함께 클리크 합의 프로토콜을 사용하는 이더리움 공개 테스트 블록 및 네트워크. 이 네트워크상의 ETH는 가치가 없다.
  • 로컬 호스트 8545
    • 브라우저와 동일한 컴퓨터에서 실행 중인 노드에 연결한다. 노드는 공개 블록체인 또는 개인 테스트넷의 일부가 될 수 있다.
  • 사용자 지정 RPC
    • 게스 호환 원격 프로시저 호출 인터페이스로 모든 노드에 메타마스크를 연결할 수 있다. 노드는 공개 또는 사설 블록체인의 일부가 될 수 있다.

테스트 이더 얻기

메인 네트워크로 이더를 얻으려면 비용이 들기 때문에 롭스텐 테스트 네트워크를 사용해서 이더리움을 얻어보자.

 

"구매"를 누르고 "포시트(수도꼭지)테스트"에서 [Ether 얻기]를 누른다. 

 

메타마스크는 아래와 같은 새 웹 페이지를 연다. 웹 페이지에 이미 메타마스크 지갑의 이더리움 주소가 있다. 메타마스크는 이더리움 사용 웹 페이지를 메타마스크 지갑과 통합하고 웹 페이지에서 이더리움 주소를 볼 수있다. 예를 들어, 이더리움 주소를 표시하는 온라인 상점에 지급할 수 있다. 메타마스크는 웹 페이지가 요청할 경우 자신의 지갑 주소를 수신자 주소로 웹 페이지에 채울 수도 있다. 이 페이지에서는 포시트 애플리케이션이 메타마스크에게 테스트 이더를 보낼 지갑 주소를 요청하고 있다. 

 

"request 1 ether from faucet" 버튼을 클릭한다. 

원래는 transactions에 트랜잭션 ID가 떠야하는데 현재는 오류가 발생해서 뜨지 않는다.

이더를 받을 수가 없어서 더 이상 진행하기가 힘들다.. 

 

메타마스크에서 이더 보내기

롭스텐 테스트 Faucet 페이지에는 Faucet에 1ETH를 기부하는 옵션도 있다. 이 옵션은 테스트가 끝나고 나머지 테스트 이더를 반환하여 다른 사람이 다음에 사용할 수 있게 만들 수 있다.

주황색 1 ether를 클릭하면 메타마스크에게 Faucet 1 이더를 지급하는 트랜잭션을 생성하도록 지시한다. 

1ETH를 보내려고 하면 잔액이 부족해서 보낼 수 없다고 뜨는데 이는 바로 가스(Gas) 비용 때문이다.

이더 트랜잭션은 모든 트랜잭션이 유효한지 확인하기 위해 채굴자에게 수수료를 지급해야 한다.

이더리움의 수수료는 가스라고 하는 암호화폐로 청구된다. 보통 이더로 가스비를 지불한다.

 

트랜잭션을 보낼 때 메타마스크가 최근의 성공한 트랜잭션의 평균 가스 비용을 계산해 결과를 산출해준다. 

 

월드 컴퓨터

암호화폐 기능은 탈중앙화된 월드 컴퓨터로서 이더리움의 기능에 부차적인 요소다. 이더리움 가상 머신(EVM)이라는 에뮬레이트된 컴퓨터에서 실행된 컴퓨터 프로그램인 스마트 컨트랙트를 실행하는 데 사용되기 위한 것이다.

 

EVM은 글로벌 싱글톤으로 마치 전 세계에 걸친 단일 인스턴스 컴퓨터인 것처럼 작동하며 세상 어디서든 실행된다. 이더리움 네트워크의 각 노드는 컨트랙트 실행을 확인하기 위해 EVM의 로컬 사본을 실행하고, 이더리움 블록체인은 트랜잭션과 스마트 컨트랙트를 처리할 때 월드 컴퓨터의 변화하는 상태를 기록한다. 

 

외부 소유 계정(EOA) 및 컨트랙트

메타마스크 지갑에서 생성한 계정의 유형을 외부 소유 계정(Externally Owned Account, EOA)라고 한다. 외부 소유 계정은 개인키가 있는 계정을 말한다. 개인키를 갖는다는 건, 자금 또는 컨트랙트에 대한 접근을 제어한다는 것이다. 또 다른 유형의 계정으로는 컨트랙트 계정(contract account)이다. 컨트랙트 계정에는 단순한 EOA가 가질 수 없는 스마트 컨트랙트 코드가 있다. 또한 컨트랙트 계정에는 개인키가 없다. 대신 컨트랙트 계정은 스마트 컨트랙트 코드의 로직을 제어한다. 여기서 스마트 컨트랙트 코드는 컨트랙트 계정 생성 시 이더리움 블록체인에 기록되고 EVM에 의해 실행되는 소프트웨어 프로그램이다. 

 

컨트랙트는 EOA와 다르게 주소가 없다. 그렇지만 트랜잭션 처리를 할 수 있는데 만약 목적지 주소가 컨트랙트 주소라면 트랜잭션과 트랜잭션 데이터를 입력으로 트랜잭션이 EVM에서 실행된다. 

 

컨트랙트는 개인키가 없기 때문에 트랜잭션을 시작할 순 없다. 그러나 컨트랙트는 복잡한 실행 경로를 구축하여 다른 컨트랙트를 호출해서 컨트랙트에 반응할 수 있다. 댑 프로그래밍 패턴으로 컨트랙트 A가 컨트랙트 B를 호출하게 하는 것이다. 

 

 

간단한 컨트랙트

이더리움에는 많은 고급 언어가 있는데 그 중 가장 많이 사용되고 있는 것이 바로 솔리디티다. 솔리디티는 개빈 우드 박사가 만들었으며 이더리움에서 가장 널리 사용되는 언어다. 

 

첫 번째 예는 Faucet을 제어하는 컨트랙트를 작성할 것이다. 

Faucet은 간단한데 요청하는 모든 주소에 이더를 제공하고 주기적으로 다시 채운다.

// Faucet.sol : Faucet을 구현하는 솔리디티 컨트랙트

contract Faucet {

	// 요청하는 사람에게 이더 주기
    function withdraw(uint withdraw_amount) public {
    
    	// 출금 액수 제한
        require(withdraw_amount <= 100000000000000000);
        
        // 요청한 주소로 금액 보내기
        msg.sender.transfer(withdraw_amount);
        
    }
    
    // 입금 금액 수락
    function () public payable {}
    
}

매우 간단한 컨트랙트이며 여러 가지 나쁜 습관과 보안 취약성을 가진 결함을 가진 컨트랙트다. 

 

require부분에서 100000000000000000 웨이가 1ETH의 단위 이므로 이보다 많은 이더를 요청하면 예외 처리로 에러가 나게 된다.

 

msg 객체는 모든 컨트랙트에서 접근할 수 있는 입력 중 하나로, 이 컨트랙트의 실행을 시작한 트랜잭션을 나타낸다. 

sender 속성은 해당 트랜잭션의 발신자 주소다. transfer 함수는 이더를 현재 컨트랙트에서 발신자의 주소로 전송하는 내장 함수다.

즉 실행을 트리거한 msg의 sender(발신자)에게 transfer(전달) 한다는 뜻이다. transfer 함수는 유일한 인수로서 양을 받는다. 몇 줄 앞에 선언된 withdraw_amount 값을 전달한다.

 

function() public payable {}

이 함수는 소위 폴백(fallback) 또는 기본 함수로,컨트랙트를 실행한 트랜잭션이 컨트랙트에 선언된 함수 또는 어떠한 함수도 지정하지 않았거나 데이터를 포함하지 않은 경우에 호출된다. 컨트랙트에는 하나의 기본 함수(이름 없음)를 가질 수 있으며, 일반적으로 이더를 받는 함수다. 이런 이유로 기본 함수는 public이고 payable 함수로 정의되며, 이는 이더를 커트랙트에 받아들일 수 있음을 의미한다. 이더를 받는 일 외에는 아무것도 하지 않는다. 이더를 지갑 같은 컨트랙트 주소로 보내는 트랜잭션이 발생하면 이 함수가 처리한다.

 

Faucet 컨트랙트 컴파일

컨트랙트를 만들었으면 솔리디티 컴파일러를 통해서 솔리디티 코드를 EVM 바이트코드로 변환해야 한다. EVM은 바이트코드를 블록체인 자체에서 실행할 수 있다. 

 

여기서는 유명한 IDE 중 하나인 리믹스(Remix)를 사용한다. 

 

리믹스에서 새로운 파일을 만들어서 "Faucet.sol"로 이름을 짓고 아까 적었던 예제 코드를 옮긴다. 

 

컴파일 하고 나면 Faucet.json 파일 내에 바이트코드를 확인할 수 있다. 

솔리디티를 사용하면 EVM 바이트코드를 사용하지 않고도 고급 언어를 통해 추상화해서 직접 프로그래밍을 할 수 있다.

 

블록체인에 컨트랙트 생성하기

컨트랙트를 만들어서 바이트코드로 컴파일 했다면 다음으로는 이더리움 블록체인에 컨트랙트를 '등록'해야 한다. 

블록체인에 컨트랙트를 등록하는 것은 목적지 주소가 0x000000000000000000000000000000000000000(제로 어드레스)인 특수 트랜잭션을 만드는 것이다. 제로 어드레스는 컨트랙트를 등록하고자 하는 이더리움 블록체인에 알리는 특별한 주소다. 이런 것은 리믹스 IDE에서 모든 것을 처리하고 메타마스크에 트랜잭션을 보낸다.

 

Deploy & RUN TRANSCATIONS 탭으로 들어가면 ENVIRONMENT 선택창에서 "Javascript VM"를 선택한다. 

 

Remix 환경은 크게 3가지 타입으로 나뉘는데

  • Javascript VM
  • Injected Web3
  • Web3 Provider

Injected Web3와 Web3 Provider는 모두 외부 도구를 필요로 하게 된다.

Injected Provider의 외부 도구는 메타 마스크이다. Web3 Provider의 외부 도구는 Truffle, Ganache-CLI, Hardhat node 또는 이더리움 노드 그 자체가 될 수도 있다.

 

Javascript VM은 브라우저에서 실행되는 블록체인으로 굉장히 간편하다 다른 소프트웨어를 필요로 하지도 않고 이를 실행하기 위한 이더리움 노드도 필요 없다.

 

주의할 점은 Javascript VM의 경우 브라우저를 새로고침하면 Javascript VM은 재시작하고 기본 상태로 돌아가게 된다.

Deploy를 누르면 하단에 "Deployed Contracts" 부분에 Faucet 컨트랙트에 대한 주소가 나타나게 된다.

 

이더리움 컨트랙트는 EVM이라고 하는 가상 시스템에서 실행되는 돈을 제어하는 프로그램이다. 컨트랙트는 블록체인에 바이트코드를 등록하는 특별한 트랜잭션에 의해 생성된다. 컨트랙트가 블록체인에서 생성되면 지갑과 마찬가지로 이더리움 주소를 갖게 된다.

누군가가 컨트랙트 주소로 트랜잭션을 보낼 때마다 그 트랜잭션을 입력 값으로 하여 컨트랙트가 EVM에서 실행된다.

 

트랜잭션에는 이더, 데이터 또는 둘다를 포함할 수 있는데 이더를 포함하면 해당 컨트랙트 잔액에 예치하고, 데이터라면 컨트랙트에 지정한 함수의 인수로 전달하게 된다. 

 

 

 

 

'블록체인' 카테고리의 다른 글

Web2 vs Web3  (0) 2021.10.27
[마스터링 이더리움] 1장 이더리움이란 무엇인가  (0) 2021.10.19
이중 지불 문제  (0) 2021.10.11
테라와 미러 프로토콜  (0) 2021.10.11