함수형 언어의 정수를 JVM에 심으려 했던 실험, 스칼라(Scala)가 남긴 유산

대표 이미지

함수형 언어의 정수를 JVM에 심으려 했던 실험, 스칼라(Scala)가 남긴 유산

단순한 '자바 대체제'를 넘어 현대 프로그래밍 언어의 표준이 된 스칼라의 철학과 트레이드오프

현업에서 스칼라를 쓰시는 분들을 보면 참 흥미로운 공통점이 하나 있어요. 메인스트림 언어들에 비해 다소 투박하거나 안정성이 떨어지는 면이 있음에도, 기꺼이 그 불편함을 감수하시더라고요. 왜 그럴까요? 아마 ’10년 뒤에나 나올 법한 언어 기능’을 오늘 당장 내 코드에 써먹을 수 있다는 그 짜릿함 때문일 겁니다 [1, 2].

사실 스칼라는 단순한 언어 하나를 만드는 프로젝트가 아니었어요. 객체지향과 함수형이라는, 어찌 보면 서로 다른 두 세계를 극단적으로 통합해 보려 했던 거대한 실험이었죠. 그 과정에서 빚어진 엄청난 복잡성은 누군가에겐 진입장벽이었지만, 역설적으로 현대 언어들이 채택하는 수많은 고급 기능의 테스트베드가 되었습니다.

자바의 한계를 넘기 위한 마틴 오더스키의 실험

혹시 자바의 끝없는 보일러플레이트 코드나, 함수 하나 다루려고 익명 클래스를 덕지덕지 붙이던 시절 기억나세요? 마틴 오더스키(Martin Odersky) 교수는 바로 그 지점에서 갈증을 느꼈습니다. 당시 자바는 하위 호환성을 유지해야 한다는 제약 때문에 타입 인터페이스가 제한적이었고, 함수형 프로그래밍을 지원하기엔 턱없이 부족했거든요 [3].

그래서 2003년에 탄생한 게 바로 스칼라입니다. 이름부터가 ‘Scalable Language’의 약자일 만큼, 확장 가능한 언어를 지향했죠 [4]. 단순히 자바의 단점을 보완하는 수준을 넘어, 객체지향(OOP)과 함수형 프로그래밍(FP)을 완전히 통합해 복잡한 시스템을 더 간결하고 강력하게 구동하겠다는 야심 찬 목표를 가졌습니다 [3, 5].

결과적으로 스칼라는 강력한 정적 타입 시스템과 타입 추론을 도입했습니다. 덕분에 개발자는 타입의 안정성을 챙기면서도, 문법적으로는 훨씬 간결하게 코드를 짤 수 있게 되었죠.

스칼라가 정의한 ‘진정한’ 함수형 프로그래밍의 정수

스칼라를 쓰다 보면 “아, 이게 진짜 함수형 프로그래밍이구나” 싶은 순간들이 옵니다. 단순히 람다식 몇 개 쓰는 수준이 아니거든요. 스칼라에서는 함수가 ‘일급 시민’입니다. 함수를 변수에 담고, 다른 함수의 인자로 넘기고, 결과값으로 반환하는 고차 함수(Higher-Order Functions)가 기본이죠.

여기서 한 가지 짚고 갈게요. 함수형 프로그래밍의 핵심은 결국 ‘선언적’으로 짜는 것입니다.

“Functional programming is basically a declarative programming paradigm where we construct programs by applying and composing functions.” [4]

“함수형 프로그래밍은 기본적으로 함수를 적용하고 조합함으로써 프로그램을 구성하는 선언적 프로그래밍 패러다임입니다.”

특히 스칼라의 ‘케이스 클래스(Case Class)’와 ‘패턴 매칭’은 데이터 모델링의 신세계라고 할 수 있어요. 상태를 바꾸는 게 아니라 불변(Immutable) 데이터를 만들고, 이를 패턴으로 분해해 처리하면 상태 변경으로 인한 런타임 버그를 원천적으로 차단할 수 있거든요 [3, 4].

실제로 어떻게 쓰이는지 간단한 코드로 보여드릴게요.

// 불변 데이터를 정의하는 케이스 클래스
case class User(name: String, age: Int, role: String)

object UserProcessor extends App {
  val users = List(
    User("Alice", 25, "Admin"),
    User("Bob", 30, "User"),
    User("Charlie", 22, "User")
  )

  // 고차 함수(filter, map)와 패턴 매칭을 결합한 선언적 처리
  val adminNames = users
    .filter {
      case User(_, _, "Admin") => true // Admin 역할인 사용자만 필터링
      case _                   => false
    }
    .map(_.name) // 이름만 추출

  println(s"Admins: $adminNames") // 결과: Admins: List(Alice)
}

이 코드를 보세요. “어떻게 루프를 돌려서 값을 찾을까”를 고민하는 게 아니라, “어떤 조건의 데이터를 어떻게 변환할까”라는 의도만 명시합니다. 여기에 꼬리 재귀(Tail Recursion)나 모나드(Monad) 같은 개념까지 네이티브하게 지원하니, 복잡한 비즈니스 로직을 수학적으로 정교하게 설계할 수 있게 됩니다 [3, 4].

Kotlin vs Scala: ‘실용적 타협’과 ‘학문적 탐구’의 차이

많은 분이 코틀린과 스칼라를 비슷하게 보시는데, 사실 지향점이 완전히 달라요. 제가 보기엔 코틀린은 ‘실용적인 타협’이고, 스칼라는 ‘학문적인 탐구’에 가깝습니다.

코틀린의 최우선 과제는 자바와의 완벽한 호환성과 생산성이었어요. 그래서 자바의 불편함을 걷어내고 FP의 맛있는 기능만 쏙쏙 뽑아 넣은 ‘FP Lite’ 같은 성격이죠 [6]. 학습 곡선이 완만해서 자바 개발자가 금방 적응할 수 있다는 게 최대 강점입니다 [3].

반면 스칼라는 훨씬 더 깊은 곳까지 파고듭니다. 고차 종류 타입(Higher Kinded Types), 타입 클래스(Type Classes), For-comprehensions 같은 고급 추상화 도구들을 제공하거든요 [6]. 덕분에 컴파일 타임에 에러를 잡아내는 능력이 압도적으로 뛰어납니다. 런타임에 터질 버그를 컴파일러가 “야, 이거 논리적으로 말이 안 돼”라고 미리 알려주는 수준이죠.

물론 대가는 가파른 학습 곡선입니다. 코틀린이 “자바보다 편하게 짜자”라면, 스칼라는 “타입 시스템으로 완벽한 논리를 구축하자”에 가깝다고 보시면 됩니다 [3, 6].

함정: 추상화의 늪과 ‘오버 엔지니어링’의 위험

그런데 여기서 조심해야 할 함정이 있어요. 스칼라의 강력한 유연성이 때로는 독이 됩니다. 도구가 너무 좋으니까, 단순한 기능을 구현하는 데도 과도한 FP 패턴을 적용하려는 유혹에 빠지기 쉽거든요 [3].

실제로 제가 본 프로젝트 중에는, 단순한 CRUD 로직인데 모나드 트랜스포머(Monad Transformers)를 덕지덕지 붙여서 웬만한 시니어 개발자도 해석 못 하는 ‘외계어’ 코드가 된 경우가 있었습니다. 추상화 능력이 너무 좋다 보니, 설계를 지나치게 복잡하게 만들어 유지보수를 불가능하게 만드는 ‘오버 엔지니어링’의 늪에 빠지는 거죠 [3, 6].

팀 전체의 숙련도가 맞지 않은 상태에서 이런 코드가 양산되면, 그 프로젝트는 사실상 유지보수 불능 상태가 됩니다. “똑똑한 한 사람이 짠 코드가 팀 전체의 짐이 되는” 전형적인 사례가 여기서 많이 나옵니다 [6].

짚고 넘어갈 한계와 안티패턴

여기서 재미있는 논쟁이 하나 있어요. 일부에서는 스칼라가 모든 값을 객체로 취급하기 때문에 객체지향 언어로서 더 자연스럽다고 주장하기도 합니다 [7]. 하지만 실제 현장의 분위기는 좀 달라요. 스칼라 커뮤니티와 생태계는 이미 함수형 프로그래밍(FP) 쪽으로 훨씬 강하게 기울어져 있거든요 [6].

가장 위험한 안티패턴은 “스칼라를 쓰지만, 그냥 자바처럼 짜겠다”는 생각입니다. 스칼라의 복잡한 기능 중 일부만 골라 쓰려 해도, 결국 주변 라이브러리나 동료의 코드가 고도의 추상화로 작성되어 있다면 그 복잡성을 다 감당해야 합니다. 적당히 쓰려다가 오히려 더 복잡한 구현체에 갇히게 되는 경우가 많죠 [6].

핵심 요약

  • 스칼라는 단순한 언어가 아니라 OOP와 FP의 통합 가능성을 탐구한 거대한 실험이었습니다.
  • 강력한 타입 시스템은 런타임 에러를 컴파일 타임으로 끌어올리지만, 그 대가로 가파른 학습 곡선을 요구합니다.
  • 실용주의적 접근과 빠른 생산성이 필요하다면 코틀린을, 극한의 추상화와 대규모 데이터 처리가 필요하다면 스칼라를 선택하세요.
  • 도구의 강력함보다 중요한 것은 팀 내에서 유지보수 가능한 수준의 ‘추상화 합의’를 이루는 것입니다 [6].

스칼라를 단순히 ‘배우기 어려운 언어’라고 생각하면 아쉬워요. 우리가 지금 자바나 코틀린, 심지어 타입스크립트에서 당연하게 쓰는 현대적인 문법들의 상당수가 스칼라가 먼저 시도했던 실험의 결과물들이거든요. 그 실험 정신을 이해하고 내 코드에 적절한 수준의 추상화를 녹여낼 수 있다면, 어떤 언어를 쓰든 더 나은 엔지니어가 될 수 있을 겁니다.


참고 자료 (References)

1. [scala-lang.org] Evolving Scala — https://www.scala-lang.org/blog/2025/03/24/evolving-scala.html 2. [github.com] evolving-scala.md — https://github.com/scala/scala-lang/blob/master/blog/_posts/2025-03-24-evolving-scala.md 3. [hyperlinkinfosystem.com] Kotlin vs Scala – Choose the Right JVM Language for App Development — https://www.hyperlinkinfosystem.com/article/kotlin-vs-scala 4. [baeldung.com] A Comparison Between Kotlin and Scala — https://www.baeldung.com/kotlin/kotlin-vs-scala 5. [en.wikipedia.org] Scala (programming language) — https://en.wikipedia.org/wiki/Scala_(programming_language) 6. [news.ycombinator.com] Ask HN: Functional programming in Kotlin vs. Scala advantages/disadvantages? — https://news.ycombinator.com/item?id=28354799 7. [techtarget.com] Kotlin vs. Scala: Which one is right for your project? — https://www.techtarget.com/searchapparchitecture/tip/Kotlin-vs-Scala-Which-one-is-right-for-your-project

관련 글 추천

  • https://infobuza.com/2026/06/04/20260604-rohbg5/
  • https://infobuza.com/2026/06/04/20260604-gghibr/

FAQ

스칼라(Scala)라는 언어의 탄생 배경과 목적은 무엇인가요?

마틴 오더스키 교수가 자바의 보일러플레이트 코드와 제한적인 타입 인터페이스, 함수형 프로그래밍 지원 부족이라는 한계를 극복하기 위해 2003년에 만들었습니다. 객체지향(OOP)과 함수형 프로그래밍(FP)을 완전히 통합하여 복잡한 시스템을 더 간결하고 강력하게 구동하는 것을 목표로 합니다.

스칼라에서 함수형 프로그래밍의 특징은 무엇인가요?

함수를 변수에 담거나 인자로 전달하고 결과값으로 반환하는 '고차 함수'를 기본으로 하며, 함수를 적용하고 조합하여 프로그램을 구성하는 '선언적' 프로그래밍 패러다임을 따릅니다. 또한 케이스 클래스와 패턴 매칭을 통해 불변 데이터를 처리함으로써 런타임 버그를 차단합니다.

코틀린(Kotlin)과 스칼라(Scala)의 주요 차이점은 무엇인가요?

코틀린은 자바와의 호환성과 생산성에 집중한 '실용적인 타협'의 언어로 학습 곡선이 완만합니다. 반면 스칼라는 고차 종류 타입, 타입 클래스 등 고급 추상화 도구를 제공하는 '학문적인 탐구'에 가까운 언어로, 컴파일 타임에 에러를 잡아내는 능력이 뛰어나지만 학습 곡선이 가파릅니다.

스칼라를 사용할 때 주의해야 할 '오버 엔지니어링'이란 무엇인가요?

스칼라의 강력한 유연성과 추상화 도구 때문에 단순한 기능 구현에도 과도한 함수형 패턴(예: 모나드 트랜스포머)을 적용하여, 다른 개발자가 해석하기 어려운 복잡한 코드를 만드는 것을 말합니다. 이는 팀 전체의 유지보수를 불가능하게 만들 위험이 있습니다.

스칼라 사용 시 피해야 할 안티패턴은 무엇인가요?

'스칼라를 쓰지만 그냥 자바처럼 짜겠다'는 생각입니다. 스칼라의 일부 기능만 선택적으로 사용하려 해도, 주변 라이브러리나 동료의 코드가 고도의 추상화로 작성되어 있다면 결국 그 복잡성을 감당해야 하므로 적당히 쓰려다 오히려 더 복잡한 구현체에 갇힐 수 있습니다.

보조 이미지 1

보조 이미지 2

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다