Setup
1 | vi ~/.bash_profile |
Type
type assertion
1 | variable.(type) |
Goland
Gland 자동 copy right
Preferences
- Editor
- File and Code Templates
- Files
탭에서 Go File
클릭 - package ${GO_PACKAGE_NAME}
앞에 copyright 주석을 추가하시면 됩니다!
1 | vi ~/.bash_profile |
type assertion
1 | variable.(type) |
Gland 자동 copy right
Preferences
- Editor
- File and Code Templates
- Files
탭에서 Go File
클릭 - package ${GO_PACKAGE_NAME}
앞에 copyright 주석을 추가하시면 됩니다!
가상화폐에 대한 관심이 높아지면서 많은 사람들이 블록체인 기술에 대해 이야기합니다. 누군가는 새로운 화폐경제의 도래에서 블록체인의 의미에 대해 열변을 토하며 진정한 의미의 경제의 민주화를 이야기하고, 누군가는 단순한 투기의 대상으로써 일확천금을 기대하며 인생역전의 기회에 대해 이야기 합니다.
하지만, 가상화폐는 블록체인 기술의 막대한 활용처 중 일부에 불과하며, 진정한 의미에서 블록체인 기술이 가지는 사회 경제적 의미를 알기 위해서는 블록체인의 ‘기술’ 그 자체로서의 의미와 역사에 대한 이해가 반드시 수반되어야 할 것입니다.
이번 글에서는 ‘가상화폐’를 넘어 블록체인 ‘’기술’ 자체에 주목하여, 기본적인 기술 철학과 개념에 대해 이야기해 보고자 합니다.
현대 사회에서 일어나는 모든 일들은 사실 개인과 개인 사이의 약속과 합의에 관한 문제를 다룬다고 보아도 무방할 것입니다.
인간은 사회적 동물로써 최대 다수의 최대 행복을 추구하기 위한 수많은 사회적 계약을 체결하였고, 현대 사회의 윤리와 법 비즈니스는 이런 사소한 약속들의 집합체에 불과한 것입니다.
이렇게 인간 사회에서 약속과 계약, 거래라는 것이 중요해 짐에 따라 이를 보다 효율적으로 수행하기 위한 수많은 방법들이 도입되었는데, 과거 조개 껍데기가 화폐로 쓰이던 시절부터 오늘날의 주주 명세서에 이르기까지 개인과 개인부터 국가 단체 사이의 거래까지 모든 계약의 신뢰를 보장하고 많은 사람들이 합의를 이루기 위한 각종 형태의 매개물이 생겨나게 되었습니다.
블록체인 기술이 본질적으로 해결하고자 하는 문제도 이와 같은 사회적 의미를 가지며, 그 본질적인 원리는 고대 그리스에서 사회적 합의를 도자기 조각에 적어서 투표를 하던 것 그 이상도 이하도 아닙니다. 다만 물리적인 한계로 과거에는 소수의 사람들만이 도자기에 의사를 적어 선별된 소수끼리만 합의를 이룰 수 있었던 반면, 현대에는 분산 컴퓨팅과 네트워크 속도의 향상 등의 기술적 진보를 통해 이 과정이 과거에 비교할 수 없이 빨라졌으며, 이를 통해 일부의 선별된 집단의 구성원만이 아니라 모든 사람들의 의사를 효과적으로 반영할 수 있는 합의 시스템이 만들어 지게되었는데, 그것이 바로 블록체인 기술이 주는 핵심적인 의미입니다.
즉, 기술의 발전으로 수천 수만의 사람들이 서로간에 완벽하게 투명하게 의사를 교환하고 수렴에 이를 수 있게 된 것입니다.
하지만, 막대한 컴퓨팅 기반으로 수많은 거래와 계약을 모두가 인정하는 합의를 이루는 데에는 과거에는 없던 새로운 문제가 발생하게 되었는데 그것은 바로 모든 거래와 계약의 순서를 올바르게 지키는 것입니다. 수억대의 컴퓨터가 각각의 계약과 거래를 체결하고 이를 모든 컴퓨터와 공유함에 따라 어떤 계약이 먼저 일어났는지를 올바르게 유지하는 것은 매우 어려운 일이며 이를 해결하기 위한 다양한 시도들이 진행되었습니다.
이처럼 블록체인 에서는 위에서 수많은 거래, 계약들이 발생하게 되고, 그 모든 활동을 트랜잭션(transaction) 이라고 부르며, 그 순서와 신뢰도를 보장하여 수많은 컴퓨터들이 합의에 이르도록 해 주는 합의 알고리즘을 필요로 합니다.
블록체인 내에서 일어나는 트랜잭션의 진실여부와 올바른 순서로 일어났는지에 대한 합의를 이루는 방법을 합의 알고리즘 이라고 합니다. 사실 블록체인이 생겨나기 전에는 이러한 모든 합의를 거대한 중앙기관(가령 은행이라는 통화 거래의 중심점) 에게 위임하고 그들이 판단하는 것을 진실로 약속하여 문제를 해결해 왔지만, 블록체인은 이러한 거대 기관이 아닌 진정한 의미에서의 민주주의라는 철학적 관점으로 모든 사람들의 합의를 진실로 규정하고자 하기에 이를 수행하기 위한 합의 알고리즘의 중요성이 강조됩니다.
그렇다면 어떤 블록체인이 우수한 블록체인이라고 불릴 수 있을까요?
블록체인의 성능을 이야기 함에 있어 우리는 TPS(초당 트랜잭션 처리량) 에 대해 이야기 하며, 구체적으로 보자면 블록체인에서 하나의 블록에 속하는 트랜잭션의 수를 그 블록이 생성되는데 걸리는 시간으로 나눈 값으로 이해하면 됩니다. 하지만 이것은 불확실한 정의이며, 가령 특정 블럭이 생성된 이후에 블록이 폐기된다면 해당 트랜잭션은 무효처리 되는데 이 빈도가 많고 적음에 따라 실질적인 TPS를 따지는 데 영향을 미치게 됩니다.
얼핏 생각하면 블록은 어차피 컴퓨터가 만드는 것이고 단순히 임의로 블록을 빠르게 만들어 내도록 하면 더 빠르게 거래가 이루어 질 수 있다고 생각될 수 있습니다.
하지만, 여기서 생각해보아야 할 문제가 있는데 그것은 바로 컴퓨터 사이의 통신 속도입니다.
가령 1억대의 컴퓨터가 있고, 어떤 컴퓨터에서 거래가 일어나 그 거래가 가장 멀리 떨어진 노드에 전파되는 속도가 블록이 생성되는 속도에 비해 너무 길다고 생각해 봅시다. 그렇다면 어떤 거래에 대한 내용을 모든 네트워크 구성원이 인지하기도 전에 거래가 승인되고 그런 거래는 그 신뢰도에 문제가 생기게 될 것입니다. 때문에 전체 네트워크를 구성하는 노드들 사이에서 신뢰를 획득할 수 있을만큼 트랜잭션의 전달(propagation)하는 시간이 주어져야 하며 그 시간보다 블럭이 생성되는데 걸리는 시간이 길어야 신뢰할 수 있는 블럭을 생성할 수 있습니다.
그렇다면 어떻게 블록체인의 성능을 향상시킬 수 있을까요?
블록체인의 성능을 향상시키는 방법에는 다음과 같이 크게 3가지 방법이 있습니다.
먼저 전체 네트워크에서 특정 거래가 전파되는 속도를 향상시키기 위해서 네트워크를 작게 나누는 방법을 생각할 수 있습니다. 가령 어떤 학교에서 합의를 이루어야 하는 내용을 각 반별로 합의를 이루는 것으로 축약하고, 각 반의 구성원을 특정 숫자 이상으로 유지한다면 어느정도 믿을만한 합의가 이루어질 것인데, 이것을 블록체인에서는 샤딩 이라고 합니다.
현재 이더리움 재단에서 이러한 샤딩을 추진하고 있으며, 누구나 합의 과정에 참여 가능하도록 하자라는 철학을 가지고, stateless client(full state를 들고 있지 않고, state root 및 트랜잭션 정보만을 가진 노드) 도 검증을 수행할 수 있게 하였으며, 트랜잭션에 witness라는 값을 두어서 어떤 노드가 변경이 일어나는지를 추가합니다.
즉, 샤딩은 블록체인 네트워크를 쪼게어 각각 순서를 정하여 합의를 이루고 나중에 합치는 방식으로 네트워크 속도를 향상시킵니다.
다른 방법으로는 어떤 대규모 블록체인 안에서 소규모의 체인을 독자적으로 형성하고 그들사이의 합의 내용을 대규모 블록체인에 전달하는 방식이 있는데 이것을 사이드 체인 이라과 합니다. 이는 마치 중앙 정부와 시민 자치단체의 예로써 설명될 수 있는데, 시민 자치단체의 일정 수 이상의 구성원들이 완벽하게 합의를 이룬 사항에 대해 중앙 정부에 전달하고 이에대한 합의를 진행한다면, 전체 사회 내에서 시민단체에 속한 사람들 사이의 완벽한 합의를 도출하고 그 결과를 중앙정부에 합리적이고 투명하게 전달할 수 있게 될 것입니다.
세번째 방식인 스테이트 채널은 거래 당사자들끼리 합의를 이루고 그 정보를 전체 체인에 올리는 방식입니다.
이처럼 위 방법들은 네트워크를 쪼개어 순서 문제를 해결하고 propagation 속도를 높여 성능을 증가시키고자 하지만, 이 경우 전체 네트워크를 구성하는 노드가 적어지기 때문에 거대 네트워크일 때보다 그 신뢰도가 내려가고 여러가지 문제가 발생할 수 있는 단점이 있습니다.
흔히 사람들이 블록체인은 안전하지만 아직 너무 느리다는 이야기를 듣고는 하는데, 일반적으로 거래는 일어나는 즉시 블록체인에 기록하고 합의를 진행하는데 그것이 그렇게 오래 걸리나 하는 의문이 드는 것은 매우 당연한 일입니다.
과거 은행들이 개인의 거래를 누군가와의 합의 없이 자신들의 내부 DB의 정보만을 바꾸는 것으로 거래를 수행하던 것과는 달리 블록체인은 모든 사람의 거래 내역을 하나의 거대한 줄기인 블록들의 체인에 기록하는 것으로 합의가 올바르게 이루어 지지 않는 경우 하나의 줄기가 계속해서 여러 갈래로 나뉘고 다시 합쳐지는 것을 반복합니다. 즉, 이미 일어난 거래라도 블록이 나뉘고 합쳐지는 과정에서 소실될 수 있는 확률이 생기는데, 이는 화폐의 거래에는 매우 큰 이슈입니다. 때문에 블록체인을 통해 화폐를 거래하는 현대의 많은 체인들의 경우 여러 특정 거래가 나뉘지 않고 큰 하나의 줄기로 이어질 확률인 finality 라는 개념을 사용하며 finality 가 낮을 수록 거래가 확정될 확률이 높다고 보며, 비트코인에서는 이러한 finality를 위해 블록이 현재 거래가 발생한 시점부터 6개 이상이 생겨나게 되면 finality가 0.02 이하이기 때문에 확정된 거래로 보고 있습니다.
잘 생각해 보면 이러한 finality는 TPS 속도에 무관함을 알 수 있는데, 거래가 아무리 빨리 일어난다고 하더라도 그만큼 믿을만한 블록들이 생겨나는것은 다른 문제이기 때문입니다. 가령 TPS가 아주 높은 블록체인에서 거래를 하더라도 거래가 빠른 만큼 블록들이 많이 생겨야 finality가 특정 수치 이상으로 낮아질 것이고, TPS가 낮은 블록체인에 비해 더 많은 블록들이 생겨나야 거래가 확정될 수 있습니다.
이러한 finality 를 빨리 단축시키는 방법, 즉 이상적으로 즉시 결제가 일어나기 위해서 많은 방법들이 시도되고 있으며 그 활용 현황은 다음과 같습니다.
첫번째 방식을 사용하는 대표적인 사례는 비트코인 캐시가 있습니다. 비트코인 캐시는 트랜잭션을 받자마자 바로 순서를 인정하며 사용자의 지갑의 값을 변경하는 것으로 즉, finality가 확보되지 않은 상태에서 거래가 진행이 되며 추후 이것이 바뀌면 지갑에서 값이 바뀔 수 있는 문제가 있습니다.
두번째 방식은 DAG 알고리즘을 활용하는 것입니다. DAG 알고리즘에서는 블록단위로 거래를 기록하는 것이 아닌 트랜잭션 단위로 거래를 기록하기 때문에 사실상 실시간으로 거래가 일어날 수 있습니다. 블록체인이 하나의 큰 줄기를 만들어 역사를 기록하는 반면 DAG는 복잡한 거래를 DAG 그래프의 확장으로 보고 모든 노드는 자신에게 관련이 있는 거래만을 가지고 거래를 직접 검증하며, 이경우 블록의 합의 라던가 하는 부분이 이루어 지지 않기 때문에 사실 블록체인으로 보기는 힘든 측면이 있습니다.
세번째 방식은 갈라진 두개의 블록을 병합하여 하나의 블록의 만드는 방식으로 국내 decipher라는 블록체인 학회에서 연구가 진행중에 있습니다.
블록체인이란 기본적으로 transaction으로 인해 변경되는 state를 기록하는 state machine입니다.
여기서 state의 종류에 따라 다양한 state model이 있는데, 다음과 같이 3가지 종류로 구분이 가능합니다.
먼저 UTXO state model은 비트코인이 쓰고 있는 모델로 트랜잭션의 아웃풋 자체가 토큰이고 토큰을 사용하였는가 안하였는가를 현재의 상태로 보고, 이것이 다른 트랜잭션의 인풋으로 들어가면 소비가 된 것으로 봅니다.
Account 모델에서 모든 state는 account에 종속되어 있습니다. 각 account는 자신만의 고유의 nonce 를 가지며, 해당 account의 public key가 키값으로 사용된다. 즉 트랜잭션의 내용은 어떤 account가 가진 잔고에 대한 정보가 되며 이러한 수많은 계정 내역으로 블록체인이 이루어 진다. 이 경우 누가 얼마를 가졌는지를 바로 알 수 있기 때문에 편리한 점이 있지만, 프라이버시 부분에서 좋지 못한 부분이 있습니다.
마지막 모델은 memory 모델인데, 이 경우 트랜잭션은 256비트 짜리 address를 다루며, 각 컨트랙트는 특정 주소값을 할당받고, 여기서 트랜잭션이란 해당 주소값을 변경하는 내용을 기록합니다. 여기서의 키는 각 컨트랙트의 주소가 되며 현재 이더리움 재단에서 이러한 memory 모델과 account 모델을 차용하여 사용하고 있습니다.
블록체인은 사실 블록들의 연결에 불과하고 모든 블록은 컴퓨터에 저장됩니다.
그렇다면 블록체인은 우리 컴퓨터에 어떤 정보들을 어떻게 저장하고 있을까요?
블록체인은 크게 다음과 같은 3가지 정보를 저장하고 있습니다.
위에서 알아본 바와 같이 블록체인은 상태값을 기본으로 저장합니다. 비트코인의 경우 트랜잭션만 저장하고 읽기 작업은 알아서 수행하는 반면 이더리움의 경우는 트랜잭션이 완료된 후의 현재 상태도 저장을 하여 보다 빠르게 데이터를 읽어 올 수 있게 합니다.
위와같은 정보는 대부분의 블록체인에서 키와 밸류 쌍으로 저장되며, 복잡한 쿼리문을 통해 정보를 읽는 등의 기능이 필요하지 않고 단순히 정보를 저장하고 꺼내오는 역할만 수행하므로 가벼운 데이터베이스인 키밸류 db를 사용하며, 흔히 leveldb 를 사용하고 있습니다
LNH
이 저작물은 크리에이티브 커먼즈 저작자표시-비영리-변경금지 4.0 국제 라이선스에 따라 이용할 수 있습니다.
c 에서 포인터를 통해 직접 데이터의 주소에 접근할 수 있으며, 이러한 특성 때문에 C 언어가 low 하다고 불린다.
1 | int main(void) |
이처럼 특정 자료를 가리키는 자료형을 정의 할 수 있고, 이를 포인터라 한다.
포인터는 특정 자료형을 가리키고 있다.
여기서 포인터는 어떤 변수를 가리키는 그 자체이므로 메모리의 특정 주소값을 가진다.
때문에 포인터를 선언할 때에는 매우 신중해야 하는데 선언 후 아무 값도 할당 하지 않는다면 포인터는 쓰레기 값으로 초기화 되기 때문이다.
1 | int *pnum = 399; |
가령 위와 같은 코드는 매우 위험한데 이는 pnum이라는 포인터에 399를 할당하고 있고, 우리는 399 의 주소값이 얼마나 중요한 주소인지 전혀 이해하고 있지 못하기 때문이다. 이를 해결하기 위해 반드시 우리는 해당 포인터 값이 이상한 값을 가리키지 않도록 해야 하는데 주로 다음과 같이 널 포인터를 지정해 준다.
1 | int *ptr2 = 0; |
위와 같이 NULL 혹은 0 으로 초기화 하면 시스템은 이것을 0 번째 주소값으로 인식하지 않고 아무것도 가리키지 않는 포인터를 만들어 낸다.
c 언어에서 배열의 이름은 그 자체로 포인터 이며, 정확히 말하면 배열의 첫번째 요소의 주소값이다.
1 | int arr[3] = {1, 2, 3}; |
변수 형태의 문자열 vs 상수형태의 문자열
1 | char str1[] = "my string"; |
위처럼 모든 문자열 혹은 배열을 선언하면 그 자체는 그 문자열 혹은 배열의 첫번째 요소의 주소값이 된다.
하지만 위에서 처럼 문자열 혹은 배열 자체를 선언하는 경우와 그것의 주소값을 선언하는 경우에 따라 그 값의 변경 가능 유무가 결정이 된다.
위의 예처럼 str1의 경우 문자열 자체를 저장한 변수형 문자열이며, str2의 경우 문자열에 대한 주소값을 저장하는 상수 형태의 문자열이기 때문에 가리키는 값의 내용이 변경될 수 없다.
다음과 같이 포인터 변수로 이루어진 배열을 선언할 수 있다.
1 | char * strArr[3] = {"Simple", "String", "Array"}; |
위처럼 “” 로 감싸진 문자열은 그 자체로 주소값을 나타내기 때문에 위와 같은 결과가 나오게 된다.
큰 따옴표로 묶여서 표현되는 문자열은 그 형태에 상관없이 메모리 공간에 저장된 후 그 주소값이 반환된다.
1 | npm install --save ejs |
1 | app.set('views', __dirname + '/views'); |
vue.js 란 user interface를 구축하기 위한 혁신적인 프레임워크 입니다.
다른 프론트엔드 라이브러리가 큰 규모로 매우 조직적이고 짜임새있는 프레임웍을 추구하는 반면 vue 는 기존의 프로젝트에 매우 쉽게 적용 가능한 유연성을 가진 프레임워크로 각광받고 있습니다.
vue는 다음과 같이 cdn을 통해 가볍게 시작할 수 있습니다.
1 | <script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script> |
1 | npm install vue |
Vue instance 는 순수한 자바스크립트 객체이며 vue 에서의 데이터 바인딩은 vue instance 의 루트 프로퍼티로 할당된다.
즉, 인스턴스가 생성된 이후에 뷰에 프로퍼티를 추가하게되면 이는 트래킹 되지 않는다
그렇다면 어떻게 뷰는 데이터의 실시간 변경사항을 화면에 반영하는 것일까?
Vue instance 에 등록된 데이터가 변경되면 이는 내부적으로 작업큐에 들어가고 뷰의 다음 tick에 동작하게 된다. 여기서 틱이란 뷰가 데이터의 변화를 감지하고 화면을 다시 렌더링 하는 주기로 쉽게 말하면 일정 시간 간격으로 데이터의 변화를 체크하여 화면을 다시 렌더링 하는 것이다. 때문에 매우 적은 시간간격으로 데이터가 변경되면 즉, 한번의 틱 내에 같은 데이터가 여러번 변화된다면 vue는 최종으로 변화된 것만 큐에 저장하고 다시 rendering 하기 때문에 화면은 한번만 렌더링 되게 된다.
이 경우에는 뷰 인스턴스의 nexttick같은 함수를 사용하여 바로 다음 틱에 적용되도록 할 수있다
만약 vue-loader혹은 vueify를 사용한다면 *.vue 파일은 빌드 시점에 js 파일로 precompile 됩니다.
다음의 webpack 의 vue loader를 통해 pre compile을 하는 방법입니다.
vue 파일은 html 과 같은 문법을 사용하여 vue 컴포넌트를 작성하며 3가지 유형의 최상위 language block 인 ,
npm install webpack webpack-cli --save
웹개발을 하면서 수많은 파일에 수많은 코드를 작성하게 된다. 하지만, 코드를 배포하기 위해서는 최대한 작은 용량으로 파일을 배포해야 하며 이를 위해 우리는 minify 혹은 uglify 등을 통해 파일을 작은 용량으로 압축해서 배포한다.
이 과정은 상당히 번거로우며 수많은 파일들을 하나의 파일로 만들 수 없을 뿐 아니라 모든 파일마다 압축을 수행해야 하는 단점이 존재한다. 또한 단순 js 파일 뿐 아니라 css, scss, png, jpg 등 다양한 스타일링 및 static asset들을 포함하면 그 양은 매우 막대한 양이 아닐 수 없으며, compile 이 필요한 다양한 framework 이 만들어 내는 수많은 자동생성 파일들을 올바르게 배포하는 것은 여간 어려운 일이 아니다.
webpack은 점차 복잡해져가는 개발 환경에서 발생하는 복잡한 상관관계를 모두 합쳐 단 하나의 파일로 bundle시켜주는 module bundler 이며 많은 framework들이 이를 차용하고 있다.
다음은 webpack 공식 홈페이지에서 제공하는 예제코드이며 몇줄의 코드를 통해 webpack이 어떤 역할을 하는지 단번에 이해할 수 있다.
src/index.js
1 | import bar from './bar' |
src/bar.js
1 | export default function bar(){ |
webpack 설정 파일 webpack.config.js
1 | const path = require('path'); |
page.html
1 | <!doctype html> |
위처럼 여러개의 js 파일을 하나로 bundle 하여 단 하나의 js 파일만을 import 할 수 있게 된다.
webpack은 내부적으로 프로젝트 내의 상관 관계를 graph 로 작성하여 번들링을 진행한다.
webpack 이 번들링을 시작할 파일이며, 모든 상관관계가 이 파일로 부터 시작된다. 흔히 project의 index.js 파일에 비유될 수 있다.
example
1 | module.exports = { |
output 은 webpack에게 생성된 bundle 을 어디에 위치시킬 지 가르쳐 준다.
초기 설정은 ./dist 로 되어 있으며 main.js 파일을 생성시킨다.
webpack은 오직 js 파일만을 식별이 가능하지만, bundling을 진행하기 위해서는 다양한 파일 형식을 load 할 수 있어야 하는데 이것은 loader의 도움을 받아 처리될 수 있다.
가령 babel-loader 와 같이 typescript 를 transpiling 을 담당하는 것들이 있다.
1 |
|
여기서 test는 어떤 파일을 읽어들일지를 말해주며, use 는 어떤 loader를 사용하여 읽어들일 지를 결정한다.
module이 특정 형식의 모듈을 변형시키는 데에 사용되는 반면, plugin은 bundling optimization 등 보다 넓은 범위의 태스크를 처리한다.
1 | const HtmlWebpackPlugin = require('html-webpack-plugin'); //installed via npm |
여러개의 플러그인을 array 형태로 추가할 수 있으며, 반드시 new keyword 를 통해 인스턴스를 생성해서 넣어주어야 한다.
mode parameter 는 어떤 모드로 bundling 을 진행할지를 알려준다.
develop, production 등의 모드가 있으며 기본 값은 production 이다.
1 | npm install --save-dev babel-loader babel-core |
webpack.config.js
1 | module: { |
1 | sudo npm install babel-preset-env --save |
babelrc.js
1 | { |
1 | sudo npm i css-loader --save |
webpack.config.js
1 | module: { |
1 | webpack-cli --config webpack.config.js |
sequelize 에서 객체를 기반으로 데이터 입출력을 하기 위해 model을 정의한다.
1 | npm install -- save sequelize |
1 | const Sequelize = require('sequelize'); |
1 | const User = sequelize.define('user', { |
1 | User.findAll().then(users => { |
Open Source Blockchain Engine인 It-chain 의 두번째 포스트입니다.
이번 포스트에서는 IT-CHAIN에서 블록의 합의를 담당하는 Blockchain component에 대해 알아보겠습니다.
블록체인에서 일어나는 모든 거래는 Transaction이라고 불리며, 하나의 블록은 여러 Transaction들의 집합으로 구성됩니다.
때문에 블록체인에서는 생성된 블록이 올바른 블록인지 확인하고 체인에 추가하는 과정이 필요하며, 이 과정은 It-chain의 Blockchain Component에서 이루어 집니다.
또한, It-chain에서는 블록의 저장 및 조회를 위한 별도의 라이브러리를 구현하였으며, Blockchain Component는 yggdrasill에서 정의한 interface에 맞게 구조체를 구현한다면 yggdrasill에 block을 저장, 조회할 수 있습니다.
yggdraill에 연속적으로 저장된 block들을 우리는 blockchain이라고 부릅니다.
Blockchain Component에서 Block은 다음과 같은 상태로 존재합니다.
Block State | Description |
---|---|
Created | 합의되지 않았고, blockchain에 저장되지 않았다. |
Staged | 합의되었지만, blockchain에 저장되지 않았다. |
Committed | 합의되었고, blockchain에 저장되었다. |
위에서 언급한 바와 같이 블록체인 네트워크를 구성하는 노드들은 계속해서 새로운 블록들을 합의하는 과정중에 있고 합의가 완료되며 오직 리더 노드 에서 블록을 생성하여 다른 노드들에게 전파하고 블록을 받은 노드는 자신이 생성한 블록과 비교하여 검증여부를 판단합니다.
즉, 각 노드에서 막 생성된 블록은 Created 상태에 있으며, 이 블록을 Consensus 알고리즘을 통해 합의를 이루고 합의가 완료되며 Staged 상태로 바뀌게 됩니다.
Staged 상태의 블록이 실제 yggdrasill 내의 데이터베이스에 저장된다면, 블록은 Commited 상태로 변경됩니다.
동기화(Synchronize)는 특정 노드의 블록 체인을 네트워크 내 임의의 노드의 블록 체인과 동일하게 만드는 과정을 의미합니다.
동기화(Synchronize) 과정의 목적은 모든 블록에 대하여 대표값(Seal), 이전 블록의 대표값(PrevSeal), 트랜잭션 모음(TxList), 트랜잭션 대표값(TxSeal), 블록 생성 시각(TimeStamp), 생성자(Creator), 블록 체인의 길이(Height) 등의 블록 체인과 관련된 모든 정보들을 다른 노드의 것과 같게 만드는 것에 있으며, 이를 통해 블록체인에 참여하는 모든 노드가 같은 블록의 모음을 가지게 될 수 있습니다.
동기화(Synchronize)는 다음과 같이 확인(Check), 구축(Construct), 재구축(PostConstruct) 의 과정을 거칩니다.
확인(Check)
특정 노드의 블록 체인이 동기화가 필요한 상태인지를 점검합니다. 이 과정은 임의의 노드에게 Blockchain 길이와 lastSeal을 받아와서 자신의 블록 체인 정보가 같은 지 비교하여, 동기화가 필요한 상태인지 점검하는 것으로, 이미 동기화가 완료된 상태라면, 동기화(Synchronize) 과정을 중단하고, 그렇지 않을 경우, 구축(Construct) 을 수행합니다.
구축(Construct)
구축에소는 임의의 노드에게 블록 정보를 요청하여, 응답받고, 응답받은 블록을 블록 체인에 저장하는 과정을 반복합니다.
블록 요청은 특정 노드의 블록 체인 길이(Height)를 활용해, 임의의 노드에 블록을 요청함으로써 수행되며, 특정 노드가 새로 참여하는 노드일 경우 임의의 노드의 블록 체인 내 최초 블록부터 마지막 블록까지 요청하고, 기존에 참여중이던 노드일 경우 보유 중인 블록 체인 내 마지막 블록의 다음 블록부터 임의의 노드의 블록 체인 내 마지막 블록까지 요청합니다.
임의의 노드의 모든 블록이 특정 노드의 블록체인에 저장되면 구축(Constrcut)이 완료됩니다.
특정 노드는 구축(Construct) 의 진행 중에 새롭게 합의되는 블록을 블록 임시 저장소(BlockPool)에 보관하며, 구축(Construct) 이 완료되고 나면, 블록 임시 저장소에 블록이 보관되어 있는 지 확인합니다. 보관중인 블록이 있다면, 재구축(PostConstruct)을 수행합니다.
재구축(PostConstruct)
이미 구축(Construct) 된 블록 체인에 블록 임시 저장소(BlockFool)에 보관중인 블록들을 부수적으로 추가하는 것을 의미하며, 재구축(PostConstrcut) 을 수행하고 나면, 동기화(Synchronize) 과정이 모두 완료됩니다.
이번 포스트에서는 It-chain 내에서 블록의 검증과 저장을 수행하는 Blockchain 컴포넌트에 대해 알아보았습니다.
다음 포스트에서는 it-chain에서 dApp을 발행하고 실행하는 ivm 컴포넌트에 대해 알아보겠습니다.
It-chain: https://github.com/it-chain/engine
Opensource Blockchain Engine It-chain 시리즈
LNH
이전 자바스크립트 버전에서는 변수를 선언하는 유일한 방법은 var 이었지만 ES6에서는 다양한 변수선언 방법을 선언하며 다음은 몇가지 새로운 변수 선언 방법이다.
다른 언어와 마찬가지로 ES6에도 const를 정의할 수 있다.
const 를 사용하여 한번 선언된 변수가 덮어씌워질 수 없도록 강제할 수 있다.
ES6 에서는 let 을 사용하여 전역 변수를 보호할 수 있다.
가령 var 를 사용하면 다음과 같이 전역 변수가 덮어씌우 지지만
example
1 | var test = 'global' |
다음과 같이 if 문 안에서 let을 사용하면 전역변수를 보호할 수 있다.
1 | var test = 'global' |
기존 javascript 에서는 문자열과 변수를 함치기 위해 string의 덧셈 연산을 통해 수행하였지만.
ES6 문법에서는 ${}
와 같은 스트링 템플릿을 통해 변수를 스트링에 전달할 수 있다.
1 | var name = 'jhon' |
arrow function 을 통해 한 줄에 함수를 선언할 수 있다.
arrow function 은 여러 방면에서 매우 편리한데, 가령 리턴을 생략해도 자동으로 해당 내용이 리턴으로 들어가며, 만약 input 변수가 하나인 경우 괄호 마저 생략이 가능하다. 뿐만 아니라 arrow function 은 this의 사용을 방해하지 않기 때문에 this를 사용하면 함수 밖의 context에 바로 접근이 가능하다.
1 | // Old |
아직 많은 브라우저에서 ES6 문법을 지원하지 않고 js는 계속해서 빠른 속도로 변화하고 있기 때문에, 이를 사용하기 위해서는 ES6 문법을 ES5 문법으로 transpile 해주어야 한다. 이러한 작업은 주로 babel 을 통해 이루어 진다.
이러한 transpile은 브라우저 레벨에서 이루어 질 수 도 있고, 서버단에서 transpile 후에 클라이언트로 전달해 주기도 하는데 전자의 경우 간편하게 처리 가능하다 성능면에서 productiondp 레벨에서 사용하기에는 많은 문제가 있다.
전자의 경우 다음코드를 html 에 추가함으로써 간편하게 transpile이 가능하다.
1 | <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.js"> |
ES6 에서는 object와 array를 보다 편리하게 사용하기 위한 다양한 문법을 제공한다.
객체 혹은 배열 내의 자료에 접근하기 위한 매우 편리한 방법인 destructuring assignment를 제공한다.
과거의 경우 일일히 해당 프로퍼티에 접근하여 하나씩 엔티티를 가져와야 했다면, 이 방법을 통해 간편하게 entity를 추출할 수 있다.
1 | // destructuring assignment in object |
ES6 에서는 오브젝트 내에서 함수 및 엔티티를 지정함에 있어 훨씬 편리하다
다음과 같이 외부의 변수를 간편하게 객체 내에 추가할 수 있고, 함수의 선언도 간편해 졌다.
1 | var name = 'namhoon'; |
spread operator(…variable) 을 통해 간편하게 배열을 다룰 수 있다.
과거 js에서는 배열 혹은 객체 내의 다양한 인자들을 명시하거나 변경하기 위해 필요없는 다를 항목들까지 일일히 명시해야 했다면, spread operator는 우리를 이러한 귀찮음에서 해방시켜 준다.
이런한 spread operator는 다양한 경우에 사용될 수 있으며, 다음은 그 사용 사례이다.
1 | var peaks = ["Tallac", "Ralston", "Rose"] var canyons = ["Ward", "Blackwood"] |
1 | var peaks = ["Tallac", "Ralston", "Rose"]; |
1 | function directions(...args) { |
1 | var morning = { |
이전 버전의 js에서는 class 가 존재하지 않았기 대문에 클래스가 필요한 경우 함수를 만들고 해당 함수에 대한 프로토 타입을 정의하는 방식으로 클래스를 만들어 사용했다.
하지만 ES6 부터는 정식을로 Class 를 지원하며 다른 클래스를 extends 할 수 있어 인터페이스의 개념도 추가되었다.
여기서 extends 를 사용하는 경우 construct를 다른 함수에서 super() 를 사용해야 하며, 그 사용사례는 다음과 같다.
1 | class Expedition extends Vacation { |
이전 버전의 js 에서는 외부 라이브러리를 가져오는 방법으로만 import 가 가능했지만, ES6 부터는 정식으로 module 을 제공하고 있다.
특히 같은 파일 내에서 여러 개의 모듈을 export 하는 것도 가능하며, object destructuring 을 통해 간편하게 import 할 수 있으며, 특정 모듈을 원하는 이름 으로 import 하는 것도 가능하다.
다음은 그 사용사례를 보여준다.
1 | import { print, log } from './text-helpers' |
과거버전의 js와 ES6 에서 통용되는 Common.js는 module.exports
를 사용하여 module을 export 하는데 주의할 점은 이렇게 export된 module은 import
를 통해 import 될 수 없다는 것이다. 그 대신 아래와 같이 require를 사용하여 import를 해야 한다.
1 | const { log, print } = require('./txt-helpers') |
많은 라이브러리들이 common.js 를 기반으로 export 되었으므로, 외부 라이브러리를 사용할 때 무분별하게 import 문을 사용하면 import 되지 않는 문제가 있으니 특히 주의해야 한다.
react 란 정적인 html 페이지를 js 라는 스크립트 언어를 통해 동적으로 redering 하기 위한 라이브러리이다.
react의 핵심은 단순히 browser라는 환경이 아닌 많은 환경에서 html 페이지를 렌더링 할 수 있게 하여 보다 다양한 환경에 쉽게 rendering 될 수 있는 페이지를 만드는 것이다. js 는 일반적으로 DOM API
를 통해 화면을 렌더링 하는데 흔히 document.createElement
와 같은 명령어들이 대표적이 예이다. 우리는 react가 제공하는 함수들을 통해 렌더링을 제어하며 react 는 우리를 대신하여 효율적으로 DOM APU
를 컨트롤 하여 매우 효과적으로 렌더링을 제어한다. 우리는 react가 제공하는 virtual dom 환경을 통해 렌더링을 조작하며, 이러한 virtual dom
을 사실 단순한 javascript object에 불과하다.
리액트는 매우 효율적으로 DOM API
를 통해 렌더링을 수행하며, 대표적으로 페이지를 리 렌더링하는 시점에 바뀐 부분과 바뀌지 않은 부분들을 파악하여 반드시 필요한 부분에 대해서만 rerendering을 수행하게 되므로 브라우저의 한정된 자원을 효율적으로 사용하여 클라이언트 효율을 올려준다.
react는 DOM API
의 element에 매칭되는 독자적인 element를 가지며 이는 js object이다.
이러한 element 및 component들은 직관적으로 html element 를 조작하는 것과 같은 환경을 제공해 준다.
facebook 은 보다 직관적인 html 작성을 위해 jsx라는 독자적인 언어를 만들었으며, 이를 통해 우리는 마치 html을 작성하는 것과 같은 환경에서 react 의 virtual dom을 제어할 수 있게 되었다.
여기서 load란 build 과정에서 우리가 작성한 코드를 브라우저가 읽을 수 있도록 변형해주는 것을 의미한다. webpack은 다양한 환경에서 동작하기 위해 막대한 양의 loader 들을 가지고 있으며, 적절한 변환을 위해 우리는 webpack.config.js
파일을 작성하여 webpack에게 어떤 내용을 변형시켜 줄 지를 말해준다. 대표적인 loader 로는 ES6 과 React 분법을 ES5 로 변형시켜 주는 babel-loader와 scss 언어를 css 로 변형시켜주는 css-loader가 있다.
webpack 설치하기
sudo npm install -g webpack
loader 설치하기
npm install babel-core babel-loader babel-preset-env babel-preset-react babel-preset-stage-0 --save-dev
1 | // Example 5-20. webpack.config.js |
번들링 되는 파일의 용량을 줄이기 위해 웹팩은 띄어쓰기, 변수명 축약 등의 작업을 수행하는 플러그인을 내포하고 있으며, 이를 사용하기 위해서는 다음 명령어를 통해 webpack을 로컬로 설치해야한다.
npm install webpack --save-dev
위와 같은 웹팩 설정 등의 여타 작업들을 수행하는 것은 상당히 성가신 일이다. facebook은 개발자들이 빠르게 설정을 완료할 수 있도록 cli 환경을 만들어 두었으며, create-react-app 을 통해 간편하게 리액트를 시작할 수 있다.
create-react-app 은 transpile 과 uglify 등 webpack 이 수행하는 여타의 작업들을 모두 끝내주기 때문에 가볍게 react 개발을 시작할 수 있다.
Update your browser to view this website correctly. Update my browser now