News Feed

“각자의 영역에서 빛난다” 개발자가 사랑하는 JVM 4대 언어

컨텐츠 정보

  • 조회 391

본문

자바 가상머신은 자바뿐만 아니라 보편적으로 사용되는 다양한 언어를 위한 고성능 범용 런타임을 제공한다. 이번 기사에서는 JVM 언어 중에서도 특히 많이 사용되는 코틀린, 스칼라, 그루비, 클로저, 4개 언어의 특장점과 일반적인 사용례를 살펴본다.

코틀린

코틀린(Kotlin)은 최근 몇 년 사이 개발자들의 선호도가 급격히 상승한 현대적 언어다. 인기의 근원은 주로 객체지향과 함수형 프로그래밍 지원이 포함된 표현력이 뛰어난 구문에 있지만 그게 전부는 아니다. 코틀린은 자바와 상호운용이 가능하고 멀티플랫폼 툴과 교차 언어 컴파일을 제공한다. 다른 JVM 언어와 마찬가지로 그랄VM(GraalVM)을 사용해 코틀린을 네이티브 바이너리로 컴파일해서 시작과 종료, 런타임 리소스 사용 측면에서 뛰어난, 최적화된 배포가 가능하다.

2019년에 구글이 코틀린을 안드로이드 개발을 위한 선호 언어로 지정하면서 믿음을 보인 것이 개발자들 사이에서 코틀린의 인기가 급격히 높아진 기폭제가 됐다.

코틀린의 또 다른 강점은 인텔리J IDE를 만든 젯브레인스(JetBrains)가 지지한다는 점이다. 젯브레인스는 그동안 꾸준히 코틀린을 유지 관리 및 개선해왔다. 코틀린의 안정성을 보장하는 동시에 최전선에서 혁신을 이끌도록 한 이 같은 젯브레인스의 투자를 통해 개발자들이 가장 중시하는 두 가지 특성인 안정성과 혁신을 모두 확보하게 됐다.

자바와 100% 상호운용이 가능하므로 자바 개발자와 조직은 점진적으로 코틀린을 도입할 수 있다. 자바 개발자는 손쉽게 코틀린을 익힐 수 있고 그 반대의 경우도 마찬가지다. 두 언어를 동시에 다루기도 어렵지 않다. 숙련된 자바 개발자에게 코틀린은 자바의 확장 버전처럼 느껴진다. 물론 자바를 잘 모른다 해도 얼마든지 코틀린 전문가가 될 수 있다.

안드로이드에서 사용할 때 확실히 빛을 발하지만 서버 측 개발을 포함한 다른 영역에서도 인기가 높다. 코틀린은 DSL(domain-specific languages) 개발에 적합하다. 그중 하나인 코틀린 HTML DSL은 웹을 위한 강력한 내장형 서버 측 템플릿 언어다.

코틀린의 가장 잘 알려진 자산 가운데 하나는 널(null) 안전성 기능으로, 이를 통해 NullPointerException 발생을 최소화할 수 있다. String과 같은 표준 타입은 null 가능 한정자(String?)를 사용해 명시적으로 허용하지 않는 한 null로 초기화할 수 없다. null 가능 타입을 사용할 경우 안전성 확인 없이는 컴파일러가 액세스를 허용하지 않는다. 코틀린은 자바스크립트의 옵셔널 체이닝 연산자와 비슷한 널 안전 점 연산자(?.)도 제공한다. 다음은 코틀린에서 ?: 연산자를 사용해 기본값을 제공하는 예시다.

val length = middleName?.length ?: 0

이 예시에서 middleNamenull이면 length는 0으로 설정된다.

또 하나의 핵심 기능은 동시 작업을 관리하기 위한 체계적인 수단을 제공하는 코루틴이다. 코틀린의 코루틴은 고의 고루틴에 착안해 개발됐고, 이후에는 자바의 새로운 구조적 동시성 모델에 영향을 미쳤다. 아래 예시는 코틀린 코루틴을 사용해 비동기 로직에 동기식 구문을 제공하는 방법을 보여준다.

import kotlinx.coroutines.*fun main() = runBlocking { // main coroutine    // Launch a new coroutine    launch {        delay(1000L)       // suspend for 1 second        print("InfoWorld!")  // Print after delay    }    print("Hello,")      // The main coroutine continues }

여기서 다룬 내용은 코틀린이 가진 역량의 극히 일부일 뿐이지만 이 예시들만 봐도 개발자들 사이에서 인기가 높은 이유를 짐작할 수 있을 것이다. 코틀린은 주류 언어로서 JVM의 힘과 사용 범위를 대폭 넓혔다.

스칼라

스칼라(Scala)가 다른 JVM 언어와 차별화되는 부분은 함수형 프로그래밍을 바탕으로 하고 이를 엄격하게 구현한다는 점이다. 이 같은 이유로 함수형 프로그래밍을 선호하면서 JVM을 활용하고자 하는 개발자들이 스칼라를 선택하는 경우가 많다. 잘 알려져 있지는 않지만, 스칼라는 객체지향 프로그래밍도 충실히 지원한다.

스칼라는 대규모, 고처리량, 실시간 데이터 처리 용도로 인기가 높다. 스칼라는 빅데이터 스트리밍, 배치 처리, 분석, 머신러닝 등을 위한 분산 플랫폼인 아파치 스파크의 언어인데, 스파크가 함수형 연산자를 사용해 이벤트 스트림을 결합하는 스칼라의 역량을 광범위하고 효과적으로 사용한다는 점도 스칼라 도입에 힘을 싣는 또 다른 원동력이다.

패턴 매칭은 스칼라에서 가장 인기 있는 함수형 프로그래밍 기능 중 하나다. 다음은 흐름 제어를 위한, 스위치와 유사한 스칼라 구문의 예시다.

case class Message(sender: String, body: String)val notification: Any = Message("Ada Lovelace", "Hello, InfoWorld!")notification match {  case Message(sender, body) => println(s"Message from $sender: $body")  case "Ping"                => println("Received a Ping")  case _                     => println("Unknown notification type")}

여기서 notification이 메시지 타입일 경우 분기를 제공하며 해당 메시지의 속성을 받는 함수를 정의할 수 있게 해준다. notification"Ping"을 포함한 String인 경우 두 번째 case로 이동하고, 밑줄 문자는 기본값을 정의한다. 이 구조의 미학은 모든 것이 함수형 프로그래밍 패러다임 안에서 이뤄진다는 점이다.

스칼라는 함수형 프로그래밍의 또 다른 원칙인 불변성도 강조한다. 불변성은 오류 가능성이 적고 단순한 소프트웨어로 이어진다. 스칼라에서 주 변수 선언 키워드는 상수인 val이며, List, Vector, Map과 같은 내장 컬렉션은 모두 불변성이다. 컬렉션 수정은 filter와 같은 함수형 연산을 사용해 이뤄지는데, 이 경우 새 컬렉션이 생성된다.

스칼라는 동시성 측면에서도 강력하며 리액티브 스타일의 프로그래밍 시스템에서 액터(actor)를 활용한다. 스칼라의 액터 모델은 멀티스레드 분산 컴퓨팅 영역에서 잘 알려진 아카(Akka) 프레임워크의 기반을 구성한다.

스칼라는 고급 사용 사례를 지원하는 정교한 타입 시스템도 갖췄다. 다음은 추상 클래스와 인터페이스를 결합하는 트레이트(trait) 타입의 예시다. 트레이트 타입은 클래스가 추상 멤버와 구상 멤버를 모두 가진 여러 상위 클래스로부터 상속받을 수 있게 해준다.

trait Speaker {  def speak(): String   def announce(message: String): Unit = {     println(message)  }}class Dog extends Speaker {  override def speak(): String = "Woof!"}class Person(name: String) extends Speaker {  override def speak(): String = s"Hello, my name is $name."}@main def main(): Unit = {  val sparky = new Dog()  val ada = new Person("Ada")  println(s"The dog says: ${sparky.speak()}")   println(s"The person says: ${ada.speak()}")   ada.announce("I am learning about traits!") }

Speaker 트레이트에는 구상 메서드와 추상 메서드가 모두 있는데, 이를 확장하는 클래스는 두 개 이상의 트레이트를 동시에 확장할 수 있다. 추상 클래스로는 불가능한 부분이다.

물론 이게 스칼라의 전부는 아니지만 위의 예시만 봐도 스칼라의 매력을 느낄 수 있을 것이다.

그루비

그루비(Groovy)는 최초의 JVM 대안 언어다. 고도로 동적인 스크립팅 언어로, 단순하면서 형식에 얽매이지 않는 구문 덕분에 인기가 높다. 널리 사용되는 그래들(Gradle) 빌드 매니저의 언어이며 글루 언어로 사용되거나 애플리케이션에 맞춤 설정 가능한 확장 지점이 필요할 때 사용되는 경우가 많다. DSL을 정의하는 기능도 그루비의 대표적인 기능으로 알려져 있다.

자바에서 넘어온 개발자 관점에서 그루비는 자바에서 상용구와 딱딱한 형식을 없앤 변형처럼 느껴진다. 그루비는 기본적으로 자바의 상위 집합이다. 즉, 대부분의 자바 코드는 그루비에서도 유효하다.

그루비는 스포크(Spock) 테스트 프레임워크의 언어이기도 하다.

그루비는 “불필요한” 세미콜론을 없애고 선언되지 않은 변수를 자동으로 스크립트에 제공한다(스크립트 바인딩이라고 함). 이는 호스트 언어(특히 자바)가 그루비 스크립트를 위한 컨텍스트를 생성하고 사용자가 변수 선언 없이 기능을 구현할 수 있는 애플리케이션 확장과 DSL에 특히 유용하다.

다음 예시는 그루비의 간결한 특성을 잘 보여준다.

def list = [1, 2, 3, 4, 5]def doubled = list.collect { it * 2 }println("Doubled: " + doubled) //-> Doubled: [2, 4, 6, 8, 10]def evens = list.findAll { it % 2 == 0 }println("Evens: " + evens) //-> Evens: [2, 4]

여기서 함수형 프로그래밍을 기반으로 한 형식에 얽매이지 않는 그루비의 컬렉션 처리 방식을 볼 수 있다.

그루비에서 인기 있는 또 다른 기능은 동적, 선택적 타입 지정이다. 변수 타입을 선언할 수 있지만 필수는 아니다. 변수 타입을 선언하지 않으면 변수가 사용되는 방식에 따라 그루비가 알아서 관리하는데, 이를 덕타이핑(ducktyping)이라고 한다. 자바스크립트에도 비슷한 기능이 있다.

마지막으로, 그루비는 자바 리플렉션 API의 더 강력한 버전이라고 할 수 있는 메타프로그래밍을 지원한다

클로저

마지막으로 살펴볼 클로저(Clojure)는 리스프(Lisp)의 뒤를 잇는 언어다. 리스프는 머신 러닝과 기호 처리에 사용된 기반 언어로, 많은 언어에 영향을 미쳤으며 뛰어난 표현력과 단순한 구문, “코드가 곧 데이터”라는 철학의 조합으로 언어 애호가들 사이에서 특별하게 취급되는 언어다.

코드가 데이터라는, 이른바 동형성은 언어에서 코드가 데이터 구조로 표현된다는 것을 의미한다. 코드 표현을 소프트웨어로 직접 불러오고 조작할 수 있어 메타프로그래밍의 기회가 열리게 된다.

또한 코드가 데이터라는 특성은 매크로가 자신이 확장하는 코드 구문을 이해하는, 강력한 매크로를 가능하게 해준다. 매크로에 대한 이 접근 방식은 매크로가 단순한 텍스트이고 이로 인해 오류가 자주 발생하는 C와 같은 언어와는 다르다.

다음은 리스프와 비슷한 구문으로 작성된 클로저의 간단한 함수 예시다.

;; Comments in Clojure use double semi-colons(defn greet [name]  (str "Hello, " name "!"))

여기서 괄호 안의 블록은 코드가 곧 데이터 구조임을 보여주는 특징이다. 괄호는 컬렉션(목록)을 나타내며, 함수는 목록을 사용해 정의되고 호출된다(예를 들어 키워드, 함수 이름, 인자).

강력한 동시성 모델로도 잘 알려진 클로저는 애초부터 여러 스레드에 걸친 상태 관리를 단순화하도록 설계됐다. 불변성, 그리고 관리되는 상태 전환에 대한 충실한 지원에 초점을 두는 클로저의 특징은 다재다능한 동시성 언어의 기반이 된다. 스레드 간에 가변 상태를 조율(오류 발생 가능성 높음)하는 대신 불변성에 집중한다. 또한 클로저에는 가변 상태와 동시성을 다루기 위한 리엑티브 에이전트 모델도 포함돼 있다.

클로저는 고도로 구조적이고 정제된 언어다. 함수형의 철학을 엄격히 따르며, 개발자에게 상당한 권한을 부여한다. 설계와 실행에 관한 이런 특성 덕분에 클로저는 프로그래머가 선호하는 언어로 자리잡았다.

결론

이 기사에서 살펴본 4개의 언어는 JVM 대안 세계의 대표적인 언어라고 할 수 있지만 그 외에도 많은 언어가 있다. 특히 j루비(jRuby), 자이썬(Jython)과 같은 주류 언어의 JVM 버전도 있다.

코틀린은 이제 독자적으로 완전한 주류 언어로 입지를 다졌으며 최근 티오베(Tiobe) 상위 20위 안에도 들었다. 그러나 4개 언어 모두 각자의 특정 영역에서 강점이 있고, 모두 JVM 자체가 가진 강력한 힘을 잘 보여준다.

다음 표에서 4개 언어의 전체적인 특징을 간략히 볼 수 있다.

언어패러다임학습 난이도주요 사용례핵심 가치
코틀린OOP, 함수형(실용적)쉬움안드로이드 앱실용성, 안전성
스칼라함수형, OOP(엄격)보통빅데이터(스파크)타입 안전성, 확장성
클로저함수형(리스프)어려움데이터 중심 API단순성, 불변성
그루비동적, 스크립팅쉬움빌드(그래들)유연성, 스크립팅

dl-itworldkorea@foundryco.com

관련자료

댓글 0
등록된 댓글이 없습니다.
Member Rank