인터페이스는 상속 받을 클래스에 기능이나 속성을 지정하는 역할을 합니다. 일반적인 상속관계와 비슷하다고 볼 수 있지만 살짝 다른 개념입니다. 우선 C#에서는 C++과 다르게 하나의 부모 클래스만 상속 받을 수 있습니다. 따라서 여러가지 기능들을 사용할 경우 하나의 부모 클래스에서 기능을 상속 받아 자식 클래스에서 정의를 하게 됩니다. 

하지만 이런 경우 부모 클래스에 너무 많은 기능이 들어가게 되고, 이런 경우 부모 클래스가 무슨 기능을 하는 클래스인지 명확하게 구분하기 어려워집니다. 그렇기 때문에 C#에서는 인터페이스를 이용하여 기능을 추가적으로 구현할 수 있게 도와줍니다. 

예를 들면 자동차라는 클래스가 부모 클래스이고, 자동차라는 클래스를 상속 받아서 여러 회사의 자동차를 만든다고 가정해보겠습니다. 부모 클래스인 자동차에는 기본적인 기능만 들어가게 됩니다. 예를 들면 가속, 감속, 핸들 조종과 같은 자동차가 가져야할 기본적인 기능들이 자동차 클래스에 있는 것입니다. 

여기에 각 회사별로 특별한 기능들이 있겠죠? 이런 기능들은 인터페이스로 정의를 하는 것입니다. 예를 들면 크루즈 모드는 라는 인터페이스를 만들어서 A, B라는 회사에서 나오는 자동차들은 크루즈 모드가 있기 때문에 크루즈 모드 인터페이스를 상속 받게 됩니다. 또 B, C라는 회사에서 출시되는 자동차에는 자율주행이라는 기술이 들어가 있다고 하면, 자율 주행 인터페이스를 만들어서 B, C 자동차 클래스에 상속을 하게 됩니다. 

그럼 이제 코드로 한번 살펴보겠습니다. 우선 자동차 클래스입니다. 

이런 식으로 추상 클래스로 BaseCar라는 클래스를 구현할 수 있겠죠. 이제 각 제조사마다 자동차들은 이 BaseCar라는 클래스를 상속받아 자신들의 고유한 자동차를 만들 것인데요. 이때 인터페이스로 두가지 기능을 미리 선언해주겠습니다. 첫 번째 인터페이스는 크루져 모드, 두 번째 인터페이스는 자율주행입니다. 

이렇게 두가지 인터페이스를 구현하였습니다. 인터페이스는 실제 기능은 구현하지 않고 이런 기능을 사용할 것이다라는 정의만 하고 실제 구현은 클래스에 구현하게 됩니다. 

이제 A 자동차를 구현하도록 하겠습니다. A 자동차는 BaseCar와 ICruiserable를 상속받는데요.

이런식으로 구현합니다. 이때 에러가 나는 것을 볼 수 있는데요. BaseCar에 함수와 ICruiserable의 함수를 A_Car에서 구현하지 않았기 때문에 이런 에러가 생기는 것입니다. 

이런식으로 구현을 해주면 에러가 안나게 됩니다. 이때 빨간줄이 나온 곳에 마우스를 올려놓고 Ctrl + . 을 누르게 되면 쉽게 자동으로 구현해줍니다. throw new NotImplementedException() 을 지워주고 원하는 기능을 구현하면 됩니다. 이런 방법으로 자동차 A, B, C를 구현하면 됩니다. 

여기서부터는 클래스 구조를 잘 잡아 필요한 기능을 미리 구현하고 상속 받도록 하여 중복된 개발이 되지 않으면서 클래스가 잘 구현되도록 해야합니다. 그리고 C#에서 인터페이스를 사용하면서 좋은 점은 해당 클래스를 인터페이스로 구분 할 수 있어요. 

예를 들면 ICruiserable만 상속받은 자동차들만 함수로 입력을 받고 싶을때 Type을 ICruiserable로 하면 해당 클래스에서 ICruiserable이 없는 클래스는 입력을 받을 수 없게 됩니다. 또 함수 내부에서는 Type을 비교하여 Boxing/ UnBoxing이 가능하기 때문에 마치 여러 클래스를 상속받아 사용하는 것과 같은 효과를 볼 수 있습니다. C#에서는 다중 상속이 불가능하기 때문에 인터페이스를 잘 활용한다면 큰 도움이 됩니다. 

지난 포스팅에서 Parallel을 사용하여서 병렬처리하는 방법에 대해서 이야기 했습니다. 아래 글을 참고하시면 볼 수 있습니다. 

https://math-development-geometry.tistory.com/37

불러오는 중입니다...

이번에는 병렬처리시 Thread에 안전한 ConcurrentBag을 사용하는 방법에 대해서 이야기해보겠습니다. 우선 그전에 ConcurrentBag이란 무엇인지 알아보겠습니다. ConcurrentBag은 평소 자주 사용하는 List을 병렬처리하여 추가하거나 삭제하는 경우에 데이터가 안전하게 보관되도록 만든 클래스입니다. 사용법은 아주 간단한데요. List와 똑같이 사용하면 됩니다. 

List와 같은 방법으로 선언하여 데이터를 추가하였습니다. 현재 각 공간에 1,2,3,4 가 들어있습니다. 여기서 삭제하는 것을 알아보면 List 에서는 Remove, RemoveAt, RemoveAll과 같은 함수가 있습니다. 이때 List에서는 데이터 삭제가 일어나면 각 item들의 인덱스와 링크 주소가 바뀌게 됩니다. 그렇기 때문에 한개의 item을 삭제하고 있는 중에 다른 item을 삭제하면 문제가 생기게 됩니다. 평소 병렬 프로그래밍을 하지 않았다면 전혀 문제가 되지 않았을 것입니다. 왜냐하면 한개를 삭제하고 삭제가 끝나면 다음 item을 삭제하기 때문이죠.

하지만 병렬처리를 하게 되면 한개의 item이 삭제되고 있는 중에 다른 item이 삭제될 수 있어요. 그렇기 때문에 에러가 생기게 됩니다. 이때 에러를 막기 위해서 사용하는 것이 ConcurrentBag인 것입니다. 여기에는 List에 없는 함수가 있는데요. TryPeek과 TryTake입니다. 함수명에 Try가 있기 때문에 반환값은 bool 값인데요. 해당 함수가 성공하면 true 실패하면 false를 반환하는 것을 알 수 있습니다. TryPeek 함수는 해당 ConcurrentBag에서 가장 마지막에 추가된 item이 무엇인지 out 키워드를 통해서 반환하는 함수입니다. 반환할때 해당 ConcurrentBag에서 item이 삭제되지 않습니다. 반대로 TryTake함수는 마지막에 추가된 item이 반환되면서 해당 ConcurrentBag에서 삭제가 됩니다.

그렇기 때문에 필요한 함수를 잘 선택하여 사용하는 것이 좋습니다. 

실제 List를 사용하여 Parallel를 돌리게 되면 다음과 같이 에러 메세지가 생길 수 있습니다. 하지만 ConcurrentBag을 이용하면 같은 코드지만 문제 없이 돌아갑니다.

사실 이 내부를 구현하기 위해서는 다양한 작업이 필요한데요. C# 같은 경우에 이런 번거로운 작업을 대신 해주고 있기 때문에 정말 편하게 사용할 수 있는 언어입니다. 단 내부가 어떻게 돌아가고 어떤 방식인지 알고 사용하는 것과 모르고 사용하는 것은 큰 차이가 있겠죠. 다음에 기회가 되면 내부가 어떤식으로 작동하는지에 대해서 이야기해보겠습니다.

컴퓨터가 발달되면서 다양한 기법들이 생기고 있습니다. 그 중에서 가장 중요하면서 당연한 기법이 병렬처리입니다. 대부분의 사람들은 한 순간에 한가지 일을 하는걸 힘들어 하지만, 컴퓨터는 한번에 여러가지일을 쉽게 처리할 수 있도록 설계되어 있는데요. 여러개의 cpu에 동시에 작업을 하도록 하여 처리 속도를 올리는 것입니다. 그렇다면 C#에서는 어떻게 병렬처리를 할 수 있는지 알아보겠습니다.

.Net 4.0에서 Parallel 이라는 것이 지원되었습니다. Parallel은 병렬 프로그래밍을 쉽게 할 수 있도록 만든 클래스입니다. Parallel은 System.Threading.Task에 가면 찾을 수 있습니다. Parallel에서 가장 많이 사용하는 것은 For와 ForEach입니다. 

우선 Parallel.For부터 살펴보면, 어떤 인덱스를 갖고 0번부터 100번까지 { } 안에 작업을 병렬로 처리하겠다는 뜻입니다. 기존의 for문은 index가 증가하거나 감소하면서 순서대로 하나씩 작업을 실행하지만, 위의 경우는 작업을 여러개로 나눠 동시에 실행하기 때문에 순서대로 실행되지 않습니다. 대신 더 빠른 속도로 작업을 끝낼 수 있습니다. 

ForEach를 사용하여서도 병렬처리를 할 수 있는데요. 이때는 List와 같이 여러개의 데이터가 들어가 있는 공간이 필요합니다. 예를 들어서 반 아이들의 키를 저장하고 있는 List가 있다고 할때, 이 키를 이용해서 바지 사이즈를 자동으로 측정하는 프로그램을 만든다고 가정해보죠. 이때 반 아이를 0번부터 100번까지 for문을 돌리면서 한명씩 측정할 수 있겠죠. 하지만 이보다 더 빠르게 하기 위해서는 ForEach를 이용해서 동시에 여러명을 측정하는 것이 가능해지는 것이죠. 이때 측정하는 함수는 각각 다른 메모리에서 서로의 데이터를 공유하면 안되는데요. 이 이야기는 뒤에 Invoke에 대한 설명을 보시면 이해가 될 것입니다. 

마지막으로 많이 사용하는 병렬처리 방법 중에 Invoke가 있습니다. Invoke는 특정 동작을 병렬로 실행할 수 있는데요. 

사용법은 이렇게 사용합니다. 동시에 함수 1~5를 실행한다는 함수입니다. 사용법은 정말 쉽습니다. 병렬처리를 하는데 있어서 가장 중요한 것은 메모리를 관리하는 것인데요. 만약에 각 함수가 실행되면서 같은 값에 접근하면 어떻게 될까요? 예를 들면 택시요금을 측정하는 기계를 만들었다고 할께요. 이 택시 요금 측정기는 인터넷에 연결되어 있어서 각 택시마다 요금이 어떻게 측정되는지 관리하고 기록할 수 있어요. 그런데 서버에 한 메모리에 가격이라는 변수가 있는데, 모든 택시에서 한 변수에만 접근해서 가격을 올리거나 내리거나 초기화한다면 어떻게 될까요? 아마 어떤 사람은 택시 요금이 10만원이 나오고 어떤 사람은 기본료만 내는 상황이 생길 수 있겠죠. 아마 자기 마음대로 요금이 바뀔 것 입니다. 각 택시들은 각자 독립적인 메모리를 갖고 있어야 안전하게 요금을 관리 할 수 있습니다.

이렇듯이 병렬처리를 할때는 입력과 출력을 정확하게 구분짓고 함수 내부에서 사용되는 메모리가 서로 공유되지 않도록 하는 것이 중요합니다. 물론 의도적으로 공유할 수 있지만 좋은 방법은 아니라고 생각됩니다. 

3세대 코인으로 유명한 코인 중 하나인 이오스에 대한 이야기를 하도록 하겠습니다. 이오스는 2017년 6월에 이더리움의 DApp으로 만들어져 ERC-20 토큰으로 상장되었습니다.  채굴 방식은 위임지분증명(DPoS)입니다. DPoS 방식은 이오스 블록체인 상에서 이루어지는 모든 트랙잭션을 BP로 불리는 21명의 대표자들의 노드에 이루어집니다. BP가 되기 위해서는 일정 수량의 코인을 확보하고 있어야하며, 이오스 홀더들의 투표를 통해서 BP로 선정됩니다. 

이오스는 처음 이더리움의 DApp으로 시작하였지만, 1년 뒤인 2018년 6월 메인넷을 런칭하고 독자적인 플랫폼 코인이 되었습니다. 이오스는 웹어셈블리, 러스트, C, C++ 언어와 같이 개발자들에게 익숙한 언어로 개발되었습니다. 이더리움은 솔리티라는 언어를 이용해야 하고 이는 친숙하지 못한 언어로 불편함이 있었지만, 3세대 코인인 이오스는 퀀텀과 같인 다양한 프로그래밍 언어를 지원하게 됩니다. 

https://math-development-geometry.tistory.com/35

불러오는 중입니다...
위임지분증명 (DPoS)

이오스는 이더리움의 킬러로 알려져 있습니다. 이더리움 네트워크에는 1000개가 넘는 DApp이 존재하고 있기 때문에 전송속도가 느려지는 문제가 있었고, 이로인해 수수료가 높아지는 현상이 발생하게 됩니다. 이를 해결하기 위해 이오스가 만들어졌습니다. DApp 사용자들이 즉각적인 반응 속도를 위해서는 이더리움보다 더 빠른 네트워크가 필요하였고 이를 이오스가 선택한 방법은 21명의 블록 생성자(BP)를 선출하고 21개의 노드에서만 트랜잭션을 처리하는 방식이였습니다. 따라서 이오스는 이더리움에 비해 엄청난 처리 속도를 갖게 되었지만, 모든 블록이 아닌 21개의 노드에서만 처리되기 때문에 보안은 이더리움보다 떨어지게 됩니다. 

또한 이오스는 사용자 거래 수수료가 무료이기 때문에 수수료가 비싼 이더리움에 비해 좋은 경쟁력을 갖게 됩니다. 

 

배경

비트코인이 1세대, 이더리움은 2세대라고 할 수 있습니다. 그렇다면 3세대 코인도 있겠죠. 대표적인 3세대 코인으로 이오스나 퀀텀이 있습니다. 오늘 소개할 코인은 바로 퀀텀코인입니다. 퀀텀 코인은 싱가폴에 법인을 설립하였고, 대표 개발자로 패트릭 다이가 있습니다. 그는 알리바바 출신의 개발자인데요. 블록체인을 알게 된 이후 2014년 비트베이를 개발하였지만, 스캠으로 판명나면서 사기꾼으로 알려지게 됩니다. 이후 그는 원래 이름인 스티븐 다이에서 패트릭 다이로 개명을 하게 되고 2016년 퀀텀이라는 코인을 만들면서 다시 블록체인 업계에 진출하게 됩니다. 퀀텀 코인은 비트코인의 UTXO 디자인과 이더리움의 EVM과 스마트 컨트렉트와 같은 여러 장점을 모아서 만든 코인입니다. 비트코인과 같은 SHA-256 알고리즘을 사용하고 자체 네트워크에서 DApp을 만들 수 있게 여러 기능을 제공합니다.

채굴방식

퀀텀의 채굴 방식은 비트코인과 이더리움이 채택한 PoW 방식이 아닌 PoS (Proof of Stake) 방식을 사용합니다. 이 방식은 기존의 채굴방식과는 많은 차이가 있는데요. 기존 방식은 해쉬율이 높은 채굴자가 더 많은 코인을 가져가게 되는 구조로 해쉬율을 올리기 위해 더 좋은 채굴기를 사용하여야 했는데요. PoS 방식의 경우 높은 채굴 비용이나 유지 비용을 낮추고 해쉬율을 독점하는 문제를 해결하였습니다. 퀀텀 코인을 보유한 하드월렛에 Staking을 하게 되면 일정 수량의 퀀텀을 묶어놓게 됩니다. 일정기간동안 이동이 불가능한 상태가 됩니다. 이 기간동안 Staking된 퀀텀 수량만큼의 확률로 블록을 채굴하게 됩니다. 예를 들어 전체 코인이 100개가 있고 내가 10개를 Staking 했다면 10%의 확률로 코인을 얻게 됩니다. 그렇기 때문에 더 많은 코인을 갖고 있으면 더 많은 코인을 이자 개념으로 받을 수 있습니다.

퀀텀 위성

퀀텀의 개발 계획 중 가장 특이한 것이 위성을 통한 네트워크입니다. 2022년가지 72개의 위성을 우주로 보내, 모든 지역에서 퀀텀 네트워크가 가능하도록 하는 것입니다. 이렇게 되면 인터넷이 없는 지역에서도 퀀텀 네트워크를 통해서 IoT와 같은 기술을 실현시킨다고 합니다. 현재까지 꾸준히 위성을 우주로 보내고 있습니다. 여기서 소형 위성은 큐브샛을 말하는 것인데요. 큐브샛은 소초형 위성으로 무게가 1kg~3kg 수준으로 아주 작은 위성입니다. 

가상머신 x86 VM

퀀텀의 또 다른 특징은 x86 VM 을 지원한다는 것인데요. 위성만큼 중요한 기술입니다. 기존의 이더리움은 많은 DApp을 갖고 있지만 솔리티 언어를 사용해야 한다는 문제가 있었어요. 솔리티 언어는 많은 개발자를 보유하지 않기 때문에 이더리움 DApp은 일반인들이 개발하기 어려운 문제가 있습니다. 하지만 퀀텀의 x86 VM은 C, C++와 같은 언어을 지원하기 때문에 퀀텀 네트워크를 이용하여 많은 개발자들이 쉽게 DApp 개발에 접근할 수 있습니다. 

비트코인 캐시는 비트코인의 하드포크로 인해 탄생한 코인입니다. 비트코인의 하드포크로 많은 코인들이 생겨났는데요. 가장 정통성있고 어쩌면 오리지널 비트코인이라고 할 수 있는 코인이 비트코인 캐시입니다. 우선 비트코인 캐시를 알기전에 우지한이라는 인물을 알아야 합니다. 우지한은 북경 대학교에서 경제학을 전공하고 사모펀드 분석가로 일하던 중비트코인 채굴사업을 시작하여 큰 돈을 벌었습니다. 비트코인을 직접 채굴하고 있었기 때문에 엄청 많은 수량의 비트코인을 갖고 있었고 자신의 채굴기를 이용해 해쉬파워를 움직일 수 있을 정도로 영향력이 강한 인물이었습니다. 현재는 비트메인의 CTO이고 중국에서 미국으로 본사를 이전하면서 채굴기 사업을 하고 있습니다.


그렇다면 왜 우지한이 나왔는지 이야기를 해보겠습니다. 비트코인이 탄생한 이유는 저번 포스팅에 이야기 했듯이 중앙집권된 화폐가 아닌 탈중앙화된 화폐를 만들기 위해서였죠. 비트코인에 대한 이야기는 아래 글에서 확인하실 수 있어요.

https://math-development-geometry.tistory.com/22

 

경제 이야기 - 비트코인, 가상화폐의 미래

비트코인은 2009년 사토시 나카모토라는 사람이 만들었다고 합니다. 필명을 사용하기 때문에 현재 국적이 어디인지 알 수 없고 누군지도 알 수 없습니다. 비트코인은 실제로 눈으로 보거나 손으로 만질 수 없는 화..

math-development-geometry.tistory.com

탈중앙화를 꿈꾸던 비트코인에 중앙화가 시작되었는데요. 그 중심에 바로 우지한이 있었습니다. 중국의 채굴업자들이 ASIC 채굴기를 이용하여 전문적으로 채굴하면서 시장을 주도할 수 있는 영향력을 갖게 되었습니다. 여기서 영향력은 해쉬율을 말하는데요. 자신들이 원하는 방향으로 해쉬율을 변화시켜 가격을 조정하게 됩니다. 이로 인해 비트코인 개발자들이 ASIC 채굴기의 특수한 기능을 무력화시키는 기능을 업데이트하려고 하였지만, 이미 중국 채굴진영에서 비트코인에 대한 영향력이 강했기 때문에 합의가 불가능해졌고, 이로인해서 비트코인은 두 종류로 나뉘게 되었고, 우지한을 중심으로한 진영의 코인은 비트코인 캐쉬가 되었습니다. 


그런데 이런 하드포크를 통해 가장 이득을 본 사람들은 채굴자입니다. 하드포크는 기존의 한 블록체인을 포기하는 것이 아니고 같은 체인이 복사되어 두개가 되는 것이기 때문에 비트코인을 10개 갖고 있었다면, 하드포크 시점에서 비트코인 10개와 비트코인 캐시 10개가 생기게 되는 것이죠. 


우지한 진영에서는 단순히 자신들의 채굴기를 포기할 수 없기 때문에 하드포크를 진행하였다는 인식을 피하기 위해서 비트코인의 블록 사이즈가 작다는 것을 문제로 비트코인 캐시는 블록 사이즈를 2배로 늘리겠다고 하였는데요. 다양하고 많은 일이 있었지만 결국 비트코인에 대한 시장 지배력을 지키기 위한 행동으로 보고 있습니다. 이후 실제로 우지한은 비트코인과의 전쟁을 선언하면서 다양한 방법으로 해쉬율을 가져가면서 비트코인 캐시의 가격을 상승시키기 위해서 노력하였는데요. 실제로 2017년 5배 가까이 가격이 상승하면서 한화 기준으로 287만원까지 오르는 결과를 보여줬습니다. 이후 비트코인 캐시는 비트코인 SV라는 새로운 코인의 탄생 배경이 되는데요. 비트코인 SV에 대한 이야기는 다른 포스팅에서 담도록 하겠습니다. 

+ Recent posts