map이라는 추상화...
reduce라는 추상화..
iterator라는 추상화..
future/promise라는 추상화...
async/await라는 추상화..
journal 이라는 추상화..
expression이라는 추상화..
vistor / Facade라는 추상화..
Traits라는 추상화..
match 라는 추상화..
executePlan이라는 추상화..
InvocationFilter라는 추상화..
Try 라는 추상화..
Composition이라는 추상화..
Channel이라는 추상화..

딱 봐도 저건 이것들을 보편화/간략화 한것이다라고 실체를 바로 판단 가능한 추상화가 있고,
대략적인 느낌 하에 세부 설명을 듣거나 해부해 봐야만, 실체에 대해 판단 가능한 추상화가 있다.

피카소의 황소그림 추상화(抽象畫) 는  전자이고, 

칸딘스키의 "즉흥"은 후자의 것이다. 

소프트웨어의 추상화(抽象化, Abstraction)는 어떤 개념들의 공통의 속성이나 기능을 묶어 이름을 붙이는 것인데,
이 것을 잘하면 먼가 대가 같아 보이긴 한다. 하지만 자동차를 움직인다고, 움직이는 것으로 추상화 하는 경우 

자동차로 명시적으로 표현하는 것보다 나을게 없을 수도 있는데 이런 경우도 많이 존재한다. 

사실 추상화는 오버엔지니어링과 구분하기 어렵다. 
치켜세워주면 유연한 설계를 한 것이고, 비판하면 시간만 잡아먹고 오히려 복잡하게 만든거 아니냐 할 수있다. 

그렇지만 나는 먼가 추상화를 하려고 노력해 놓은 코드를 보면, 어쨌거나 사랑스럽다. 
물론 GoF의 패턴에서 정의 해놓은 그 단어들은 그 책에서 나온 설계/의도대로만 사용해 줬으면 하기도 하지만, 
그 "의도"를 개인적으로 재설계해서 사용하는것을 뭐라고 하기도 참 머시기 하다...

...





"코딩을 잘하는 사람" 보다는 ooo 사람이 되라. <-- ?? 
"코더보다는 프로그래머가 되라" <-- ??
"코더/프로그래머 다음에는 관리자로 업그레이드 되야 한다" <- 아니다
" 코딩과 설계는 분리 가능하며 설계가 상위능력자의 일이다" <- 아니다


코딩이라는 단어에 대한 감각이 다들 다르니,  저런 식의 말들도 많이 있는거 같습니다.
저는 저런 식의 말들이 틀렸다라고 생각하진 않습니다. 옳을 수도 있는 말입니다.다만 그냥 저는 조금 다른 감각을 가지고 있습니다. (더 광의적으로 해석합니다. 아니 굳이 구분을 하는 의도에 불순함이 있어 보입니다) 

개발자의 '코딩'은 소설가의 '글쓰기'와 같다고 생각 합니다. (일맥상통하는 부분이 있다.)
소설가가 '글쓰기'를 잘하는 것은 가장 중요한 재능이나 노력의 결과인 겁니다. 
어떤 대학의 소설 한편 못써본 국문과 교수가, 직업 소설가를 바라보며 '글쓰기'는 사소한거다.
라고 말해바짜 비웃음만 당할 뿐이겠지요.  

'코딩'도 마찬가지입니다. '코딩'은 가장 중요한 덕목이며,
'코딩'을 잘하기 위해 서는 매일 매일 습작 하는 버릇을 들이고, 평생 '장인' 정신을 가지고 노력해야하는 일입니다.
'코딩' 도 잘하려면  어느정도의 재능과 하루하루 쌓아가는  오랜기간의 부단한 노력이 필요합니다. 

'코딩'을 잘한 다는 것은 

1. 어떤 주제에 대해서 유려하게 구성을 잡고, 꼼꼼하게 빈틈을 채워나가는 능력을 보유 한다는 것을 말합니다. 누구는 어떤 주제에 대해 겨우 10줄밖에 못짜겠지만, 누군가는 200줄로 짤 수 있을 수 있습니다. 
여기서 이 200줄이 쓸모없는 것이 아니라, 모두 필요한 요소들이라면 이 격차는 어마어마 한 것일 겁니다.

2. 문제해결을 위한 기본적인 지식을 기반으로 가지고 있거나, 상황에 따라서  빠르게 공부 할 수 있는 능력을 가지고 있어야 합니다.

3. 문제해결을 유연한 사고 방식으로 다른 각도에서 바라 볼 수 있는 창의력을  가지고 있어야 합니다.

4. 반복해서 고치고, 고민하고 덧붙히는 끈기가 있어야 합니다.

을 기반으로 코드를 작성해 나간다는 의미라고 생각합니다.

그러므로, '코딩'을 잘한다는 것은 우리 소프트웨어 개발자의 평생의 목적이지 않을까 싶습니다.
이렇게 정의를 내려 놓고 보니, '코딩' 을 잘하는 사람들에게 절로 존경심이 들며,  그 코딩의 다음 단계로 관리자가 되어야지, 코딩만 잘해서는 안되다는 말을 하는 사람들에게 역시 쓴 웃음이 나거나 고깝게 보이기도 하지만, 감각이 다르거니 하고 흘려 버려야 겠지요..

ps) 

코딩잘하는 사람을 보기란 정말 어렵습니다.
물론 모든 사람들이 최고의 능력을 보일 필요는 없습니다. 평범한 직업으로써의 능력만으로도 충분할 수 있으며, 삶을 영위 하는데 존중 받을 수 있습니다. 이게 "직업으로써의 소설가" 와는 조금 다를 수있는 부분 인거 같습니다. 

'소프트웨어 사색' 카테고리의 다른 글

스타트업 CTO 가 해야 할 것들 (링크)  (0) 2021.10.20
추상화  (1) 2021.08.29
왜 패턴이 중요한가?  (3) 2020.08.13
왜 야근해야 하는지 모르겠는데 설명 좀 해주실분?  (0) 2020.07.16
Rust  (0) 2020.06.16

https://www.dezeen.com/2014/08/29/campus-netzwerk-office-format-elf-architekten-perforated-aluminium/

패턴은 추상적인 "의도"를 보다 명확한 의미로 "규정" 을 짓습니다.
패턴을 사용하는 이유와 공부하는 이유는 아래와 같습니다.

- 그로 인해 선배로 부터 값진 경험을 물려 받게 해 줍니다. 
- 그로 인해 의사소통을 원할하게  만들어 줍니다.
- 그로 인해 자신의 생각에 확신을 갖게 합니다.
- 그로 인해 장점과 단점을 드러내 줍니다. 모든 패턴에는 장점과 단점이 있습니다. (모든 기술도 마찬가지)  

- 그로 인해 연관 패턴들과의 계층적 구조를 보여주어 큰 규모에서의 설계를 가능하게 합니다.
- 그로 인해 시야가 넓어집니다. 
- 그로 인해 이름 짓기 능력을 발전 시킬 수 있습니다. 
- 그로 인해 추상화 & 모듈화 능력을 발전 시킬 수 있습니다.

이제 다양한 패턴들에 대한 이름과 의도에 대해서 정리 해 보겠습니다. 

Gof 디자인패턴 

Creational 

패턴명 의도
Factory Method  
Abstract Factory  
Builder  
Prototype  
Singleton  


Sturctural

패턴명 의도
Adapter  
Bridge  
Composite  
Decorator  
Facade  
FlyWeight  
Proxy  


B
ehavioral

패턴명 의도
Interpreter  
Template Method  
Chain of Responsibility  
Command  
Iterator  
Mediator  
Memento  
Observer  
State  
Strategy  
Visitor  


켄트백 구현 패턴 

   
   
   
   
   


멀티쓰레드 디자인패턴 

패턴명 의도 
Single Threaded Execution   
Immutable  
Balking  
Producer-Consumer  
Read-Write Lock  
Thread-Per-Message  
Worker Thread  
Future   


POSA-2 (네트워킹) 디자인패턴 

이벤트 핸들링 패턴 

Reactor  
Proactor  
Asynchronous Completion Token  
Acceptor-Connector  

Synchronization Patterns

Scoped Locking  
Strategized Locking  
Thread-Safe Interface  
Doblle-Checked Locking Optimization  

Concurrency Patterns

Active Object  
Monitor Object  
Half-Sync/Half-Async  
Leader/Followers  
Thread-Specific Storage   


POSA-3 (리소스) 디자인패턴 

Resource Acquisition

Lookup  
Lazy   
Eager  
Partial  

Resource Lifecycle

Caching  
Pooling  
Coordinator  
Resource LifeCycle Manager  

Resource Release

Leasing  
Evictor  

 

메세지 큐 디자인패턴 

(work queue) Round Robin Dispatch 워커에게 하나씩 배분한다.
(work queue) Fair Dispatch 워커에게하나씩 배분하되, 작업시간도 감안해서 균등히 배분한다.
(pub/sub) Exchange  여러 소비자에게 한번에 다 나눠준다.
(routing) Direct Exchange 특정 데이터만 선택해 가져간다.
(topic) Topic Exchanges 패턴에 기반해 소비자가 가져간다.
(request/response) rpc 보내고 바로 받는다.

 


마이크로서비스 디자인패턴 

SAGA  
CQRS  
BFF  
회로차단   
백오프  
타임아웃  
상태점검  
서비스탐색   
부하분산 - 동일한것을 여러개로 복제
- 리소스가 다른것을 분리 
- 서비스가 다른 것을 분리 
캐싱   
동기/비동기 콜   
이벤트 소싱   
서비스별 DB   
격벽    


엔터프라이즈 어플리케이션 디자인패턴 

도메인 논리 패턴  
데이터 원본 아키텍처 패턴  
객체-관계형 동작 패턴  
객체-관계형 구조 패턴  
웹 프레젠테이션 패턴
 
분산 패턴
 
오프라인 동시성 패턴
 
세션 상태 패턴
 


Spring 프레임워크 디자인 패턴  www.baeldung.com/spring-framework-design-patterns

   
   
   
   



J2EE 프리젠테이션 패턴 

Intercepting Filter 패턴  
Front Controller 패턴  
Context Object 패턴  
Application Controller 패턴  
View Helper 패턴  
Composite View 패턴  
Service to Works 패턴  
Dispatcher View 패턴
 


J2EE 비지니스 티어 패턴 

Business Delegate 패턴  
Service Locator 패턴  
Session Facade 패턴  
Application Service 패턴  
Business Object 패턴  
Composite Entity 패턴  
Transfer Object 패턴  
Transfer Object Assembler 패턴  
Value List Handler 패턴
 
통합 티어 패턴
 
Service Activator 패턴
 
Domain Store 패턴
 
Web Service Broker 패턴
 

 

기업통합 디자인패턴 

Content based Router  
Message Filter  
Dynamic Router  
Recipient List  
Splitter  
Aggregator  
Resequencer  
Content Enricher  
Content Filter  
Pipes and Filter   


데이터 모델 패턴

   
   
   
   


DDD 디자인패턴 

   
   
   
   


빅데이터 디자인패턴 

람다   
   
   
   

 

메모리 매니지먼트 디자인패턴 

고정된 크기   
고정되지 않은 크기   
연속 할당 후 한번에 릴리즈   
Buddy   
tcmalloc  


데이타 베이스 디자인 패턴 

   
   
   
   
   

 

React 에서 사용되는 패턴 

Provider 패턴   
   
   
   

 

패턴매칭 (데이터 분석) 디자인패턴 

   
   
   
   

크립토 이코노미 디자인패턴 

   
   
   
   

크립토 보안 디자인패턴 

   
   
   
   

 

'소프트웨어 사색' 카테고리의 다른 글

추상화  (1) 2021.08.29
코더보다는 프로그래머가 되라?  (5) 2021.07.01
왜 야근해야 하는지 모르겠는데 설명 좀 해주실분?  (0) 2020.07.16
Rust  (0) 2020.06.16
소프트웨어 복잡도 줄이기 (1)  (0) 2020.05.13

이라는 후배의 질문에.....그냥 이 얘기 저 얘기 두서없이 주절거려 봅니다. 

------------------------------------------------------------------------
세상은  하나를 얻으면 하나를 버려야 한다고 합니다.
다 사람사는 곳이라.. 여러 생각들이 바람처럼 부드럽헤 흐르다가도 부딪히기도 하고 그렇습니다.

회사는 먼저 동호회가 아닙니다. 가족같은 회사, 친구같은 회사는 결국 문제만 생깁니다. 
따라서 아래 원칙만 지키시고, 중심을 잡으세요. (저도 못하는 것들 이고 저에게 하는 말이기도..)

1. 모두에게 친절하고 상냥하게 대한다. 조금은 손해보고 살자. 
2. 일과시간엔 적어도 6시간은 일에 초집중 하고 공유한다. (다만 일을 더 잘하기 위한 휴식같은건 필요합니다.) 
3. 특정 밥친구, 술친구, 커피, 담배 동료를 두지 않는다. 

회사에는 2,6,2 법칙이 있다고 합니다. 

자신을 좋아하는 사람 2
무신경한 사람 6
싫어하는 사람 2

모든 사람도 예외가 없습니다. 

님이 일에 에너지를 쏟는것으로 중심을 잡았으면 사람 (윗분이건 아랫분이건) 신경 쓰지마시고, 밀고 나가세요. 좀 외로워 질수도 있지만 두마리 토끼를 다 가질 수 없어요. 원칙,중심이 중요합니다. 한번 결과가 안 좋았다고 해서(야근안한다고 짤렸다? 실수가 있었다등 ) 원칙을 옮기지 마세요. 그럴수도 있지하고 쿨하게 넘기세요.  원칙을 옮기지 마세요. 그리고 사람에게 에너지를 쏟으면  인기인이 될 수도 있겠지만 불필요한 오해가 생길 수도 있습니다.  즉 다른 토끼를 놓치게 되는 것이 인지상정입니다. 

명확한 이유/보상이 동반되지 않은 "야근" ......님이 열심히 일 했으므로 눈치 보지 마십시요. 원칙대로 살면 ..스스로 떳떳하면 된 것입니다. 전 부장인데 6시 전에 퇴근하며, 다른 직급 분들은 야근하는 분들도 많은 거 같습니다. 저는 일찍 출근해서 일찍 가는 것을 좋아하고 늦게 출근해서 늦게 가는걸 선호하는 사람이 있을 뿐입니다. 강요하는 회사는 어차피 님 수준 보다 낮으니 미련두지 마세요

모두에게 시간은 똑같이 부여되나 사용하는 방식은 다릅니다.  스스로 명확하게 시간관리를 하게 되면 남들보다 더 많은 것을 얻을 수 있는데, 남 눈치보면 결국 인생의 많은 시간을 낭비하게 될 것입니다.
 
나이먹고 직급 높아지면 더 눈치보게 되는게 인생입니다. (꼰대는 나이랑 상관없어요.상황이 안그런 인간을 그렇게 만들기도 하고...아니기도 하고...저도 엄청 꼰대였다가 아니었다가 그럽니다.) 젊을 수록 기회도 많습니다. 요즘은 야근 강요하는 회사가 없어지고 있으며 점점 더 그럴 겁니다. 옮길 좋은 회사가 많아지고 있으니 실력을 쌓으시고 자신감 가지시고 화이팅 합시다.

'소프트웨어 사색' 카테고리의 다른 글

코더보다는 프로그래머가 되라?  (5) 2021.07.01
왜 패턴이 중요한가?  (3) 2020.08.13
Rust  (0) 2020.06.16
소프트웨어 복잡도 줄이기 (1)  (0) 2020.05.13
Go vs Rust vs C++ vs Java 등 벤치마크 이야기  (5) 2020.03.11

현대 프로그래밍에서 가장 중요한 오류들인 동기화 문제( 레이스컨디션이나 데드락등 )는 C++같은 언어로 개발한 제품들에서 굉장히 많은 문제를 발생시키곤 한다. 윈도우즈 오류의 대부분이 동기화문제, 메모리관리 문제라니까..

그중 동시성에서 레이스컨디션 문제는 
1. 가변변수인데 게다가 동시접근가능 할 때 발생된다.


2. 가변변수가 없거나 ㅡ 순수함수형
3. 동시접근예방 ㅡ Actor패턴 , CSP (예방이지 불가는 아님)

둘 중 하나만 충실 하면 근본적으로 없앨수 있다는 얘기이다. 

1번 경우는 뮤텍스등을 통해 직접 보호 장치를 해야 하는데 , C++,Java, Go 같은 착한 (방종 or 자유로운) 부모하에서 인간의 실수는 비일비재 하다. 배움이 모자르고 막나가는 아이들도 생겨남.

근데 러스트는 엄한부모라 자식 (프로그래머) 에게 관련 지식(스마트포인트류,LifeTime,RefCell등등)을 강제 요구하고, 각종 메모리를 사용하는 규칙이 이미 단단히 정해져있기 때문에  오류가능성을 컴파일 타임에 알려준다.

만약 팀을 결성하고 C++만큼 빠른 성능에 다가 무엇인가 오류없는 결과물을 만들고자 출발 할 때, 러스트를 선택하면 팀내에 최소한 막나가는 아이들은 없다는 안도감은 가질 수 있겠다. 

 

 

 

 

예) 블록체인에서 블록을 받아서 처리하기 

- 명령적

0. 서버에 클라이언트들을 등록하고 초기화 한다. 서버는 현재 running 상태이다. 
1. 입,출력 채널을 초기화하고 시작시킨다. 현재 connected 상태이다. 
2. Recv 이벤트를 event 쓰레드풀의 쓰레드 하나를 얻어서 등록한다.
3. Recv 이벤트를 기다린다. 
4. Recv 이벤트가 오면 읽을 수 있을 만큼 읽어서 버퍼에 저장해 두고, 채널은 다시 이벤트를 기다린다. 
5. Recv 한 데이터가 너무 많으면 버퍼는 자동으로 증가 하고 적으면, 이미 읽은 버퍼의 앞쪽으로 이동해서 채워진다. 
6. 채워진 버퍼는 유저 Handler에 세션정보와 함께 보내진다.
7. 유저는 어떤 세션에서 데이터가 왔는지 확인하고  버퍼에서 데이터를 4바이트 읽어서, 헤더를 확인하고, 바디 부분을 마져 읽는다. 전체 바디가 만들어지지 않을 경우, 상태를 읽고있는 중이라고, 유지하고 중단한다. 
8. 완전한 데이터가 읽혀지면, 블록이라는 객체를 만들어서 User application으로 보낸다. 
9. 블록의 헤더를 확인한다.
10. 블록의 바디를 확인하기 시작한다.
11. 정상포매팅인지 확인한다.
12. 서명이 제대로 됬는지 확인한다.
13. 데이터의 버전 및 커밋 될 수 있는지 확인한다.
14. 데이터를 데이터베이스에 저장한다. 
15, Event Hub에 결과를 알린다.
16. 웹,앱,모니터링 시스템등에 알린다. 

- 선언적

Core application) 
서버 : 서버는 클라이언트로 부터 접근하겠다는 이벤트를 받아서, 세션이라는 이름의 객체로 만들어서 관리합니다. 
세션:  클라이언트를 세션이라고 부르며, 클라이언트의 접속 상태를 관리하고, 입출력 채널을 관리합니다.
채널:  특정 클라이언트를 지칭하는 파일디스크립터를 읽기,쓰기 이벤트로 등록하고, 이벤트를 처리합니다.
버퍼:  버퍼는 바이트 데이터를 관리하는데, 읽을 수 있는 양, 쓸 수 있는 양에 대한 정보도 제공합니다. 
유저 핸들러 :  버퍼를 받아서, 패킷을 어플리케이션 레벨로 재구성 하고, 블록객체를 만든후 User단으로 보냅니다.

User application) 
Application: 블록을 받아서 처리 합니다. 헤더를 분석해서, 구분합니다.
Verifier : 서명을 확인합니다.
Committer : 데이터의 버전 및 커밋 가능성을 데이터베이스를 통해서 검증하고 저장합니다.
Notifier : 해당 블록처리에 관한 결과를 이벤트 허브에 전송합니다. 
EventHub: 웹,앱,모니터링시스템등 여러 단말 으로 보내 줍니다.


대게 복잡도는 단순하게 할 수 없다고 합니다. (쉬운 알고리즘으로 대체 가능한 일부 제외하고) 비지니스 로직적으로는 애초에 상태가 무지 많아지기 때문에 대부분 복잡도는 대개 구성원이 모두 익숙해지거나, 더 직관적인 아키텍쳐로 바꿔야 하는 방법뿐인데요. 보통 선언적으로 프로그래밍을 하면 유지/관리에 좋다고 합니다. 위에서 언급한 명령적/선언적 예는 좀 오버를 한거이구요. 사실 "for문으로 돌리면서 이렇게, 저렇게 한다" 를 map은 전체요소를 일률적으로 변경시킨다. fillter는 일부요소를 제거한다. reduce는 개개의 요소를 하나로 묶는다. 등등의 한단계 위의 추상화된 요소들로 선언하죠. 다음 글에는 위의 예제(상태가 굉장히 복잡한데, 매우 단순화 시켜 놓음) 중 일부를 하나는 Observer or Listener or Handler 식으로 코딩하고, 하나는 FRP (함수형 기반의 반응형 파라다임) 식으로 코딩해서 비교해보도록 하겠습니다. 

 

한국에선 Go가 1등, 세계적으론 Rust가 1등 - 사랑하고 배우고 싶은 언어 

 

1. 시작하면서

언어에 대한 벤치마크에 있어서 보편적, 절대적이란것은 없으며, 팀의 숙련도, 제품의 특징등에 따라서 성능/개발속도는 천차만별 일 것이다. 이 포스트는 그 동안 블록체인 연구만 하느라 잊어버린 코더라는 나의 정체성을 일 깨우고, 각 언어에 대해서 일단 빠른 시간내에 손가는 대로 만들면 어떻게 되는지 재미로 만든 것이며, 옵티마이징에 대한 부분은 전혀 신경 쓰지 않았기 때문에 객관적 지표로 삼을 수는 없을 것이다. 특히 CPU점유율 같은건 신경도 안썼다. 락을 안걸고 CPU 펌핑시키면 성능은 엄청 올라 간다. (참고로 코드 품질은 안드로메다) 이 벤치마크는 주로 생산자-소비자 패턴에 대한 테스트이며, 쓰레드끼리 데이터를 주고 받는 과정을 시뮬레이션 하였다. 현재 Future등을 통한 비동기 행위는 없으며 sequential(blocking)하게 통신이 이루어 진다. 

2. 벤치마크를 위한 심플 프로젝트

하이퍼레저 패브릭이라는 허가형 블록체인 시스템의 미니멀 버전으로써 코드의 주요 흐름은 2가지가 있는데 

1. 장부에 쓰기
   1-1. endorser들에게 보증 받기  <--- 벤치마크는 이 부분에서만 
   1-2. orderer/committer에게 값 보내서 영구저장 시키기
2. 장부에서 읽기

아래에 모듈간의 흐름을 그려보았다.

 

 

쓰기 순서

브라우저에서 신용장을 만들고 싶어서 해당 데이터를 백엔드로 보내고, 벡엔드에서는 하이퍼레저 패브릭 시스템과 통신할 수 있는 SDK를 호출 한다. 이 부분이 코드에서 미들웨어이다.

1. 미들웨어는 Endorsing Peer들에게 트랜잭션(Proposal request)을 요청함
2. Endorsing Peer 들은 해당 트랜잭션에 대한 체인코드를 호출하여 실행하고 결과값(RWSet)을 미들웨어로 돌려줌
3. 미들웨어는 RWSet을 받아서 보증에 대한 확인후 이상없으면 Orderer에 RWSet을 보낸다.
4. Orderer들은 받은 트랜잭션을  Kafka의 채널에 Push하고 , Pull 하여 정렬.
5. Orderer는 정렬된 트랜잭션 모음을 받아서 블록으로 가공.
6. 가공된 블록을 Commit Peer로 보내고
7. Commit Peer는 블록을 검증하고 Ledger (Blockchain + State Storage)에 저장.

 

 

읽기 순서
브라우저에서 신용장을 읽고 싶어서 백엔드로 요청. 벡엔드에서는 하이퍼레저 패브릭 시스템과 통신할 수 있는 SDK를 호출.

1. 미들웨어는 Commiting Peer에게 트랜잭션을 요청함
2. Commit Peer는 Ledger (State Storage)에서 정보를 가져온다.
3. 미들웨어(클라이언트)에 반납.

3. 결과

언어 성능 개발기간 개인적 언어 사용기간  요약   
Go 1.14  1(1)  1일 1년   x나 빠르네 (역시 성능 테스트는 뭘 하냐에 의존한다. b tree 같은거 하면 다를듯)
C++ 17 12 (4.2) 3일 13년 unique_lock과 condition을 직접 사용하여 concurrent queue를 만들어서 구현함. C++경력이 제일 길지만 중간에 멀리 했다 다시 하면서 디버깅하는데 애를 먹었다.  C++의 동시성 지원은 모던 C++ (11버전 이후) 들어서, 자바의 메모리모델을 참고하여 메모리 모델도 생기고, Thread, Lock도 생기는 등 뒤늦게나마  지원하기 시작했으며 C++20 를 통해 거의 완성 될 것으로 보이지만 역시 신세대 언어들에 비해 모듈 관리 편의성 및 유틸리티류가 부족.. 크로스플랫폼으로 가면...웬만한 경험치가 아니고선 후.. 
Java 11 1.6 (2) 1일 1년 lock과 condition도 사용하였으며, 의도적으로 LinkedBlockingQueue(블로킹) 과 concurrentLinkedList(비동기)를 혼합하여 사용하였다. java는 옛날 1.5버전부터 끝내주는 동시성 라이브러리를 많이 제공해 주고 있기 때문에 이것 저것 해볼게 많다. 
Scala 2.12 9.8(1.2) 2일 1년 akka의 actor패턴을 사용하여 구현하였다. go루틴/채널이 기본적인 것들만 지원하는것에 비해 정말 많은 것들을 지원해주고 있으며, 그 만큼 복잡하다. 양면의 칼!! 오랜만에 사용하다보니 삽질을 꽤나 했다. 
Rust  1.31 3.2(4.2) 3일 2주일 C++처럼 직접 동시성 큐를 만들려다가 채널라이브러리를 확인하고 go처럼 채널을 이용해서 만들어 보았다. 채널에는 std::sync::mpsc를 확장한 cossbeam::channel을 이용하였다. 참로로 이 채널은 Go와 다르게 recv시 블로킹을 하지 않는다. C++과 다르게 개발 편의 라이브러리가 대부분 존재 하고 Cargo덕분에 모듈관리편의성이 엄청 편해졌다. 물론 코딩하는 동안에 러스트의 러닝커브를 높이는 주범인 강제성 있는 소유권 문제, 라이프타임 문제등에 대한 에러가 당황스러웠으며 분석하고 수정하는데 애먹었다. 
Node 12.16 N/A(4.1) 1일 1개월 Since the release of Node.js v10.5.0, there’s a new worker_threads module available, and it has been stable since Node.js v12 LTS. There is a Message Channel that is a simple communication channel. It has two ends, which are called ‘ports’. In JavaScript/NodeJS terminology, two ends of a Message Channel are just called ‘port1' and ‘port2'.
Python 3.7 1000+(13) 1일 2년  Performance of this kind of pattern is very slow as i expected(GIL).  I think Python has to be only used like as asyncIO
Elixir 1.10.2  1.8(13) 1일 2일 Elixir is a dynamic, functional language Based on Green Thread, Actor model.
Actor communication is very fast but tail recursive optimization is not good.

* 성능은 낮을 수록 좋음 (100만 트랜잭션 처리 시간 기준)
* 사용기간이란 해당 언어를 사용(스터디, 쓰기,읽기) 해본 필자의 경력기간 
* 성능 괄호안은 Integer to String 변환 (32,000,000번 반복)
* rust, elixir, python, node is partially completed

4. 언어 별 썰을 풀어 보자면 

(Just my emotional criticize in some part but may be changed in future) 

C++
러스트와 다르게 메모리를 스마트하게 다루어도 되고,안 해도 되니 문제가 생길 수 밖에 없다. 개발자에게 자유를 준다. 망할 자유를... 즉 윈도우즈 버그의 70%이상이 메모리,동시성 문제. C++은 이제 이전에 레거시로 존재하는 것만 유지보수하고, 일반 서버솔루션에서는 Rust로도 시도를 해보는게 어떨 까 한다. 모던C++을 충실히 이해하는 당신은 비교적 무난하게 이동할 수 있다.(2022년에는 구글에서 C++개발자를 위한 새로운 언어인 카본이 등장한다. 코틀린이 자바개발자에게 그러하듯이 카본은 C++개발자에게 러스트보다 훨씬 더 상호호환성이 좋고 친숙하게 만들어졌다.) 혹시 자신은 C++ 버그 만드는 공장장이 아니라고 생각하나? 그럴 가망성이 없지만 믿어드린다. 다만 자신의 팀원들도 그럴까? 

@ 아직 아기인 Rust도 좀 더 떳으면 하는 마음에서 C++ 살짝 비판을 했지만 사실 나는 C++에 애증이 크다. (20년 개발자 인생중 13년을 C++을 했다) 따라서 이런 의견도 링크 해 드린다 : Rust 언어 비판과 C++이 사라지지 않을 이유 

아시다시피 모든 언어는 트레이드 오프가 있으니 무작정 하나를 깍아 내리지 말고 각 언어의 장점과 재미요소에 집중하는편이 좋다.

 

Criticizing the Rust Language, and Why C/C++ Will Never Die

We liked the article "Criticizing the Rust Language, and Why C/C++ Will Never Die" very much. We offer the author that we will do the translation on our own, and publish it in our blog. He agreed, and we represent this article in Russian and English with g

www.viva64.com

 

Java

자바로 코딩하면 제일 먼저 드는 생각은 모든 면에서 적당하다라는 느낌? 과한거 같기도 하고 ㅎㅎ 세계에서 제일 많이 사용되는 언어로 (특히 백엔드) 오랫동안 군림 할 수 있었던 여유와 안정성이 느껴진다. 특히 더그 리 덕분인지 동시성 지원 구성요소들이 잘 정리되어 있다. 2000년대 중반 부터 자바하면 다른 신생언어가 추종하는 성능 표준이 됬을 만큼 성능도 훌륭하다. (즉 이 정도 성능이면 웬만한 곳에서는 다 무리 없이 사용 가능) 편의성 + 성능 모두 대체적으로 만족 스럽다. 단 한가지 가벼운 쓰레드가 없는건 많이 아쉽다. 이 점 및 많은 부분에서 자바와 상호호환성이 좋은 코틀린은 정말 강력한 자바의 후계자 위치를 차지할 것 같다. 나도 코틀린으로 갈아탔고.

@ 자바와 코틀린의 가벼운 쓰레드 이야기는 여기 참고-> https://www.baeldung.com/kotlin/java-kotlin-lightweight-concurrency

String.valueOf(i)
* 자바와 스칼라에서 숫자 -> String 변환시 속도 차이가 약 2배나 차이나는데, 왜 그런지 누가 분석 해서 알려 주시면 좋겠다.

Go
절대로 Go로 하면 안되는게 아니고서는 (그런게 있을 확률도 희박, 가비지컬렉터 문제는 최신버전에서는 정말 더 좋아졌다.웬만하면 월드스탑 핑계는 대지말자) 즉 대부분의 프로젝트에서는 Go를 사용하자고 오버해서 말하고 싶다. 무엇을 하냐에 따라 달라지겠지만 최고의 전문가들로만 이루어진 팀이 아니라면 러스트,C++이 Go보다 성능이 더 좋을지도 의문사항이다. 다만 언어가 자유롭고 단순한 만큼 추상화 시키면 (특히 덕타이핑) 오히려 가독성이 많이 떨어지며 , 안전성은 러스트,스칼라에 비해 떨어지고, 스탠다드 라이브러리가 화려한 자바에 비해서는 기능이 빈약하긴 하다. 그럼에도 불구하고 서버개발의 첫번째 선택지로 두고 싶다. 한국에선 백엔드 개발에 있어서 스프링,노드가 디폴트이므로 직장을 찾는 주니어에겐 비추한다. 코틀린 굿!!

Rust
자신이 C++개발자인데, C++2X 버전들어서 RAII가 강제되고, Uniqued_ptr, move가 디폴트가 되었으며, Shared_ptr가 좀 더 세분화되어 강제되었다고 생각 해보자. 게다가 스칼라 같은 패턴 매칭 및 적절한 함수형 스타일 첨가와 Go처럼 클래스 없이 struct + traits의 덕타이핑 스타일로 변화 되었다고 하자. 그것이 Rust이다. 순수함수형 스타일이 아닌 언어로 멀티코어 프로그래밍을 할 때 얼마나 주의를 기울여야 안전한 솔루션이 나올 수 있는지에 대한 철저한 교과서이다. 즉 C++ 및 다른 언어로 개발 할 경우, 이 만큼의 주의를 기울이지 않을 가망성이 크기 때문에 버그가 끊임없이 생겨 난다는 얘기. C++은 자유(방관)를 주는 언어이고, 자바는 (최소한만) 알아서 챙겨주는 언어라면 러스트는 채찍들고 서방님을 최고의 장군으로 만들기 위해 맹훈련시키는 평강공주같은 스타일이다. 따라서 대중화 되기는 요원할 거 같다. 라이프타임의 책임이 컴파일러 제작사보다 너무 사용자에게 전가되어 있다. 대중은 쉬운길로 간다. 다만 팀원을 신뢰하게 만들고 성능이 최우선사항이며 사람목숨이나 큰 돈이 오가는곳에 C++,Go 대신해 쓰여 질 만하다. (근데 최근 스페이스X에는 일론 머스크가  C++를 욕하고도 결국 C++를 사용) 수년간 블록체인 분야에서 일하고 있는데 이쪽 분야가 비교적 Rust를 잘 사용한다. go에 비해 쓰레드가 무겁다는 것은 아쉽다.  green thread의 단점으로 의도적으로 제거했다고 하는데..태생이 시스템 언어라 green 쓰레드는 보통 VM기반에서 돌아가기 때문. 뭐 서드파티로 나오겠지..(rust goroutine equivalent golang -> https://github.com/Xudong-Huang/may)

Elixir 
Go에는 멀티코어 사용시에 mutable 사용이 너무 자유로우며 채널을 통한 메모리 공유로 안심하다가 뒤통수 맞을 가능성도 크다.(물론 심플하니깐 문제점 찾기도 비교적 쉬울 듯?)  Scala + akka 도 무거운데다가 구현하기 나름이지만 강제하지 않기 때문에 결국 비슷해보이고... Rust는 너무 복잡하게 관리를 유도하고...이런 전차로 벤치마크 리스트에 (비교적) 순수함수형 언어도 없고 해서 아무것도 모르지만 일단  Elixir를 구현해봤다. 안전성, 심플코딩이야 특유의 장점 인건 알겠는데 ...개빠르기 까지 하네?  Elixir is a dynamic, functional language Based on Green Thread, Actor model

 

 

5. 구현 코드

Go: https://github.com/wowlsh93/hyperledger-fabric-400

 

wowlsh93/hyperledger-fabric-400

hyperledger fabric in less than 400 lines of Go. Contribute to wowlsh93/hyperledger-fabric-400 development by creating an account on GitHub.

github.com

Elixir : https://github.com/wowlsh93/hyperledger-fabric-400-elixir
Scala:  https://github.com/wowlsh93/hyperledger-fabric-400-scala
Java:  https://github.com/wowlsh93/hyperledger-fabric-400-java
Rust :  https://github.com/wowlsh93/hyperledger-fabric-400-Rust 
C++:  https://github.com/wowlsh93/hyperledger-fabric-400-CPP  
Python: https://github.com/wowlsh93/hyperledger-fabric-400-python

6. 마무리

테크니컬 포스트라기 보다는 주관적 수필 같은 느낌의 코딩 작업과 글이 었습니다. 코드는 계속 수정 보완 될 것이며  실제 프로덕트에서는 Lock free 및 object copy관점에서 많은 최적화가 이루어 질 수 있을 것인데 언어별 문제점 및 동시성 최적화 후의 변화에 대해서는 (백수가 되면) 2편에서 다루어 볼 생각입니다. 

'소프트웨어 사색' 카테고리의 다른 글

Rust  (0) 2020.06.16
소프트웨어 복잡도 줄이기 (1)  (0) 2020.05.13
소프트웨어 아키텍트란  (0) 2019.12.11
'망할' 에이콘 출판사  (2) 2019.04.16
개발자 면접 방식을 바꾸자  (2) 2019.04.12

+ Recent posts