Programming Erlang 을 읽다 든 생각

얼마 전에 Pragmatic Version Conrol using Git 이랑 같이 구입한 Programming Erlang을 읽는 중이다. ((한글 번역서가 있는데 모르고 영문 eBook을 구입해버렸다. 사고나서 다음날 출근해보니, 팀장형이 한글판 번역서를 보고 있더라 ㅠㅠ)) 읽다가 드는 생각은, 멀티스레드 프로그래밍 혹은 병행 프로그래밍(concurrent programming)은 그 “원칙”에서 거기서 거기구나란 느낌이 든다.

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

  • 변수 대입에 부가 효과(side-effect)가 없다 (erlang에선 변수에 한 번 대입하고 나면 끝이다)
  • 스레드/프로세스 간 동기화는 메시지 패싱을 통해서만 이루어진다
  • 스레드간 통신은 비동기적이다
  • 분산 환경(RPC-like distributed env.) 구축이 쉽다
  • side-effect가 없는 ((사실 전역 테이블을 다루는 API가 있어서 완전히 그런건 아니지만 그런 연산은 사실상 지양되는 걸로 보이니 그건 빼고 생각하겠다)) 함수형 언어

정도였다. ((내가 erlang에선 뉴비인지라 틀린 부분이 있을 수 있다. 그런게 있으면 알려주시라 :) ))

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

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

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

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

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

Jinuk Kim
Jinuk Kim

SW Engineer / gamer / bookworm / atheist / feminist

Articles: 935

7 Comments

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

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

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

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

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

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

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

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

Leave a Reply