Elixir v1.20 릴리스 노트 / 새로운 기능
Elixir v1.20은 언어를 점진적 타입 언어(gradually typed language)로 변환합니다. 주요 핵심은 개발자가 기존 코드에 어떠한 타입 어노테이션을 추가할 필요 없이, Elixir 컴파일러가 이제 타입 추론을 수행하고 모든 프로그램에서 "verified bugs"—런타임에 실패가 보장되는 타입 위반—를 체크할 수 있다는 점입니다.
The Set-Theoretic Type System
Elixir의 새로운 타입 시스템은 건전하고(sound), 점진적이며(gradual), 개발자 친화적으로 설계되었습니다. 이는 집합론적 타입(set-theoretic types)을 활용하며, 이는 타입이 합집합(unions), 교집합(intersections), 그리고 부정(negations)과 같은 기본적인 집합 연산을 사용하여 구성됨을 의미합니다.
The dynamic() Type and Bug Detection
많은 점진적 타입 시스템에서 발견되는, 종종 타입 체크를 비활성화하는 any() 타입과 달리, Elixir의 dynamic() 타입은 타입 정보를 유지합니다. 이 타입은 두 가지 핵심 속성을 가집니다: compatibility와 narrowing입니다.
- Compatibility: 타입 위반은 제공된 타입과 허용된 타입이 완전히 서로소(disjoint)일 때만 보고됩니다. 만약 어떤 겹침(교집합)이 있다면, 코드는 호환 가능한 것으로 간주됩니다. 이는 동적 코드를 다룰 때 정적 타입 시스템에서 흔히 발생하는 동일한 양의 오탐(false positives)을 방지합니다.
- Narrowing: 타입 시스템은 변수가 사용됨에 따라 그 타입을 정제(refine)할 수 있습니다. 예를 들어, 변수가 맵 키 접근(
data.a)으로 사용되면, 컴파일러는data의 타입을:a키를 포함하는 맵으로 좁힙니다(narrowing). 만약 후속 코드가 동일한 변수를 정수(integer)로 사용하려고 시도하면, 컴파일러는 좁혀진 타입(맵)이 예상된 타입(정수)과 서로소이기 때문에 위반을 표시합니다.
Type Inference in Guards and Clauses
Elixir v1.20은 여러 핵심 언어 구조 전반에 걸쳐 타입 좁히기(type narrowing)와 체크를 구현합니다:
Guards
컴파일러는 이제 가드(guards)로부터 타입을 추론할 수 있습니다. 예를 들어, when is_list(x)는 x가 리스트임을 추론하고, when not is_map_key(x, :foo)는 x가 구체적으로 :foo 키를 포함하지 않는 맵임을 추론합니다. 또한 데이터 구조의 크기를 추적합니다; when tuple_size(x) < 3과 같은 가드는 컴파일러가 튜플이 최대 두 개의 요소를 가짐을 알 수 있게 하여, 잘못된 elem/1 호출을 방지합니다.
Case Statements and Conditionals
타입 정보는 절(clauses)을 통해 정제됩니다. case 문에서 첫 번째 절이 nil과 일치하면, 컴파일러는 이후의 모든 절에서 해당 변수가 더 이상 nil일 수 없음을 알게 됩니다. 이러한 좁히기(narrowing)를 통해 컴파일러는 중복된 절을 찾고 기존 코드베이스에서 데드 코드(dead code)를 식별할 수 있습니다.
Compilation Performance and Tooling
Elixir v1.20은 특히 멀티코어 머신을 위한 컴파일 속도 개선을 도입합니다. 합성 벤치마크에 따르면, Elixir의 빌드 도구는 이제 BEAM 언어 중 가장 빠릅니다.
또한, 새로운 컴파일러 옵션인 :module_definition을 통해 개발자가 모듈 정의를 :interpreted로 설정할 수 있습니다 (via elixirc_options: [module_definition: :interpreted] in mix.exs). 이는 디스크에 기록되는 최종 .beam 파일에는 영향을 주지 않으면서 대규모 프로젝트에서 컴파일 시간을 단축할 수 있습니다.
Future Roadmap
While v1.20은 어노테이션 없이 타입 추론을 제공하지만, Elixir 팀은 여전히 명시적 타입 시그니처(explicit type signatures)의 연구 및 개발을 진행 중입니다. 이는 다음 기준이 충족된 후에만 도입될 것입니다:
v1.20의 타입 시스템 성능이 검증됨.
재귀 타입(recursive types)의 효율적인 구현.
매개변수 타입(parametric types)의 효율적인 구현.
열거 가능한(enumerable)으로서 맵 키-값 쌍을 순회하는 효율적인 구현.
Community Perspective
이번 릴리스에 대한 커뮤니티 피드백은 엇갈리지만 대체로 긍정적입니다. 일부 개발자들은 업데이트를 통해 제공되는 "free" 버그 탐지 기능을 찬양하며, 한 사용자는 다음과 같이 언급했습니다:
"It's very nice updating Elixir, having no breaking changes across my many projects and it then the compiler just finds bugs for free."
반대로, 일부 비판론자들은 처음부터 타입이 지정되지 않았던 언어에 타입을 추가하는 것은 Gleam이나 Rust와 같은 언어보다 본질적으로 덜 효과적이라고 주장합니다. 다른 이들은 이 방식이 Dialyzer의 "success typing"과 어떻게 비교되는지, 그리고 점진적 타입 시스템이 프로그램의 점진적 성능(asymptotic performance)에 대해 어떤 영향을 미칠지 의문문을 던집니다.
Source Material
- Official Announcement: Elixir v1.20 released: now a gradually typed language
- Research Paper: Elixir's type system design