Programming Erlang 을 읽다 든 생각

얼마 전에 Pragmatic Version Conrol using Git 이랑 같이 구입한 Programming Erlang을 읽는 중이다.[1] 읽다가 드는 생각은, 멀티스레드 프로그래밍 혹은 병행 프로그래밍(concurrent programming)은 그 “원칙”에서 거기서 거기구나란 느낌이 든다.

Erlang에서 병행 프로그래밍이 쉽고/성능이 잘 나온다는 이유로 강조하는게,

  • 변수 대입에 부가 효과(side-effect)가 없다 (erlang에선 변수에 한 번 대입하고 나면 끝이다)
  • 스레드/프로세스 간 동기화는 메시지 패싱을 통해서만 이루어진다
  • 스레드간 통신은 비동기적이다
  • 분산 환경(RPC-like distributed env.) 구축이 쉽다
  • side-effect가 없는[2] 함수형 언어

정도였다.[3]

실제로 C/C++로 병행 서버를 작성할 때에 보통 하는 일들이,

  • 메시지 패싱등을 사용하는 비동기 (작업) 큐 구현
  • 메시지 패싱을 통한 느슨한 동기화
  • 모든 작업은 비동기 적이며, continuation 같은 구현(혹은 closure나 C++ 0x lambda 같은 류)이 흔하다
  • 상수 값 사용이 많다. 변수들은 흔히 상수부(한 번 초기화 되고 변경하지 않는)와 변경 가능한 부분을 분리하고, 변경 가능한 부분에 적당한 동기화를 수행하게 짠다[4] .

이런 일이다. 덤으로 부가 효과라는게 생각만큼 — 그러니까 싱글스레드만큼 — 쉽게 쓸 수 있는게 아니게 되어서, 가능하면 함수형 언어에 가깝게 만든다. 힙 대신에 스레드 로컬한 장소 — 스택이라거나 TLS라거나 — 에 값을 보관한다거나. 비동기적으로 실행되고 / 중단되고 / 재개되는 closure 비슷한 것들(co-routine이라거나 C++ 0x lambda + thread 라거나, MS Windows fiber 류의 유저 레벨 스레드 팩키지 라거나 )을 사용한다.

다만 erlang에서 맘에 들었던 점은 — erlang이 만들어진 목적 때문이겠지만 — 이런 메시지 패싱 자체가 언어 자체 프레임웍으로 구현되어 있다는 것. 그리고 C/C++ 환경에서 프로그래머가 신경써야하는 상수 값 (혹은 단일 초기화 원칙) 을 언어 런타임이 처리한다는 것은 훌륭하다. 다만 게임 서버 같이 꽤나 단단히 묶여있는(tightly coupled system) 류의 응용에서 흔히 나오는 여러 값의 동시 업데이트 — 약간은 트랜잭션 같은 류의 — 는 어찌 처리해야할지는 아직 감이 잘 안온다.

ps. Project Euler를  erlang 연습삼아 풀어보고 있는데, 언어 자체의 라이브러리 탓인듯도 하지만 문자열 다루는게 너무 귀찮게 되어있어서 괴롭다. Python도 값이 상수라는 건 똑같(?)지만 이렇게 힘들진 않았는데(사실 그건 파이썬이 여러번 대입할 수 있어서 일지도 모르지만), 스크립트 언어류를 쓰다가 좀 더 static한 언어를 쓰려니 귀찮다.

  1. 한글 번역서가 있는데 모르고 영문 eBook을 구입해버렸다. 사고나서 다음날 출근해보니, 팀장형이 한글판 번역서를 보고 있더라 ㅠㅠ []
  2. 사실 전역 테이블을 다루는 API가 있어서 완전히 그런건 아니지만 그런 연산은 사실상 지양되는 걸로 보이니 그건 빼고 생각하겠다 []
  3. 내가 erlang에선 뉴비인지라 틀린 부분이 있을 수 있다. 그런게 있으면 알려주시라 :) []
  4. 락을 쓰든  RCU를 쓰든, 동기화 큐를 만들든 … []

Published by

rein

나는 ...

7 thoughts on “Programming Erlang 을 읽다 든 생각”

  1. side effect는 부작용으로 해석되는게 맞을것 같아요. 한글판 programming erlang에도 그렇게 번역했던데…부가 효과라는건 뭔가 가치를 더해준다는 늬앙스까지 가지고 있는 반면, 부작용은 negative한 것이 확실하니깐요. :)

    저도 rein님처럼 병렬처리의 원칙은 거기서 거기라는 생각이 들더군요.
    다만 언어 디자인시에 아예 반영했기때문에 발생하는 장점들이 많다는 생각..:)

  2. 근데 여기서(?)는 C/C++ 같은 언어에선 “공유된 메모리 영역을 변경하면서” 진행한다는 의미로 쓴거라서 부작용으로 하면 좀 괴로워요(??)

    네 병렬성의 원칙은 거기서 거긴데, 이걸 언어 차원에서 하는지 / OS나 라이브러리 차원에서하는지에 따라 편리함이나 이식성이 많이 갈리죠 :)

    1. 유니코드 지원문제야 그냥 binary 비슷하게 다룬다쳐도 데이터베이스 인터페이스는 좀 그랬어요 -_-;
      ODBC 라이브러리가 있는 것 같긴했지만, 편하게 구성되어있지가 않아보여서 Orz

  3. 최신 버전 erlang은 유니코드도 지원합니다. erlang에서는 RDBMS를 쓰는건 언어의 장점을 상쇄 시킵니다. Mnesia를 쓰는것이 맞고, Mnesia를 쓰려면 기존에 RDBMS에서 생각하던 DB구조를 버려야죠.

    1. kukhyun / Mnesia 를 쓴다면 제가 말한 문제점이 줄어들긴 합니다. 그렇지만 당장 밑바닥에서 다시 짜지 않는한 Mnesia 를 쓸 순 없습니다.
      이미 레거시 코드가 섞여있는 시스템에서 — 대부분 imperative 할 겁니다 — 당장 함수형 언어로 전환하기는 힘들기 때문에 기존의 RDMBS 를 무시하고 전환하는건 그다지 현실적이지 못합니다.

      1. 말씀하신 부분에 공감합니다. 따라서 elang은 밑바닥부터 다시 만들때 사용해야 합니다…

Leave a Reply