BlockChain 개발자가 되는 방법

in #kr7 years ago (edited)

개발자라면 한번즘 나도 BitCoin, EOS, Steem 같은 BlockChain을 개발해서 ICO도 해보고... +.............+ 라는 생각들을 해보시지 않으셨을까요? 잘 정리된 글이 있어서 간단히 소개해봐요.

https://blockgeeks.com
https://blockgeeks.comHow To Become A Blockchain Developer: Crash Course! 라는 글을 요약 정리한 내용입니다.

두둥 ~ Blockchain 개발자가되는 방법

Milestone # 1 : 기초 이해하기

블록 체인 기술과 같이 새롭고 혁신적인 것을 학습하는데 가장 큰 어려움 중 하나는 시스템에 필수적인 새로운 개념과 용어들을 익히는 것입니다.

특히 초보자의 경우 익숙해 져야 할 특정 용어가 있습니다.
이미 잘 알고 계신 스티미언 분들은 PASS ~

  • Blockchain : 블록체인은 중앙통제 없이 가치있는 데이터를 포함하고 있는 블록들의 사슬입니다. 그것은 암호화되어 안전하고 불변합니다.
  • Decentralized : 탈중앙화, 블록 체인은 중앙 통제가 없기 때문에 분산되어 있다고합니다.
  • Consensus Mechanism : 합의 메커니즘. 분산 네트워크가 특정 사안에 관해 합의하기 위한 방법.
  • Miners : 컴퓨팅 파워를 이용해 블록을 채굴하는 사용자.

이 외에도 암호학 영역에서 사용되는 다양한 용어들을 더 자세히 학습해 둔다면 도움이 됩니다. BlockChain 용어집 A~Z (영문)

하지만 영알못인 저는 나무위키 - BlockChain 를 선택합니다.

시간이 좀 걸리겠지만 이 유투브 영상도 추천합니다. 조금은 개발~ 개발~ 한 영상이지만 아주 쉽고 상세하게 설명되어 있어요. 강추!!

개발자들이 잘 알지 못하는 암호경제학 에 대해서도 공부해야 한다고 하네요 ㅠ_ㅠ. 암호화와 전자서명 은 물론이구요.

그리고 최소한 사토시 나카모토의 BitCoin 백서 정도는 읽어봐야 하지 않을까요? 필독!!

영문판 주소 (PDF) : https://bitcoin.org/bitcoin.pdf
한글판 주소 (PDF) : http://s.kwma.kr/pdf/BitCloud/bitcloudwpkor_p43.pdf

참고로 백서(White Paper)란 정부나 기업 등에서도 정책을 설명하기 위해 백서를 발간하기도 하지만 일반적으로 대학에서 쓰여지는 논문을 말한다고 합니다.

Milestone # 2 : 프로세스 작동 방법 학습

언젠가 ICO를 하기 위해선 +..........+ 지갑과 특히 멀티시그 지갑이 어떻게 작동 하는지를 반드시 알아야 합니다. 동전을 사봐야 한다는 얘기죠. 사용법도 모르고 만들수는 없을테니까요.

이 섹션은 거저먹기인 듯 합니다. 이미 사고 팔고 물리고...
어쨋거나 지갑에 익숙해 져야한다!!

Milestone # 3 : 코딩하자!

자 이제 드디어 코딩할 수 있답니다. 블록체인을 개발하게 되면 백엔드에서 수많은 도전에 직면하게 될 것이라고 경고하는군요. 공개 블록 체인을 만들고 유지하는 것은 여러 가지 이유로 쉽지 않다면서... 어차피 쉬운 건 없습니다. 구체적으로 알아봅시다. 대체 뭐가 어려운 것인지

첫번째 어려운 이유 1 : 보안 (Security)

Ripple 의 Chief Cryptographer 인 David Schwartz 가 블록체인은 fortresses 여야 한다고 말했다네요. 포트리스 기억나시죠? 추억의 게임... 은 아니고 요새. 일반적으로 블록체인 코드는 모두 공개되어 있고 누구나 버그와 취약점을 찾아낼 수 있습니다. 다만 일반적인 오픈소스 코드와 달리 블록체인 코드 내에서 취약성을 찾아내는 것의 영향력은 엄청날 것입니다. 수백, 수천만 달러를 해킹할 수 있게 되겠죠. 이런 보안 문제로 인해 블록체인 개발은 일반적으로 매우 더디게 진행된다고 하네요.

두번째 어려운 이유 2 : 자원 관리 (Resource Management)

It is important to keep pace with the network. You cannot fall too far behind and not keep up with all the network demands. You should be well equipped to handle remote and local queries.
네트워크와 보조를 맞추는 것이 무척 중요하다. 너는 너무 느려서 네트워크의 모든 요구사항을 따라 잡을 수는 없다. 원격 혹은 로컬에서 실행되는 쿼리들을 처리할 수 있도록 잘 준비되어 있어야 한다. 라고 합니다.

( 음.. 저는 Network의 의미를 정확히 파악하지 못하겠네요. 빨리 개발하라는 것 같기도 하고... 빠르게 만들라는 것 같기도 하고 +..........+;;)

세번째 어려운 이유 3 : 성능 (Performance)

블록체인은 언제나 가능한 최대한의 성능으로 빠르게 수행되어야 합니다. 이를 위해 작업을 구분해보자면 병렬로 처리 가능한 작업과 그렇지 못한 작업들이 있습니다. 병렬 처리가 가능한 작업의 좋은 예는 전자서명 확인작업이 있습니다. 전자서명 확인을 위해 필요한 모든 것은 키, 거래 및 서명이고 세 가지 데이터만 사용하면 병렬화 된 방식으로 검증을 수행 할 수 있습니다.

블록체인의 모든 기능이 그런 식으로 수행되어야하는 것은 아닌데요. 트랜잭션 실행을 생각해보면 여러 트랜잭션을 병렬로 실행할 수 없겠죠? 이중 지출과 같은 실수를 피하기 위해 한 번에 하나씩 수행해야 합니다.

일부 언어는 병렬 작업에서는 좋지만 일부 언어는 비병렬 작업에서 유용하기 때문에 블록체인 개발에는 매우 다양한 언어가 선택되어질 수 있다고 합니다.

네번째 어려운 이유 4 : 격리 (Isolation)

결정론적인 행동. 동일한 조건이 주어진다면 언제든 항상 결과가 같아야 하는 이러한 특성을 결정론적 행동이라고 합니다. (함수형 프로그래밍과 유사한 개념으로 생각되네요)

해시 함수는 결정적이고 블록체인 개발에서 모든 트랜잭션 작업은 결정적이어야 합니다. 시간과 공간에 상관없이 항상 동일한 방식으로 계약이 체결되어야 하기 때문이죠.

개발자가 이러한 것을 보장하기 위한 유일한 해결책은 격리입니다. 스마트 계약, 트랜잭션들을 비결정적 요소들과 격리시켜야 합니다. 이러한 요구들을 충족시키는 몇몇 언어들을 선택할수 있겠네요.

일반적으로 BlockChain 개발자들에게 C++, Javascript 지식이 요구된다고 합니다. 실제로 BitCoin 이 C++로 작성되었고 Javascript 는 대화형 웹페이지를 개발하는 데 필요하겠죠. 두 가지는 저자가 제안하는 언어일뿐 다양한 언어가 선택될 수 있을거라고 생각됩니다.

이미 BitCoin 이후에는 C++ 이외에도 다양한 언어들로 BlockChain 이 개발되고 있습니다. Tron (Java), Aeternity (ERLANG), Tezos (Ocaml), Hyperledger (GO) 등등...

자 그럼 이제 실제로 Javascript를 사용해서 아주 간단한 블록 체인을 만들어봅시다.

우리가 만들려고 하는 "NewbieCoin" 에서 각 블록들은 다음과 같은 정보들로 구성됩니다.

  • Index : 블록 넘버를 알기 위한 색인.
  • Timestamp : 생성시간을 알기 위한 Timestamp.
  • Data : 블록 내부의 데이터.
  • Previous Hash : 이전 블록의 해시.
  • Hash : 현재 블록 의 해시.

계속하기 전에, 몇가지 키워드에 대해 짚고 넘어갑시다. (다들 잘 아시겠지만...)

  • this : "this"키워드는 함수 내에서 호출되어 특정 함수를 호출하는 특정 객체 내부의 값에 액세스 할 수있게합니다.
  • Constructor : 생성자는 클래스 내의 객체를 만들고 초기화하는 데 도움이되는 특수 함수입니다. 각 클래스는 하나의 생성자로 제한됩니다.
블록 만들기
const SHA256 = require("crypto-js/sha256"); 
class Block { 
    constructor(index, timestamp, data, previousHash = '') { 
        this.index = index; 
        this.previousHash = previousHash; 
        this.timestamp = timestamp; 
        this.data = data; 
        this.hash = this.calculateHash(); 
    } 

    calculateHash() { 
        return SHA256(this.index + this.previousHash + this.timestamp + JSON.stringify(this.data)).toString(); 
    } 
}

코드 내용을 살펴보면, SHA256 해시함수를 사용하기 위해 crypto-js 라이브러리를 호출했고, 생성자를 하나 만들었습니다. calculateHash 함수를 살펴보면, 블록의 모든 내용을 해시하고 JSON.stringify 함수를 사용하여 블록 데이터를 문자열로 변환합니다.

블록이 준비되었으니 블록 체인으로 연결해 봅시다.

블록 체인 만들기
class Blockchain {
    // Section 1 Genesis block creation
    constructor() { 
        this.chain = [this.createGenesisBlock()]; 
    } 

    createGenesisBlock() {
        return new Block(0, "01/01/2017", "Genesis block", "0"); 
    } 

    // section 2 adding new blocks
    getLatestBlock() { 
        return this.chain[this.chain.length - 1]; 
    } 

    addBlock(newBlock) { 
        newBlock.previousHash = this.getLatestBlock().hash; 
        newBlock.hash = newBlock.calculateHash(); 
        this.chain.push(newBlock); 
    } 

    // section 3 validating the chain
    isChainValid() { 
        for (let i = 1; i < this.chain.length; i++) { 
            const currentBlock = this.chain[i]; 
            const previousBlock = this.chain[i - 1]; 
            if (currentBlock.hash !== currentBlock.calculateHash()) { 
                return false; 
            } 
            
            if (currentBlock.previousHash !== previousBlock.hash) { 
                return false; 
            } 
        } 
        return true; 
    } 
}

위 코드가 하는 작업들을 조금 나누어서 살펴보자면 ~

Section 1 : 창세기 블록

창세기 블록은 블록 체인의 첫 번째 블록이며 특별한 이유는 모든 블록이 이전 블록을 가리키고 있지만 기성 블록은 아무 것도 가리 키지 않는다는 것입니다. 그래서 새로운 사슬이 만들어지면 즉시 창세기 블록이 호출됩니다.

위 코드에서는 창세기 블록의 데이터를 하드코딩 한 "createGenesisBlock ()"함수를 볼 수 있습니다.

    createGenesisBlock() {
        return new Block(0, "01/01/2017", "Genesis block", "0"); 
    }

Section 2 : 블록 추가

현재 블록 체인의 마지막 블록이 무엇인지 알아야합니다. 이를 위해 getLatestBlock() 함수를 사용합니다.

    // section 2 adding new blocks
    getLatestBlock() { 
        return this.chain[this.chain.length - 1]; 
    } 
    
    // Now that we have determined the latest block, let’s see how we are going to add new blocks.
    addBlock(newBlock) { 
        newBlock.previousHash = this.getLatestBlock().hash; 
        newBlock.hash = newBlock.calculateHash(); 
        this.chain.push(newBlock); 
    }     

블록을 어떻게 추가하고, 주어진 블록의 유효성을 어떻게 체크할까요?
새 블록의 이전 해시값을 최신블록의 해시값과 비교합니다.

이미지 제공 : Lauri Hartikka 매체 기사
이미지 제공 : Lauri Hartikka 매체 기사

이 두 값이 일치하면 새 블록이 합법적이며 블록 체인에 추가된다는 의미입니다.

Section 3 : 체인 유효성 검사

블록체인 전체가 이상없이 안정적인지 확인해야 할 필요가 있겠죠? for루프를 사용하여 블록 1에서 마지막 블록으로 이동합니다. (참고로 창세기 블록은 0 입니다.)

for (let i = 1; i < this.chain.length; i++) {
            const currentBlock = this.chain[i];
            const previousBlock = this.chain[i - 1];
            if (currentBlock.hash !== currentBlock.calculateHash()) {
                return false;
            }
            
            if (currentBlock.previousHash !== previousBlock.hash) {
                return false;
            }
        }
        return true;
    }

현재 블록의 "previousHash"가 이전 블록의 "Hash"와 같지 않으면 해당 함수는 False를 반환하고 그렇지 않으면 True를 반환합니다.

이제 "NewbieCoin"을 만들기 위해 블록 체인을 사용합니다.

let BlockGeeksCoin = new Blockchain();
BlockGeeksCoin.addBlock(new Block(1, "20/07/2017", { amount: 4 }));
BlockGeeksCoin.addBlock(new Block(2, "20/07/2017", { amount: 8 }));

Blockchain을 기반으로 새로운 암호화를 생성하고 "NewbieCoin"이라고 명명했습니다. 새 객체를 호출하여 생성자를 활성화했으며, 생성자가 자동으로 창세기 블록을 만들었습니다.

단순히 두 개의 블록을 더 추가하고 데이터를 추가했습니다.

정말!! 간단합니다. (약... 파는 것 같은 감탄사군요 ㅋ)

위 코드들로 아주 간단한 블록체인의 구성들에 대해서는 파악해볼 수 있는 듯 합니다. 시작이 반이니... ㅋ

Milestone # 4 : Smart Contract 교육

Smart Contract 는 어떻게 정의될까요?

Wikipedia에 따르면, Smart Contract 란 "계약의 협상 또는 성과를 촉진, 검증 또는 집행하기 위한 컴퓨터 프로토콜"입니다. 1996 년 American Cryptographer Nick Szabo에 의해 처음 제안되었지만 비탈릭 부테린의 Ethereum 덕분에 유명해졌죠.

어렵네요 +.....+;; 확 와닿지는 않습니다. 더 자세한 내용은 다음 글을 읽어보서도 좋을 듯 합니다. Smart Contracts: The Blockchain Technology That Will Replace Lawyers

어쟀거나 ~ 스마트 계약에서 우리가 원하는 바람직한 특성은 무엇일까요? 블록 체인에서 실행되는 모든 것은 변경 불가능해야하며 무결성을 손상시키지 않으면 서 여러 노드를 통과 할 수 있어야합니다. 그 결과 스마트 계약은 세 가지가 충족 되어야한다고 합니다.

  • Deterministic 결정론적.
  • Terminable 종결시킬 수 있는, 기한이 있는
  • Isolated 격리.

기능 1 : Deterministic

한 번에 주어진 입력에 같은 출력을 주면 프로그램은 결정적입니다. 예 : 3 + 1 = 4 라면 3 + 1은 항상 4가됩니다 (같은 베이스를 가정 할 때). 따라서 프로그램이 서로 다른 컴퓨터에있는 동일한 입력 집합에 동일한 출력을 제공하면이 프로그램을 결정론 이라고합니다.

아니 그럼 3 + 1이 4지 그럼 5냐고 무슨 그런 당연한걸 설명하나? 라는 의문을 가지실수 있을 듯 합니다. 하지만 당연하지 않게 프로그램이 비결정적으로 작동 할 수있는 다양한 순간이 있습니다.

결정적이지 않은 시스템 함수 호출 : 프로그래머가 프로그램 내에서 결정적이지 않은 함수를 호출 할 때. 예를 들면 getDate 같은 함수가 있겠죠? (MS SQL의 결정적 함수 및 비결정적 함수

비결정적 데이터 자원 : 런타임 중에 프로그램이 데이터를 수집하고 해당 데이터 소스가 비결정적이라면 프로그램이 비결정적이됩니다. 예 : 특정 검색어에 대한 상위 10 위의 Google 검색을 획득하는 프로그램을 가정해보면, 목록이 계속 변경 될 수 있겠죠?

동적 호출 : 세번째는 프로그램이 동적 호출에 의해 다음 프로그램을 실행 할 때입니다. 호출 타겟은 실행 중에 만 결정되기 때문에 본질적으로 비결정적입니다.

기능 2 : Terminable

수학 논리에서 "정지 문제"라는 오류가 있습니다. 기본적으로 주어진 프로그램이 제한된 시간 내에 해당 기능을 실행할 수 있는지 여부를 알 수 없다고합니다. 1936 년 앨런 튜링 (Alan Turing)은 캔터의 대각선 문제 (Diagonal Problem)를 사용하여 주어진 프로그램이 제한 시간 내에 끝날 수 있는지 여부를 알 수 없다는 것을 추론했습니다.

정의에 의한 계약은 주어진 제한 시간 내에 해지가 가능해야하기 때문에 Smart Contract의 경우 분명히 문제가됩니다. 외부 적으로 계약을 "죽일"수있는 방법이 있고 자원을 낭비 할 수있는 무한 루프에 빠지지 않도록하는 몇 가지 방법이 있습니다.

Turing Incompleteness : Turing Incomplete 블록 체인은 제한된 기능을 가지며 점프 및 / 또는 루프를 만들 수 없습니다. 따라서 그들은 끝없는 반복을 할 수 없습니다.

Step and Fee Meter : 프로그램은 그것이 수행 한 "steps"의 수를 쉽게 추적 할 수 있습니다. 즉, 실행 된 명령어의 수를 추적하고 특정 단계 수를 실행되면 종료되도록 할 수 있습니다. 또 다른 방법은 요금 미터입니다. 계약서는 선불료로 지불되며, 모든 명령 실행에는 특정 금액의 수수료가 필요합니다. 지불 된 수수료가 선불 수수료를 초과하면 계약이 해지되는 방식입니다.

Timer : 미리 설정된 타이머를 유지하고, 계약 실행이 시간 제한을 초과하면 외부에서 중단됩니다.

기능 # 3 : Isolated

블록 체인에서는 누구나 누구나 Smart Contract를 업로드 할 수 있습니다. 그러나 이로 인해 계약에는 악의적인 바이러스와 버그가 포함될 수 있습니다. 계약이 격리되지 않으면 전체 시스템을 방해 할 수 있습니다. 따라서 모든 생태계에 부정적인 영향을 미치지 않도록 계약을 샌드 박스에서 격리하는 것이 중요합니다.

일반적으로 스마트 계약은 두 시스템 중 하나를 사용하여 실행됩니다.

Ethereum 은 Virtual Machines 을 사용합니다.
Fabric 은 Docker 를 사용합니다.

Ethereum (Virtual Machines)을 Fabric (Docker)의 장단점을 비교한 표입니다. 내용을 보면 저자는 VM의 손을 들어주고 있습니다만, 적용 방식에 따라 논란의 여지가 있을 수 있을 것 같습니다. 단순 참고용으로 봐주시면 좋을 듯 합니다.

virtual MachinesDocker
Deterministic계약에는 비결정적 기능을 포함하지 않고 데이터는 체인 상의 정보로만 제한됩니다. 그러나 본질적으로 비결정적 일 수있는 동적 호출을 실행합니다. 다행히 접근 가능한 데이터는 결정론적이다.docker의 디자인 때문에, 시스템은 결정론적인 계약을 생성하기 위해 사용자에게 의존합니다. 최적의 해결책은 아닙니다.
Terminableethereum은 종료를 위해 "프리 미터"를 사용합니다. 계약의 모든 단계는 "가스"비용이 들며 가스 비용이 선불 비용을 초과하면 계약이 종료됩니다패브릭은 타이머를 사용합니다. 각 노드가 자체 계산 능력을 가지므로 타이머가 노드에서 노드로 변경 될 수 있는 경우 합의 프로세스에 위험이 있습니다
Isolated좋은 격리 속성을 가지고 있습니다.네임 스페이스 의존적이고 적절한 격리가 불가능합니다.

Milestone # 5 : Be In The Mix

Reddit 포럼, Gitbub 페이지 및 StackExchange에 참여하여 다른 개발자와 연락하고 기술 관련 뉴스를 항상 확인하세요.

블록 체인 개발자를 찾는 사람들이 무엇을 원하는지 알면 도움이 될 것입니다. 기업들이 고용하고자 할 때 원하는 내용을 파악해보면 도움이 되겠죠.

BlockGeeks Article : Smart Contracts: The Blockchain Technology That Will Replace Lawyers

지금까지 BlockChain 개발자가 되기 위한 방법을 살펴보았습니다.

BitCoin Source Code를 Checkout 받아서 분석해도 될테고 다양한 접근법이 있겠지만 이 글이 조금이나마 스티미언들에게 도움이 되었으면 좋겠네요.

BlockGeeks 에서 제공되는 online 강의들에도 조금 관심이 생기네요. 곧 이더리움 프로그래밍 관련 강의도 한번 들을 계획인데요 다녀와서 또 한번 공유 드리도록 하겠습니다. +........+

Sort:  

스스로 홍보하는 프로젝트에서 나왔습니다.
오늘도 좋은글 잘 읽었습니다.
오늘도 여러분들의 꾸준한 포스팅을 응원합니다.

정성스럽게 쓰여주신 글을 잘 읽었습니다. 피드백을 드리고 싶네요.

"블록 체인 만들기"

부분에 나온 내용은 사실 컴퓨터공학에서 기본으로 다루는
연결리스트(linked list) 의 개념입니다.
블록 체인 또한 연결리스트라고 볼 수 있죠.
다만, 연결리스트라는 사실이 블록체인의 전부는 아닙니다.
"왜 구지 연결리스트로 표현하는지"
이 이유를 자세하게 더 다뤄주시면 좋겠네요

좋은 피드백 감사합니다
말씀주신대로 딱 블록체인 개발의 진입점 정도로 봐주시면 좋을듯 해요
링크드 리스트를 사용하는건 체인의 형태를 구현하기 위해서라고 생각되는데요
블록체인 세부 구현에 대한 인사이트가 더 생기면 다시 글을 작성해보도록 할게요

관심있는 1인으로써 글 넘 잘 읽었습니당!!^^

파이썬으로 steemit 관련 개발하고 계시군요 팔로우 합니당 ㅋ

블록체인이 뭔지 확 와닿네요!!

개발 ㄱㄱ 하시는 건가요? +_+

좋은 정보 감사드립니다. 저녁때 다시 한번 차근히 읽어봐야겠네요.

넵 ~ 댓글 감사합니다

코드로 보니까 블록체인을 이해하는데 큰 도움이 되네요! 좋은글 감사합니다~!

도움이 되셨다니 다행이네요 !!

개발자는 아니지만 잘 읽었습니다. 좋은 정보 감사해요.

감사합니다 +____+

오~ 코딩 전문가셨군요. 눈이 휭휭 돌아갑니다. 놀이기구를 방금 탄것 같아요 ㅋㅋㅋ

좋은 작품 많이 보여주세요 ~ 눈이 휙휙 돌아가는 ㅋ

저도 중초보라 그정도 작품은 없답니다. 그냥 열심히 한걸 보여드리려구용 히힛.

이거 읽느라 30분이상 걸림...
너무 집중해서 머리 쥐나여~@.,@
하지만 보팅 꾸~욱!

쥐날때까지 읽어주셔서 감사해요!!

조만간 이 글 참고하면서 시도해봐야겠어요!

참고가 되었으면 좋겠네요!

좋은 글 정말 감사드립니다. 저는 개인적으로 아직 경험은 없지만 프로그래밍을 배워나가면서 스팀잇에도 기여하는 개발자가 되고 싶은데요, 어떻게 공부를 시작해야할지 잘 모르겠습니다.ㅠ 초보자가 따라갈 수 있는 커리큘럼이 소개된 자료가 있다면 알려주시면 정말 감사드리겠습니다! (일단 지금 계획으로는 C++를 복습하고 이더리움 개발 책을 사서 공부할 생각입니다.)

참고가 되었다니 ~ 감사합니다
블록체인 관련해서는 저도 이제 막 공부를 시작하는 참이라 ㅎㅎ 제가 보고 있는 책 몇 권 추천 드릴게요

  • 비트코인, 블록체인과 금융의 혁신
  • 블록체인 애플리케이션 개발 실전 입문 : Solidity를 이용한 이더리움 스마트 계약 구현

Mastering Bitcoin은 읽었습니다!! Solidity 공부를 시작해야겠네요!! ^^ 감사합니다

저는 이더리움 보다는 스팀잇이나 EOS 쪽으로 공부해보려구요 그 편이 더 댑개발에는 효율적일 것 같아요

사실 저도 최종 목표는 EOS & STEEM개발진인데..ㅋㅋㅋㅋㅋㅋㅋ참고할만한 자료를 찾기가 힘드네요.. 스팀잇 개발이라면 깃헙에서 커밋하는거를 말씀하시는건지요??

개인적으로는 블록체인 코어 개발보다는 DApp 개발 쪽에 더 큰 관심을 가지고 있습니다 ㅎㅎ

아..멋있으세요 저도 곧 따라가겠읍니다..ㅋㅋㅋㅋㅋ 팔로우 했어요 앞으로 더 좋은 글 잘 읽겠습니다~

This post received a 46% upvote from @krwhale thanks to @coffeex! For more information, click here!
이 글은 @coffeex님의 소중한 스팀/스팀달러를 지원 받아 46% 보팅 후 작성한 글입니다. 이 글에 대한 자세한 정보를 원하시면, click here!

크 감사합니다 많은 도움이 되었습니다!
Follow 하고 갑니다 :D

감사합니다 ~ 자주 놀러 갈게요! ㅋ

좋은 글 공유 감사합니다~!
오늘도 좋은 하루되세요^^