-
(3) 튜링팀과 람다팀, 자바튜링과 람다 2016. 3. 18. 14:44
이 글은 월간 마크로소프트웨어 2015년 8월 자바 특집호에 기고한 글입니다. 원고가 길어서 두편으로 나눠 올립니다. 지금은 마소가 발행 중단되어 링크를 찾을 수 없습니다.
# JVM 리그
프로그래밍 언어를 만들어야 하는 상황에 처했다고 생각해 보자. 풍부한 라이브러리와 좋은 개발툴이 지원되면 좋을 것이다. 개발자들이 좋아하는 Mac OS에서 개발도 하고 실행도 되면 좋겠다. 다양한 서버 환경에서 실행 되면 좋겠다. 이런 조건들과 많이 겹치는 게 하나 떠오른다. 바로 Java다. 만약 Java 언어를 빼고 JVM위에 새 언어를 실행할 수만 있다면 최고다. 다행히 Java는 이런 방식을 지원한다.
Java 언어와 JVM은 실행에 있어 무관하다. JVM은 오직 Java bytecode만을 실행한다. Java 언어 자체를 실행하지 않는다. Java 문법과 실행은 무관하다는 이야기다. 문법이 어떠하든 컴파일러가 Java bytecode로 바꿔주기만 하면 실행하는데 문제가 없다. 이 점이 언어를 만드는데 유용하다. 언어의 문법을 정의하고 컴파일러를 만들면 Java의 다양한 장점을 가질 수 있다. 처음부터 만드는 것보다 대폭 일이 줄어 든다.
” Most people talk about Java the language, and this may sound odd coming from me, but I could hardly care less. At the core of the Java ecosystem is the JVM. “
James Gosling (2011, TheServerSide)
Java는 프로그래밍 언어가 아니라 플랫폼이다. Java 플랫폼은 OS의 일부 기능을 가져간 모양세다. OS가 애플리케이션을 실행하는 역할을 Java 플랫폼이 대신한다.
JVM 위에 올라가는 프로그래밍 언어가 얼마나 있는 지 찾아봤다. 위키피디아에 정리한 페이지를 보니 언뜻 봐도 많다. 몇 개인지 세봤다. 딱 60개다. 찾아보니 언어는 더 있다. 처음 보는 언어가 수두룩 하다. 꽤 알려진 언어들만 몇 개 소개해 보겠다.
Scala 2001
JRuby 2001
Jython 2001
Groovy 2003
X10 2004
Fantom 2005
Clojure 2007
Ceylon 2010
Kotlin 2011
Xtend 2011
JVM리그의 많은 선수들을 두 팀으로 나눠 보자. 튜링팀과 람다팀이다. 두 팀을 오락 가락 하는 선수도 있다. 최근 멀티 패러다임 언어가 늘어나는 추세다. 객체 지향 언어에서 람다 함수를 받아들이거나 동적 타임 언어에서 정적 타입을 지원하는 등 다양하다. 이런 언어들은 시작을 어디서 했는 지를 기준으로 삼았다. Scala, Groovy, Java 8은 람다 함수를 지원하므로 멀티 패러다임이라 할 수 있다.
튜링팀
Java - JVM 리그 튜링팀의 주장, 객체 지향 언어이고 Java 8 부터 람다 함수를 지원
Groovy ( http://groovy-lang.org/ ) - 동적 타입 객체 지향 언어다.
Jython ( http://www.jython.org/ ) - Python의 Java 구현체다.
JRuby ( http://jruby.org/ ) - Ruby의 Java 구현체다.
Kotlin ( http://kotlinlang.org/ ) - 정적 타입을 지원하는 객체 지향 언어.
Ceylon ( http://ceylon-lang.org/ ) - Red Hat이 개발한 정적 타입을 지원하는 객체 지향 언어.
Xtend ( https://www.eclipse.org/xtend/ ) - Java의 방언이며 정적 타입을 지원하는 객체 지향 언어
Fantom ( http://fantom.org/ ) - 정적과 동적 타입을 지원하는 객체 지향 언어
람다팀
처음 보는 언어가 많다. 대중적이진 않다. 현재 실무에 도입 할 수 있는 언어는 Scala와 Clojure 정도다. 재밌게도 Apache Spark는 Scala로 개발됐고 Apache Storm은 Clojure로 개발됐다. 두 오픈소스는 실시간 분석 엔진이다. 공교롭게 둘 다 함수형 언어로 개발 됐다. Scala와 Clojure는 JVM 위에서 먼저 개발 됐다. 반면에 나머지 언어들은 기존의 함수형 언어들을 JVM위에 구현한 것이다.
Scala( http://www.scala-lang.org/ ) - 객체 지향을 지원하는 함수형 언어
Clojure( http://clojure.org/ ) - LISP을 계승하고 불변데이터를 지원하는 함수형 언어
Erjang( http://www.erjang.org ) - Erlang의 Java 구현체
Kawa( http://www.gnu.org/software/kawa/ ) - Scheme의 Java 구현체
Frege( https://github.com/Frege/frege ) - Haskell의 개념을 이어 받은 순수 함수형 언어
ABCL ( Armed Bear Common Lisp https://common-lisp.net/project/armedbear/ ) - LISP의 Java 구현체
람다팀 선수보다 튜링팀 선수가 훨씬 많다. 각 언어에 대해 자세한 내용은 찾아 보시길 바란다.
# 람다팀의 반등
튜링 머신과 람다 대수는 Java를 통해 만났다. 그 전에도 만나기는 했다. 근데 Java를 통해 만난 것이 특별한 의미가 있다. 우리 현실에서 함수형 언어를 사용해 프로젝트를 할 수 있을까? 거의 없다. 그러나 가능성이 생겼다. 전통적 함수형 언어는 산업적으로 의미있는 역할을 하지 못 했다. 산업적으로 퍼지기엔 약점이 많았다. 그 약점을 Java가 해결했다. Scala, Clojure는 Java 위에 올라 간다. 이제 우리는 람다 스타일로 실전 코딩을 해 볼 수 있다. 단, 회사가 허락을 해야 한다.
Java와 호환성은 매우 중요한 전략이다. Java가 20년 간 쌓아 놓은 탄탄한 기반 위에 그데로 올라간다. 풍부한 오픈소스, 라이브러리, 엔진, 프레임웍. Java가 진출하지 못 한 소프트웨어 분야는 거의 없다. 게다가 충분한 실전 검증을 받았다. 대부분 JVM 기반 언어는 코드 레벨에서 Java와 서로 호출이 가능하다. Wrapper는 필요 없다. 예를 들면, Groovy, Clojure 코드가 Java Swing을 호출할 수 있다. 그래서 Java의 견고함 위에 올라 갈 수 있다. Java 프로젝트는 많기 때문에 JVM 기반 함수형 언어를 사용해 볼 기회가 열렸다.
(import 'javax.swing.JFrame)
(def frame (JFrame. "Hello Frame"))
(.setSize frame 200 200)
(.setVisible frame true)< Java Swing으로 Frame을 생성하는 예제 코드 >
# 닮아가는 두 팀
재밌는 현상이 있다. Java, Groovy 등등 대부분의 객체 지향 JVM 언어들이 함수형 스타일을 받아들이고 있다. Java도 논란 끝에 Java 8에 도입했다. 물론 C언어 계열도 오래전 부터 지원했다. 함수형 언어들 중에도 객체 지향 개념을 받아들이는 경우가 있다. 이런 추세라면 결국 하나의 모습으로 수렴할 지도 모른다는 공상을 해본다. 지금도 정도의 차이는 있지만 어떤 언어로 개발을 해도 함수형 스타일을 쓸 수 있다.
기본적으로 객체 지향 언어는 인자로 객체를 넘넘기는데 함수형 언어는 인자로 함수를 넘긴다. 객체 지향 언어는 함수를 넘기기 위해 우회하는 방식을 사용하다 보니 코드가 복잡하다. 이 문제가 함수형 스타일로 깔금하게 해결 된다. 단지, 표현 방식을 바꿀 뿐인데 추상화 수준이 올라간다.
재밌는 진화가 하나 있다. Java는 개발자의 메모리 관리를 없앴다. 그 다음에 무엇이 없어지면 개발자가 편해질까? Thread 관리다. 물론 개발자가 Thread를 직접 다루는 일은 드물다. Netty나 Tomcat 등등의 추상화 된 엔진을 사용하기 때문이다. Thread를 직접 다루면 동시성 문제가 발생한다. 여러 Thread가 하나의 데이터를 동시에 변경할 때 발생한다. 게임 서버를 만들다 보면 흔히 발생한다. Thread 관리를 없앤 언어가 Clojure다. Clojure는 언어 차원에서 STM(Software transactional memory)을 지원해 동시성 문제를 해결했다. Clojure는 Thread를 직접 다루는 api가 없다. Java는 메모리 관리를 없앴고 그 위에 올라간 Clojure는 Thread 관리를 없앴다. 점점 추상성이 높아지는 방향으로 발전하고 있다.
# 튜링 머신 VS 람다 대수
두 개념의 대립 되는 점을 보면 확연히 이해가 될 것이다. 어느 쪽이 튜링 머신인지 람다 대수인지 느껴질 것이다. 느끼는 그데로다.
명사 VS 동사
데이터 VS 함수
How(어떻게 구현할 것인가) VS What(무엇을 구현할 것인가)
가변 데이터 VS 불변 데이터
Statefull VS Stateless
소설 VS 시
튜링 머신은 인간이 기계처럼 생각하고 람다 대수는 기계가 인간처럼 생각한다.
튜링 머신은 인간이 기계처럼 생각하고 람다 대수는 기계가 인간처럼 생각한다.# Java와 멀티 코어
이제 멀티 코어 시대다. 손에 들고 있는 스마트폰도 멀티 코어다. 멀티 코어를 지원하는 코드를 짜는 것은 어렵다. CPU Power를 총 동원하려면 Thread를 써야 하는데 잘 다루기가 만만치 않다. 뛰어난 개발자가 Thread를 잘 다루더라도 다시 난관을 만난다. 데이터가 깨진다. 불변 데이터(immutable data)를 사용해야 한다. Thread를 지원하는 어떤 언어로도 멀티 코어를 지원하는 코딩은 할 수 있다. 그러나 매우 불편하다. 동시성을 위한 변수를 전부 final로 선언하고 병렬로 처리해야 하는 로직을 샅샅이 분리해야 하는 등등 복잡하다.
멀티 코어를 잘 지원하기 위해서는 부수효과(Side-effect)가 없어야 한다. 기본적으로 튜링 머신 계통의 언어들은 상태를 사용하기 때문에 부수효과가 발생한다. 람대 대수는 기본적으로 부수효과가 없는 함수를 사용한다. 이 점때문에 멀티 코어에 함수형 언어가 유리하다. 부수 효과는 두가지 부분에서 발생한다. 데이터와 함수다. 데이터는 불변 데이터로 해결하고 함수는 순수함수로 해결할 수 있다. 이런 해결책들을 얼마나 지원하는 지가 멀티 코어 지원과 비례한다.
JVM기반 언어들은 다양한 방법으로 멀티 코어를 지원한다. Java는 Java 8의 람다와 java.util.concurrent를 통해 지원한다. Groovy, JRuby, Fantom, Xtend 등등의 언어들이 함수형 스타일을 통해 가능하다. Clojure, Scala와 같은 함수형 언어들은 기본적으로 강점이 있다. 특히, Clojure는 언어 차원에서 STM까지 지원하기 때문에 유리하다. 병렬 프로그래밍을 위해 설계한 X10이라는 언어도 있다.
# 다시 새로운 길
길 없는 곳으로 가는 사람들이 처음에 Real Machine 위에 언어를 만들었고 그 다음엔 Virtual Machine 위에 언어를 만들었다. 이젠 언어를 만들어 쓰는 시대다. 전체 흐름을 보았으니 앞으로 어떻게 전개 될지 즐거운 상상을 해보시기 바란다.
道行之而成(도행지이성) - 길은 걸어가야 만들어 진다.
-장자-
'튜링과 람다' 카테고리의 다른 글
(2) 튜링팀과 람다팀, 자바 (0) 2016.03.18 (1) 튜링팀과 람다팀, 자바 (0) 2016.03.18