이전 글에서는 이더리움을 설치하고 테스트넷을 통해 Ether의 발행부터 송금까지 다루어봤습니다. 여기서는 이더리움의 확장 기능인 Contract를 사용해 브라우저에서 동작하는 간단한 카운터 프로그램을 만들어 보겠습니다.
이더리움 스마트 컨트랙트
- 에이전트 방식으로 동작하는 Contract 프로그램을 블록체인에 배치할 수 있고 다양하게 동작하도록 프로그램밍할 수 있음
- 계정과 동일한 주소를 가지며 이 주소에 트랜잭션을 발행하여 동작을 수행함
- Contract는 geth 내부의 EVM(Ethereum Virtual Machine) 환경에서 동작
- EVM은 자바의 가상 머신(JVM: Java Virtual Machine)처럼 운영체제에 종속되지 않고 코드를 구동할 수 있음
- Contract 코드는 블록체인에 저장돼 네트워크를 통해 각 노드에 전파되므로 개별적으로 배포할 필요가 없으며, 이러한 특징을 통해 이더리움은 분산 응용프로그램 기술을 실현함
- Contract 프로그램은 Solidity라는 이더리움 공유의 언어를 사용(Serpent, LLL 등 여러 언어가 존재하지만 Solidity가 가장 활발함)
스마트 컨트랙트에 대해 잘 설명된 자료가 있어 링크해 드립니다.
개발 도구 준비
Contract 개발을 위해서는 브라우저 기반의 IDE인 Remix을 준비합니다.
브라우저 기반 Solidity IDE인 Remix 실행 화면
이 밖에도 다양한 개발 도구들이 있지만 Remix가 가장 활발하게 업데이트되고 있습니다.
Remix 기동
Remix는 브라우저 기반의 온라인 모드와 설치 파일을 다운받아서 로컬환경에서 실행할 수 있는 2가지 모드를 제공합니다. 여기서는 크롬이나 파이어폭스 등의 브라우저를 통한 온라인 모드를 사용을 하겠습니다.
처음 실행하면 기본으로 Ballot라는 Contract가 보입니다. 이 코드를 삭제한 뒤, 새 Contract를 입력하면 됩니다.
사파리 브라우저에서 Remix를 실행한 화면
Contract 작성
카운터를 1씩 증가시키는 간단한 Contract 코드입니다.
// 계정 관리용 Contract
contract CounterMaster {
// 계정 목록
// Contract는 주소를 지정해 호출해야하기 때문에 주소 및 카운터 Contract를 지원하는 맵 정보
mapping (address => Counter) private counters;
// 주소를 관리하는 배열
address[] private addressList;
// 카운터 Contract를 배열과 맵에 추가
function addCounter(bytes32 name) {
// 카운터 Contract를 작성
Counter c = new Counter(name);
// 배열에 주소를 추가
addressList.push(address(c));
// 매핑에 주소와 카운터 Contract 등록
counters[address(c)] = c;
}
// 카운터 Contract 주소 목록 가져 오기
function getCounterAddressList() constant returns
(address[] counterAddressList) {
counterAddressList = addressList;
}
}
// 카운터 Contract
contract Counter {
// 카운터 항목 이름
bytes32 counterName;
// 카운트 수
uint32 numberOfCounter;
// 생성자(신규 작성시에 카운터 항목 이름 설정)
function Counter(bytes32 name) {
counterName = name;
}
// 카운트 업
function countUp() {
numberOfCounter++;
}
// 카운터 항목 이름 검색
function getCounterName() constant returns (bytes32 name) {
return counterName;
}
//카운트 수 가져오기
function getNumberOfCounter() constant returns (uint32 number) {
return numberOfCounter;
}
}
화면에 표시된 Contract 소스 코드
Contract 배포
작성한 Contract를 배포합니다. JSON-RPC 서버 기동 옵션을 추가하고 geth를 기동합니다.
geth --networkid "123" --rpc --rpcaddr "172.16.234.28" --rpcport 8545 --rpccorsdomain "*" --rpcapi "net,eth,web3,personal" --datadir "eth_testdata" --testnet console
기동 후 miner.start() 명령으로 채굴을 시작합니다.
이제, Contract 코드를 기동한 로컬 블록체인에 배포해 보겠습니다.
화면 우측의 Run 메뉴를 클릭하고 Environment에서 Web3 Provider 옵션을 선택합니다.
Web3 Provider Endpoint 입력란에 geth 기동시 지정한 IP를 입력합니다.(port은 8545 default 사용)
여기서 아래와 같은 Web3 Provider에 연결할 수 없다는 메세지가 표시될 경우, Remix를 https가 아닌 http로 재접속 후 진행하면 정상적으로 연결이 됩니다.
CounterMaster 계약의 create 버튼을 누릅니다.
Remix 화면 하단의 콘솔창에 CounterMaster Contract가 생성됐다는 트랜잭션이 표시됩니다.
테스트 데이터 입력
테스트 데이터 입력전에 getCounterAddressList() 함수를 호출해 보면 데이터를 없는 것을 확인할 수 있습니다.
CounterMaster의 addCounter() 함수를 호출해 3개의 테스트 데이터를 입력해 보겠습니다.
위에서 3개의 테스트 데이터를 입력하고 getCounterAddressList()를 호출하면 아래와 같이 데이터가 입력된 것을 확인할 수 있습니다.