원래 적어도 이틀에 하나씩 글을 쓰려 했지만, 학기중 스케쥴이 은근 바빠서 실천하지 못했다..ㅠㅠ 여튼! 오늘은 Java Tree 구현법을 보려고 한다.

앞의 ArrayList, Stack, Queue를 모두 본 사람은 알겠지만, 우리는 정보를 담는 어떤 객체와 이 객체를 어떠한 구조를 사용하여 데이터를 저장할 것인가를 다룰 것이다.

트리 구조에서는 흔히 객체를 담는 구조를 노드라고 하며, 이를 가지로 연결하여 나무처럼 만든다 해서 트리라 부른다. 트리에 사용되는 용어는 다음과 같다.

root: 뿌리. 최상위 노드
parent: child node를 갖는 노드
child: parent node를 갖는 노드
edge: 노드를 연결하는 선, branch라고도 함
depth: root부터 어떤 특정 노드까지의 깊이
height: 해당 노드까지 트리의 높이 (level-1)
leaf: 자식이 없는 최말단 노드
degree: 자식 수

아 맞다. 구현하는 글을 쓰고 있었지. 트리의 개념은 따로 정리해서 글을 쓰겠다.


Top Down, Bottom Up

트리는 위에서부터 아래로 만들어 나가는 Top down 방식과 최말단 노드에서부터 위로 올라가는 Bottom Up 방식이 있다. 본 글에서는 탑다운 방식을 구현할 예정이다. Root를 먼저 만들고, 그 뿌리에 가지를 하나씩 이어나가는 방식으로 말이다.


Tree에는 어떤게 필요할까?

Full Binary Tree

나무(식물)을 떠올려보면, 모두 뿌리를 먼저 내리고 그 이후에 줄기, 기둥, 가지, 잎, 꽃, 그리고 열매를 만들어 나간다.

즉 우리는 먼저 트리의 뿌리, root를 먼저 내려야 한다. 따라서 root를 설정할 수 있어야 하고, 뿌리로부터 나머지 가지들을 칠 수 있어야 한다.

root를 설정하는건 생성자로 할 수도 있고, setRoot와 같은 함수를 통해 할 수도 있다.

가지를 치는 것은 부모에서 자식을 설정하는 것이고, (반대로 자식에서 부모를 찾는 기능이 추가적으로 있어도 된다!) 본 글에서는 이진트리(Binary Tree)를 구현할 예정이라 setLeft, setRight (혹은 addLeft, addRight)를 만들 예정이다.

추가로 있으면 좋을 기능에는 size, height, depth, 그리고 트리의 꽃인 순회 기능이 있다.

본 글에서는 size와 순회기능을 추가 구현하고, 늘 그렇듯 height와 depth는 간단하기 때문에 구현하지 않을 예정이다.


Tree의  Node!

우선 Tree를 책임질 Node를 만들 것이다. Node는 내 부모를 가리킬 수 있어야 하고, 내 자식들을 가리킬 수 있어야 한다.

상상해보라. 나무에서 가지가 끊어진 상태로 존재할수는 없다. 끊어진 나뭇가지는 본체와 아무관계가 없으며, 죽은 가지일 것이다! (마찬가지로 열매도 가지 혹은 꽃으로부터 떨어진다면 더 이상 나무와는 관계 없다.)

노드는 정말 나의 데이터를 설정하고, 부모와 왼쪽, 오른쪽 노드를 가리키는것이 전부이기 때문에 한번에 코드를 올린다.

public class Node<T> {
    private T element;
    private Node<T> parent;
    private Node<T> left;
    private Node<T> right;

    Node(T element){
        this.element = element;
        this.parent  = null;
        this.left    = null;
        this. right  = null;
    }

    Node(T element, Node<T> left, Node<T> right){
        this.element = element;
        this.parent  = null;
        this.left    = left;
        this.right   = right;
    }

    Node<T> setParent(Node<T> parent){
        this.parent = parent;
        return this;
    }

    T getElement(){ return this.element;    }
    Node<T> setElement(T element){ this.element = element; return this; }
    Node<T> getLeft(){ return this.left;    }
    Node<T> setLeft(Node<T> left){ this.left = left; return this; }
    Node<T> getRight(){ return this.right;  }
    Node<T> setRight(Node<T> right){ this.right = right; return this; }
    Node<T> getParent(){ return this.parent;}
}

<T>는 제네릭 형태인데, 쉽게 말하면 이 노드는 T형태의 데이터를 갖겠다는 뜻이다. 이 T는  String, int, float 등 아무 객체타입이 될 수 있다.


Tree 구현!

자 이제 Tree를 구현 해보자! 트리의 생성자는 다음과 같다.

public class Tree<T> {
    private Node<T> root;
    private int size;
    public Tree(){
        this(null);
    }

    public Tree(Node<T> root){
        this.root = root;
        if(root != null)
            size = 1;
    }
}

나무를 아직 안심었을 수도 있고, 나무를 심었을 수도 있기 때문에 두 가지로 나누었다.

여기에 root, 그리고 트리의 왼쪽, 오른쪽 노드를 설정하는 코드는 다음과 같다.

    ...
    public int size(){ return this.size; }
    public Node<T> getRoot(){ return this.root;  }

    public Tree<T> setRoot(T element){
        if(root == null)
            size = 1;
        this.root = new Node(element);
        return this;
    }

    public Tree<T> setRoot(Node<T> element){
        if(root == null)
            size = 1;
        this.root = element;
        return this;
    }

    public Node<T> addLeft(Node<T> parent, Node<T> child){
        if(parent.getLeft() != null){
            System.out.println("Already have left");
            return null;
        }
        size++;
        parent.setLeft(child);
        return parent;
    }

    public Node<T> addRight(Node<T> parent, Node<T> child){
        if(parent.getRight() != null){
            System.out.println("Already have right");
            return null;
        }
        size++;
        parent.setRight(child);
        return parent;
    }

    public Node<T> removeLeft(Node<T> parent){
        Node<T> target = parent.getLeft();
        if(target != null)
            size--;
        parent.setLeft(null);
        return target;
    }

    public Node<T> removeRight(Node<T> parent){
        Node<T> target = parent.getRight();
        if(target != null)
            size--;
        parent.setRight(null);
        return target;
    }
    ...

해당 코드를 보면 root를 설정하거나 획득하는 것을 볼 수 있다.

보면 알겠지만, 트리에서 각 노드들에 대한 왼쪽, 오른쪽 노드를 설정하는 것에 깊게 관여하지 않는다. Node에 기본적으로 왼쪽, 오른쪽을 설정하는 코드가 포함되어 있기 때문에, 노드가 잘 할것이라 믿고 노드에게 준다. 다만, 트리는 이미 자식 노드가 설정되어 있을 때 덮어씌우면 안되기 때문에, 해당 경우에 한해서만 "Already have left!"와 같은 말을 출력해준다.

이제 트리의 꽃인 순회이다. 순회는 크게 3가지 방향이 있다.

height가 1인 full binary tree를 떠올려 보면 다음 표의 왼쪽과 같은 그림이다.

이진 바이너리 트리

이 트리를 더 확장해보면 아마 오른쪽과 같이 확장 될 것이다. 트리의 모양이 삼각형과 비슷하지 않은가?

자! 삼각형을 한붓 그리기로 그려봐라. 이 때, 각 꼭짓점은 full binary tree의 각 노드를 가리킨다고 하자. 그러면 우리는 이렇게 그릴수 밖에 없다. A-B-C, B-A-C, C-B-A. (각각의 가지수가 더 있지만, 여기까지만 표현하겠다. 그 이유는 다음줄에서 바로 나온다!)

트리의 순회도 똑같다. 부모-왼쪽-오른쪽(부모-오른쪽-왼쪽), 왼쪽-부모-오른쪽(오른쪽-부모-왼쪽), 왼쪽-오른쪽-부모(오른쪽-왼쪽-부모)로 순회할 수 있다. (통상적으로 오른쪽-부모-왼쪽 혹은 오른쪽-왼쪽-부모 의 오른쪽 먼저보다 왼쪽을 먼저 순회한다.)

각각의 순회 방법에 있어서 현재 내 노드(부모)를 기준으로 이름이 붙여지는데, 각각 전위순회, 중위순회, 후위순회라고 부른다(preorder, inorder, postorder).

순회를 할 때 연결된 모든 노드를 순회해야 하며, 이를 재귀를 이용하여 쉽게 나타낼 수 있다.

Full Binary Tree

다시 사진을 보면서 생각해보자! 설명은 preorder만 하고, 나머지 inorder, postorder는 직접 생각해보길 바란다. 원리는 같다.

순회를 A로부터 시작한다고 하자. 그러면 A를 돌고, 왼쪽자식 B, 오른쪽자식 I를 돌아야 한다. 그런데 이 때, B를 순회할 때 또 다시 (부모)-(왼쪽자식)-(오른쪽자식)을 돌아야 하는 상황이 발생하고, B-C-F를 돌게 된다. 마찬가지로 C를 확인할 때 또 다시 C-D-E순으로 돌게 된다. 이후 왼쪽자식이 더 이상 돌 게 없으니, B는 F를 확인하게 된다.

즉, (나)-(왼쪽자식)-(오른쪽자식)을 먼저 돌 때 A-B-C-D-E-F-G-H-I ... 순으로 순회해야하는 것을 알 수 있다.


이제 순회 코드!

 

    ...
    /* traverse */
    public void preorder(Node<T> node){
        System.out.println(node.getElement());
        if(node.getLeft() != null){
            preorder(node.getLeft());
        }
        if(node.getRight() != null){
            preorder(node.getRight());
        }
    }

    public void inorder(Node<T> node){
        /* Try it! */
    }

    public void postorder(Node<T> node){
        /* Try it! */
    }
    ...

실행 코드

트리를 구현할 수 있기 때문에 이제 각 노드에 대해 값이 잘 들어갔는지 확인 하는 코드는 작성하지 않았다.

따라서 최종 실행코드와 결과는 다음과 같다. 노드의 요소를 설정하는 값은 본 글에서 사용한 트리와 같게 했다.

    public static void main(String[] args){
        Tree<String> tree = new Tree(new Node("A"));
        //root node
        Node<String> root = tree.getRoot();
        tree.addLeft(root, new Node("B"));
        tree.addRight(root, new Node("I"));

        tree.addLeft(root.getLeft(), new Node("C"));
        tree.addRight(root.getLeft(), new Node("F"));

        tree.addLeft(root.getRight(), new Node("J"));
        tree.addRight(root.getRight(), new Node("M"));

        System.out.println("====preorder====");
        tree.preorder(root);
        System.out.println("\n==== inorder====");
        tree.inorder(root);
        System.out.println("\n===postorder====");
        tree.postorder(root);
        System.out.println("\ntree size: " + tree.size());

        System.out.println("====remove root.right.left====");
        tree.removeLeft(root.getRight());
        tree.preorder(root);
        System.out.println("\ntree size: " + tree.size());
    }

실행 결과

다음 글에서는 그래프 구현 방법을 다룰 예정이다.

끝!

 

 

[블록체인 만들기] 1. 블록체인이란?

내 생각에 블록체인은 비트코인에 의해 확-뜨고 인공지능에 의해 확-진 기술인 것 같다. 사실 블록체인 자체는 그렇게 어려운 개념이 아니다. 나는 블록체인을 쉽게 얘기할 때, '일종의 데이터

dev-whoan.xyz

 

[블록체인 만들기] 2. 블록체인 합의, Consensus

[블록체인 만들기] 1. 블록체인이란? 내 생각에 블록체인은 비트코인에 의해 확-뜨고 인공지능에 의해 확-진 기술인 것 같다. 사실 블록체인 자체는 그렇게 어려운 개념이 아니다. 나는 블록체인

dev-whoan.xyz

 

[블록체인 만들기] 3. 블록체인 검증, 거래의 검증 / Transaction Verification

[블록체인 만들기] 1. 블록체인이란? 내 생각에 블록체인은 비트코인에 의해 확-뜨고 인공지능에 의해 확-진 기술인 것 같다. 사실 블록체인 자체는 그렇게 어려운 개념이 아니다. 나는 블록체인

dev-whoan.xyz

오늘은 블록체인의 종류에 대해 얘기하려 한다. 블록체인은 크게 공개형 블록체인과 폐쇄형 블록체인이 있다.

이 둘은 누가 "블록체인을 사용할 수 있냐"를 기준으로 구분할 수 있다.

블록체인은 참여자들을 Node(노드)라고 부르며, 해당 노드들에 데이터를 분산저장하고, 이들은 합의(작업증명 등 해시연산)을 수행함으로써 새로운 블록 생성에 참여할 수 있다.

이 때, 노드의 참여 조건에 대하여 공개형 블록체인은 누구나 참여할 수 있고, 폐쇄형 블록체인은 허가된 사람만 참여할 수 있는 차이가 있다.


참여 조건에 따른 블록체인

공개형 블록체인 (Public Blockchain)
공개형 블록체인은 우리가 흔히 알고있는 비트코인, 이더리움을 예시로 들 수 있다.
폐쇄형 블록체인 (Private Blockchain)
폐쇄형 블록체인은 허가된 사람만 데이터를 읽고 쓸 수 있다.

폐쇄형 블록체인의 경우, 해당 블록체인을 운영하는 기관이 어떤 노드에게 참여 권한을 주고 회수할 수 있어야 하며, 이러한 참여자를 관리하는 시스템이 추가적으로 필요하다.


저장방식에 따른 블록체인

블록체인은 정보를 노드들에게 분산저장하는 것이 기본이나, 가끔 필요에 따라 중앙화된 서버에 저장하는 경우도 있다.

전자를 탈중앙화 블록체인(Decentralized Blockchain)이라 하고, 후자를 중앙화 블록체인(Centralized Blockchain)이라 한다.

탈중앙화 블록체인은 Peer-to-Peer 네트워크 등 노드들 간의 네트워크 연결을 통해 데이터를 주고 받는다. 토렌트를 떠올리면 쉽게 상상이 가능하다.

중앙화 블록체인은 우리가 흔히 알던 시스템과 같이 데이터를 하나의 서버에 모두 저장하는 것이다. 쉽게 생각하자면 데이터베이스 대신 블록체인을 활용한다 정도


어.. 사실 이 내용 관련해서 쓸 내용이 많을 줄 알았는데.. 딱히 없는 것 같다... 음.....

다음에는... 블록체인의 기본 구현과 관련된 글을 작성해야겠다.

 

애플 공홈 주문 DHL 배송...

애플 교육할인 스토어에서 18일날 맥북 에-어를 주문했다. 19년 그램 중고 가격이 꽤 잘 나가길래, 쓰던 그램을 처분하고 맥북 에어를 구매했다. 구매 당시에 배송 예정일이 7월1~7월5일이라서, 아

dev-whoan.xyz

어제 저녁, 맥북 배송상태가 업데이트 되었다!!

DHL이 가끔 밤 배송을 해준다는 사람도 있어서 혹~시 정말 혹~~~시 내게도 밤 늦게 배송이 될 수 있지 않을까 라는 기대감에 계속 기다렸지만, Departed from facility 이후로 업데이트 되는건 없었다..ㅠㅠ

그래도, 오늘! 최초 예정일인 7월 1일~7월5일 보다 10일가량 빠른 배송을 받을 수 있었다! (사람들이 왜 DHL이 좋다 하는지 몸소 느꼈다..)

그래서 오늘은 맥북 에어 개봉기를 보려한다!!

박스...예쁘잖아...

노트북은 LG의 그램만 사봤는데... 맥북 박스는..뭔가.. 예쁘다. 뭐가 예쁜지 모르겠는데, 그냥 예쁘다.

저 박스 안에 맥북이 들어있는데, 박스 여는게 생각보다 힘들다...

아니~~~~~

아 ㅋㅋ 말이 더 필요한가 ㅋㅋㅋㅋ!!!! 나와 앞으로 긴 세월을 함께할 맥북녀석......예쁘다.. (사실.. M2 맥북 에어가 내년에 나오면....ㅋ.ㅋ...)

이 녀석을 위해 준비한 파우치.... 사실... 다음 아이를 위해 그램 14인치용 파우치를 샀지만... 좀 후회되긴 하는듯... 널널하다..ㅠㅠ


불량 테스트를 해봤는데 이녀석 흔들면 소리가난다 ㅠㅠㅠㅠ 트랙패드가 터치되는 소리같기도 하고,, 신경쓰일만한 수준은 아닌데, 괜히 흔들어봄.. 앞으로 신경쓰일것같기도 하다. 일단!!! 14일이 아직 남았으니..ㅋㅋ 써보고~ 신경쓰이면...바꿔야지..ㅋㅋ

아참 사양은 16램에 256 ssd다. 나는 내 서버컴 하드 물려서 쓸려고 256짜리 샀다.(사실 너무비쌈....)

애플 교육할인 스토어에서 18일날 맥북 에-어를 주문했다.

19년 그램 중고 가격이 꽤 잘 나가길래, 쓰던 그램을 처분하고 맥북 에어를 구매했다.

구매 당시에 배송 예정일이 7월1~7월5일이라서, 아무생각없이 기다리고 있었는데, Apple에서 나를 설레게하는 메일이 왔다.

IT기기를 정말 좋아하는 나에게 일주일이나 빨리 배달해준다니!!

이날부터 나는 하루종일 맥북 배송이 언제될지 배송조회만 했다. 저 메일이 21일 월요일에 왔고, 빠른사람은 배송된지 이틀만에 받았다는 사람도 있어서 진짜 매 시간마다 확인한 것 같다.

그런데..
내 맥북은 언제..

아니..ㅠㅠ

왜~~ 업데이트가 안되는거야~~~ ㅠㅠㅠ

내가 계속 맥북 맥북 맥북 거리니 여자친구도 이제 맥북의 ㅁ만 들어도 질려하는데,,ㅠㅠㅠㅠ

빠른사람들은 DHL 이틀만에 온다며~~ 흑흑.. 조회 업데이트도 안되고,, 계속 움직임이 없으면 애플에 전화해보라해서 전화까지 해봤지만..
"고객님~ 애플은 개별 분류하지 않기 때문에, 컨테이너를 열어서 확인 할 때 까지 업데이트가 안되세요. 예정일자까지 배송이 안된다면, 그때 다시 연락주시겠어요? " 라고 너무 친절하게 말해서.. 네..ㅠㅠ 하고 끊었다..

흑흑... 사실..원래 배송예정일보다 엄~~~~청 빨리 오는거지만... 기다리는게 너무 힘들다...
블로그 활동도 맥북으로 하려고 기다리고 있는데..ㅠㅠㅠ

기다리는게 너무 힘들당..

 

 

[블록체인 만들기] 1. 블록체인이란?

내 생각에 블록체인은 비트코인에 의해 확-뜨고 인공지능에 의해 확-진 기술인 것 같다. 사실 블록체인 자체는 그렇게 어려운 개념이 아니다. 나는 블록체인을 쉽게 얘기할 때, '일종의 데이터

dev-whoan.xyz

 

[블록체인 만들기] 2. 합의, Consensus

[블록체인 만들기] 1. 블록체인이란? 내 생각에 블록체인은 비트코인에 의해 확-뜨고 인공지능에 의해 확-진 기술인 것 같다. 사실 블록체인 자체는 그렇게 어려운 개념이 아니다. 나는 블록체인

dev-whoan.xyz

오늘은 블록체인에 등록된 거래에 대하여 어떻게 검증이 이루어지는지 얘기하려 한다.

그러려면, 우선 블록이 어떻게 이루어지는지 알아야 한다. [1. 블록체인이란?]에서 언급한 바와 같이 블록은 Transactions, timestamp, nonce, ..., previous_blocks_hash_id를 사용하여 블록의 hash ID가 결정된다.

지금 검증하고자 하는 것은 블록의 실질적인 내용이고, 등록하고자 한 데이터의 한 형상인 Transactions이다.


Transaction

Transaction은 거래라는 의미를 갖고 있다. 비트코인으로 예를 들면, "A가 B에게 10만큼의 비트코인을 전송했다."를 Transaction이라 생각하면 된다.

이후에 아무 B는 비트코인을 사용하거나 전송하지 않았으면, B는 적어도 10만큼의 비트코인을 갖고 있어야 한다.

따라서 B는 자신이 비트코인 10만큼을 소유하고 있다는 것을 남들에게 알리려면, 적어도 해당 Transaction이 유효하다는 것을 검증해야 한다.


Merkle Tree

이제 블록에 등록되는 내용 중 새로운 친구인 Merkle Tree에 대해 설명하고자 한다.

Merkle Tree는 Hash Tree라고도 불린다. 따라서 어떤 해시 된 데이터들을 node로써 갖고 있는 Tree다.

우선, 위에서 든 예로 "A가 B에게 10만큼의 비트코인을 전송했다." 라는 데이터가 있다고 하자. 하지만, 실제로 우리는 Transaction을 봤을 때, A와 B를 지목하거나 대상을 구체화 할 수 없다. 그 이유는 데이터가 해시 되어서 블록에 저장되어 있기 때문이다.

즉, 거래 내역에 대한 데이터해시 되어 Transaction으로 존재하게 된다. 대충 Merkle Tree에 어떤 정보들이 존재하는지 짐작이 가지 않는가?

Merkle Tree는 Binary Tree로 생각하면 구현하기 쉽다. 그 이유는 다음 글을 참고하길 바란다.

 

[JAVA] Merkle Tree 구현 / 머클트리 구현

블록체인의 작업증명은 거래(트랜잭션)이 주어지면, 해당 거래를 가지고 블록을 만들 수 있는지 확인해야 한다. 주어진 거래와 같은 블록을 이루는 거래들을 이용하여 해당 블록의 Hash값과 일치

dev-whoan.xyz

Transaction을 두 개씩 짝지어 하나의 해시 값을 만들고, Bottom Up 방식으로 node를 만들어 나가다보면, 언젠가 트리가 완성될 것이다. 이 때, 트리의 root 값이 나오게 되는데, 이 값이 중요하다.


검증!

이제 검증이 어떻게 이루어지는지 설명할 차례다.

이쯤되면 우리는 각각의 character(마땅히 단어가 생각나지 않는다.) 혹은 character의 집합을 hash 했을 때 고유한 값이 나오는 것을 알고 있다.

즉, 거래의 내용이 변하면 hash값도 변하게 되고, 이를 이용해 Merkle Tree를 만들었을 때 다른 Root값이 나올것이다.

따라서 내가 검증하고자 하는 어떤 데이터가 블록체인에 정상적으로 등록되어 있다면, Merkle Tree를 다시 만들었을 때, Root Node의 값은 블록을 생성할 때 나왔던 값과 같을 것이고, 이로써 내가 갖고있는 데이터가 유효함이 검증된다.

*Merkle Tree에 쓰인 다른 Transaction은 다른 네트워크 참여자에게 요청하여 얻을 수 있다.


정리하면

내가 검증하고자 하는 데이터를 해시하여 Transaction을 만들고, 해당 Transaction을 바탕으로 블록의 Merkle Tree를 재구성하여 Tree의 Root 노드가 같은 값을 갖고 있다면, 데이터는 유효하다. 다른 값이 나오면, 해당 데이터는 유효하지 않은 것이다.

사실 여기까지의 내용으로 간단한 중앙화 블록체인(Centralized Blockchain Network)을 구현할 수 있다.

블록체인은 탈중앙화로 알고있는 사람들이 많기 때문에, 다음 글에서는 중앙화 / 탈중앙화 그리고 공개 / 비공개 블록체인 네트워크에 대해 글을 써야겠다.

 

 

[블록체인 만들기] 1. 블록체인이란?

내 생각에 블록체인은 비트코인에 의해 확-뜨고 인공지능에 의해 확-진 기술인 것 같다. 사실 블록체인 자체는 그렇게 어려운 개념이 아니다. 나는 블록체인을 쉽게 얘기할 때, '일종의 데이터

dev-whoan.xyz

오늘은 작업증명에 대해 알아보려 한다. 블록체인에서 작업증명은 빼놓을 수 없는 중요한 내용이다.

앞 글의 제일 하단에 보면, 블록체인의 해킹이 왜 어려운지 합의 파트에서 설명하겠다고 작성하였고, 이 문장을 보면 블록체인에서 어떤 합의를 해야 하기 때문에 해킹이 어렵다고 으레 짐작할 수 있다.

비트코인에서 합의 알고리즘은 작업증명(Proof of Work)를 채택하고 있다. 


합의

그렇다면 합의는 무엇일까?

합의는 간단하게, 블록체인에 등록될 어떤 거래 내역(Transactions)들에 대하여 정상적(valid)이라고 많은 사람들이 동의하는 것이다.

모두가 4994가 값이라고 알려주고 있고, 따라서 이는 유효하다.

비트코인에서는 작업증명을 통해 Nonce를 찾고, 해당 값이 Maximum Value보다 낮으면 합의하게 되고, 이 Nonce를 찾은사람에게 비트코인을 보상으로 제공한다. 이 때, 해당 Nonce와 블록 내용으로 누가 되었건 hash를 했을 때, 같은 값이 나오고 해당 난이도 시점에서 valid한 값을 찾기 때문에, 모두가 동의할 수 밖에 없는것이다.

특정 참가자들이 771을 주고있지만 이는 채택되지 않는다.

실제 합의 알고리즘은 작업증명지분증명위임지분증명, ... 등 많은 종류가 있고, 해당 내용은 나중에 중요한것만 다루도록 하겠다.


해킹이 어려운 이유?

블록체인이 해킹이 어려운 이유는 보통 다음과 같다.

1. 이미 생성된 블록들의 내용을 변조하는 것은 불가능하다.
2. 전체 블록체인의 참여자의 50%가 해당 블록에 대해 동의해야 한다.

1번은 앞 글에서 설명한 것 처럼, N번째 블록은 해시 ID를 생성할 때, (N-1)번째 블록의 해시 ID를 사용하기 때문에, 이미 생성된 블록의 내용을 변조하는 것은 해당 M번째(변조된 N) 블록의 해시 ID가 변하게 된다. 이는 기존 (N+1)번째 해시와 (M+1)번째 해시가 달라지게 되고 결국 사슬이 끊어지는것을 의미하며, 해당 블록들은 무의미한 블록이 된다.

2번은, 기본적으로 블록체인은 Peer to Peer 네트워크로 이루어져 있다. 참여자들이 노드 정보(Block정보)를 갖고 있게 되고, 따라서 블록의 내용을 다른 참여자와 비교 하였을 때, 절반 이상 같은 내용을 가지고 있어야만 해당 노드가 유효하게 된다. 앞 1번의 이유로 인해, 이미 생성된 블록을 해킹하는건 불가능하고, 즉 새로 생성될 블록에 내가 변조 내용을 넣어야 한다. 그러나 블록체인 네트워크는 "나"만을 가리켜 블록에 대한 합의를 해달라고 요청하지 않고, 네트워크의 모든 참여자에게 합의를 요청한다. 이는 결국 해당 블록에 대한 합의는 작업증명을 기준으로 모두 같은 값을 줄 것이고, 중간에 변조내용을 심은 사람만 다른 값을 줄 것이다. 이 때 블록체인은 어떤것이 유효한지 선택하여야 하고, 결국 많은 사람들이 동의한 내용을 채택할 것이다.

이를 다시 말하면, 내가 전체 블록체인 네트워크의 51%에 대한 힘을 가지고 있어야만 블록체인에 해킹된 내용을 심을수 있다는 것과도 같다. 이제 왜 블록체인 해킹이 어려운지 이해가지 않는가?


정리하면

블록체인 네트워크는 합의를 통해 새로운 블록을 생성하고, 해킹을 시도한다면 변조된 내용을 동의할 만큼 센 힘을 가지고 있어야 한다. 

다음 글에서는 내가 갖고있는 거래 내역이 어떻게 블록체인에서 검증되는지, 어떻게 유효성이 유지되는지 설명하는 글을 올리겠다.

내 생각에 블록체인은 비트코인에 의해 확-뜨고 인공지능에 의해 확-진 기술인 것 같다.

사실 블록체인 자체는 그렇게 어려운 개념이 아니다.

나는 블록체인을 쉽게 얘기할 때, '일종의 데이터 저장 시스템' 혹은 '일종의 데이터베이스와 같은 것'이라고 얘기한다.

그렇다면 블록체인은 데이터 저장 시스템인데 왜 사람들이 어렵다 말하고, 비트코인이 유명해진걸까? 본 글에서는 사토시 나카모토의 비트코인을 기반으로 블록체인을 설명하려고 한다.


비트코인

우선 비트코인이 무엇인지 알아볼 필요가 있다. 사실 지금 가상화폐로 인해 비트코인이 무엇인지 모르는 사람은 없겠지만, 우리는 블록체인으로서 비트코인이 어떻게 동작하는지 알 필요가 있다.

Bitcoin: A Peer-to-Peer Electronic Cash System, Satoshi Nakamoto, 2008.

놀랍게도 비트코인은 2008년에 논문이 공개되었고, 2009년에 발행이 시작된 가상화폐다. 2009년부터 비트코인을 구매하기 시작했다면, 지금 엄청난 부자가 되었겠지?

블록체인 기술이 주목받기 시작한 이유는 하드웨어의 발전을 빼놓고 얘기할 수 없다. 왜 하드웨어가 중요한지, 도대체 블록체인이 뭔지 이제 시작해보도록 하자.


블록체인, 말 그대로 블록을 연결한 구조

<간단한 블록체인>

블록-체인. 즉 블록을 사슬처럼 연결하였다는 뜻이다. 사슬을 이루는 각각의 블록은 거래 내역(지금부터 데이터라 칭하겠다.)을 가지고 있고, 이러한 블록들이 연결되어 있다. 단순히 연결되어 있다면, 사슬이라는 이름보다는 블록-리스트 라는 이름이 되었을 것이다.

따라서 '사슬'처럼 쉽게 끊어낼 수 없는 어떠한 알고리즘이 사용되어야 하고, 비트코인에서는 Hash(암호화)를 이용하였다. 단순히 현재의 블록이 갖고 있는 내용만으로 Hash를 하였다면, 마찬가지로 단순한 '리스트'였을 것이다. 이를 해결하기 위해 각각의 N번째 블록은 자신의 ID를 만들기 위해 그 앞번째, (N-1)번째의 블록 정보를 이용하여야 한다.

<ID Hash>

만약 여기까지 이해했다면, 다음과 같은 의문이 생길수 있다. "그러면 블록의 정보들만 모두 구할 수 있으면 똑같은 블록을 만들 수 있는거 아니야? 내가 알기로 블록체인은 변조가 어려운 걸로 알고 있는데"

맞는 말이다. 블록의 내용만으로 똑같은 블록을 구성할 수 있고, 블록체인을 이룰 수 있다면, 비트코인의 가격이 폭등하지도 않았고, 그래픽카드 대란이 일지도 않았을 것이다.

즉 블록의 ID를 만들기 위해서는 추가적인 기술이 필요하고, 흔히 난이도라고 부르는 것이 그것이다.

*Hash : 임의의 길이의 데이터를 고정된 길이의 데이터로 매핑하는 함수, 나무위키, 비트코인에서는 SHA-256을 이용하였다. 


난이도

난이도가 꽤 어려운 내용이기 때문에, 여기서는 단순하게 난이도가 어떤것인지 설명만 하도록 하겠다.

난이도라는 이름 그대로, 쉽게 말하면 블록을 생성할 때의 난이도다. 난이도가 쉽다면 블록을 누구나 만들 수 있을것이고, 난이도가 어렵다면 블록을 아무나 쉽게 만들지 못할 것이다.

비트코인은 SHA-256을 이용하여 데이터를 해시하였으며, SHA 함수는 값마다 서로 다른 해쉬값을 뱉어내는데, 예로 다음과 같다.

iphone: 241c1e30ed886aa4a8f4248024be2ca1a221fe9773b52e2dca7891ff5771f399
iPhone: 38fdf519314e3151d7e7f6ef456f327b78ddb84bc457bdb0d49bce0b1fc3c959
IPhone: fde283a6fa88982b40441fe8d9d1ba8659ddb4c4cd75bf717a9371822370bcf4

조금만 값이 바뀌어도, 전혀 다른 결과가 나오는 것을 볼 수 있다. 이에 착안하여, 비트코인에서는 Nonce라고 불리는 값을 내가 만들고자 하는 블록의 데이터에 추가한다. 위의 그림 <ID Hash>를 보면, Transactions + Timestamp + Nonce + ... + Prev_ID라 이해하면 된다.

위의 해시 결과를 보면 알겠지만, 대소문자만 바뀌어도 값이 변하기 때문에, Nonce는 막 수학적으로 계산하거나, 어려운 값을 넣을 필요 없이 단순히 숫자 0부터 조건을 만족할 때 까지 1씩 증가시키면 된다. 

비트코인에서는 그 조건으로, 해시된 결과의 앞 n개의 글자가 0이면 된다. 최초에는 000000... 으로, 0이 6개 나오면 됐지만, 하드웨어가 발전함에 따라 해시속도는 급격하게 빨라졌고, 따라서 지금은 가변적인 난이도를 갖게 되기 때문에 n개의 글자수가 0이면 되는 것이다.

000000을 만드는것도 쉬운거아니야? 라고 생각할 수 있는데, i5-9600KF 기준으로 000000을 찾는데 평균 2분 30초 정도 걸리며, i9 10900으로는 1분 30초가 소요된다.

이러한 난이도(Nonce)를 찾는 행위를 작업증명이라고 한다.


정리하면

블록체인은 앞 블록의 Hash값과 현재 만들고자 하는 블록의 정보(Transactions, Timestamp, ...)를 함께 Hash하여 원하는 조건이 되는 ID를 가지는 블록들로 이루어진 데이터 사슬이라고 보면 된다.

"그러면 해킹은 왜 어려운거야?" 라는 질문이 생길수도 있는데, 이는 아직까지 설명하기엔 쉽지 않다. 하지만, 사람들이 흔히 말하는 내용처럼, "비트코인 네트워크의 절반 이상이 해킹된 내용을 갖고 있어야해."가 그 정답이다. 이는 나중에 합의파트에서 설명하도록 하겠다.

이번에 누나가 S21으로 휴대폰을 바꾸면서 워치 쿠폰이 생겼다.

그냥 지나가는 말에 워치 "엄청 저렴하다~! ㅎㅎ.." 했더니 누나가 사줬다 (...)

개인적으로 갤럭시 스마트 워치를 통해 기아 자동차의 UVO앱을 정말 사용하고 싶었는데, 이제 나도 가능해졌다!!!

모나미 S펜, 버즈 프로 모두 보라색 계열인데, 이번에 들여온 액티브 2도 보라색으로 구매함으로써 나도 갤럭시 깔맞춤을 하게 됐다. (내 플립은 검정색이지만..ㅠㅠ..)


삼성 마일리지몰에서 구매를 했는데, 매번 느끼는거지만 삼성 물류 배송은 좀 많이 개선되어야 한다. 2021년에 물품 구매 후 배송까지 어떻게 1주일이 넘는 시간이 걸리는가.. (3월 25일 구매해서 4월 3일에 수령했다.) 제품을 받아서 파는 곳이면 그럴 수 있지만, 삼성 내부적으로 판매하는건데도 이렇게 오래 걸리는지 아직도 이해가 안간다.

상자를 개봉하면, 위 뚜껑 안에 보이는 SAMSUNG이라 써 있는 곳은 삼성의 제품이 항상 그러했든 사용설명서가 들어있다. 시계의 모양을 유지해주고 있는 둥근 기둥(?) 같은 것을 들면, 충전기가 나온다.

갤럭시 액티브2 충전기의 단점이라면, 스탠드가 아니고 눕혀서 액티브 2를 충전 시켜야 한다. 그래서 나는 미리 충전기 거치대를 구매했고, 위 사진처럼 거치하여 충전하고 있다. 거치해서 충전하는게 공간도 덜 차지해서 꽤 괜찮은듯.

착용샷

사실 나는 제품을 착용하기 전까지, 40mm면 좀 많이 작지 않을까..? 하는 걱정이 있었는데, 시원시원하다. 내가 차고다니던 시계는 이것보다 큰데, 불편함이 없다. (원래 아날로그 시계는 액티브2의 베젤까지 모두 시계영역이었으니, 꽤 답답할거라 생각했는데도.)

갤럭시 생태계 구축은 이제.. 노트북만..남았다..!!


총평 (★◐)

3.5 개를 준 이유는, 우선 아직 장착해서 실생활을 안해봤기 때문에 배터리 러닝타임이 얼마나 되는지 몰라서 한칸 비워뒀다. 반개를 깎은 이유는 시계의 반응이 좀 느리다.

예전에 갤럭시 기어 S3를 썼을 때는, 느리다는 느낌이 없었는데, 액티브2는 반응이 느리다.

베젤 터치 반응도 그렇고, 버벅거림이 눈에 보인다.

디자인은 완전 만족!

나중에 실생활 1주일 해보고, 본 게시글에 배터리 관련하여 내용을 추가 하겠다.

2021.06.12 추가!

배터리는 하루에 40%씩 소모되고, 따라서 이틀 쓰고 충전해주고 있다! 꽤 괜찮은듯?

+ Recent posts