프로그래밍 일기 — Elixir

배우는 자(Learner Of Life)
11 min readNov 20, 2023

--

이 요상한 언어는 무엇인고?

elixir라는 마법 주문이 새로 생겼다고한다.(1)

프로그래밍 세계는 참 변화 무쌍하다. 내가 모르는 사이에 새로운 언어가 생기고 다음어진다. 도대체 Elixir라는 언어는 또 뭔가? 참 프로그래밍 세계의 마법사들은 부지런하다. 어떻게 새로운 마법 주문을 계속 만들어 낼까? 그만큼 우리가 배워야할 것들도 더 많아지는게 문제지만.

뭐 어쩌겠는가? 대세에 따라야지. 한 순간이라도 배우기를 멈추면 쉽게 도태될 수 있는 개발자의 숙명이다. 하지만 좋은 점도 있다. 그만큼 계속해서 배우기에 치매가 올 확률이 낮아지고, 계속해서 유용한 사람으로 남을 수 있다. 프로그래머가 배우기를 멈추지만 않는다면 가장 오래할 수 있는 직업이라고도 볼 수 있으니까.

오늘 배울 내용은 Elixir라는 언어다. 이 언어의 모든 것을 이 글에서 다룰 수는 없지만, 입문자 입장에서 무엇을 알아야하는지, 이 언어의 특징과 강점 그리고 전망에 대해서 배워보려한다.

Elixir(2)

영어로 “마법 물약"을 의미하는 이 단어는 아이콘 역시 마법의 약을 연상시킨다. 새롭게 생긴이 프로그래밍 마법 주문은 Jose Valim이라는 Ruby on Rails를 창시한 팀의 멤버가 처음 만들어 낸 언어다. 많은 사람들이 배울 수 있게, 함수형(functional)이면서 동시적(concurrent)인 언어를 창조하는 것이 본래 이 언어의 탄생 목적이었다. Valim은 Ruby on Rails의 성능을 개선하려던 중 Erlang의 생태계와 호환성이 맞지 않는 문제에 부딪혔다고 한다. 이를 보완한 언어가 필요함을 깨닫고 Erlang의 가상머신(VM)인 BEAM위에서 실행될 수 있는 목적을 가진 언어를 만들었다.

Elixir의 문법은 Ruby와 상당히 닯아있으며, 지금은 오류에 관대(fault-tolerant)하고, 스케일이 가능(scalable)하며, 유지보수(maintainable)가 가능한 어플리케이션을 만드는데 많이 활용되고 있다. 즉, 이 언어는 스케일이 가능하며, 동시성제어가 가능하고, 오류에 관대하며, 지연성이 낮다(low latency)는 특징이 있다.

Elixir vs Erlang

Elixir는 Erlang의 VM위에서 돌아가는 언어라고 이야기했다. 그 만큼 Elixir와 Erlang도 닮은 점이 있지만, 서로 사용되는 목적에 차이점이 있다.

두 언어는 동시성(concurrency)을 지원하며 오류를 허용(fault-tolerance)한다는 특징이 있다. 대용량 분산 시스템을 만드는데 안전한 언어라는 공통점이 있으나, Elixir는 Erlang보다 빠르다고 평가를 받는다. Elixir는 Erlang으로부터 OTP(Open Telecom Platform)라는 Erlang에서 동시성 프로그래밍에 활용되는 표준 라이브러리를 이어받았다.

여러 데이터베이스 및 프레임워크와 호환되는 언어를 원한다면 Erlang이 조금 더 좋은 선택일 수 있다. Elixir는 상대적으로 데이터베이스 및 프레임워크 지원에 한계가 있다. 그러나, 조금 더 다양한 클라우드 플랫폼과 호환되는 것을 원한다면 Elixir가 조금 더 나은 선택이다. Elixir는 Erlang에 비해 조금 더 다양한 클라우드 플랫폼을 지원한다.

Elixir와 Erlang의 차이점을 요약하자면 아래와 같다.

  • Erlang은 Elixir가 지원하지 않는 동작을 일부 지원한다. 예를 들어 Erlang에서는 논리연산자인 andor 를 지원하지만, Elixir는 그렇지 않다.
  • Erlang에서는 : 를 활용해 함수를 부른다, 그러나 Elixir는 . 연산자를 통해 함수를 부른다.
  • Elixir에서는 변수를 한번 이상 지정 가능하지만, Erlang에서는 변수를 한번 이상 지정할 수 없다. 만약 그렇게 하려한다면 Erlang은 에러를 발생시킬 것이다.
  • Elixir는 인자(argument)에 대한 기본값(default value)가 정의되어 있으나 Erlang은 그렇지 않다. 전체적으로 두 언어는 신뢰성이 높고 유지보수성이 높다. 최근에는 Elixir가 둘 중 더 많이 활용되는데, Elixir가 기능적으로 지원하는 것이 더 많고, 문법이 단순하며, 스케일링이 용이하기 때문이다.

Elixir의 기능 및 도구

  • Elixir는 Erlang VM이 해석할 수 있는 bytecode로 컴파일 한다.
  • 매크로(macro)를 활용하여 스스로나 다른 컴퓨터 프로그램을 데이터로 활용하는 메타프로그래밍(metaprogramming)과 프로토콜을 통한 다형성(polymorphism)이 가능하다.
  • 다른 함수를 인자로 전달받거나 결과를 함수로 반환하는 고차함수(higher-order functions)및 함수 스스로를 호출하는 재귀(recursion) 특성을 가지고 있다.
  • 스트림에 대한 Lazy하고 비동기적(asynchronous) 데이터 수집이 가능하다.
  • 패턴 매칭(pattern matching)
  • 원격 디버깅(remote debugging), 의존성관리(dependency management), 코드 컴파일(code compilation) 등의 기능을 내부에서 제공한다.
  • Elixir는 동적타입(dynamical-typing)을 지원하여, 모든 타입이 컴파일이 아닌 런타임에 체크된다. (컴파일이 아닌 런타임에서만 에러를 확인할 수 있다는 의미라서 이 부분은 단점이라 느껴진다.)

Elixir는 유용한 웹 개발 도구들도 지원한다.

  • Mix: 프로젝트를 생성하고, 테스트를 실행하며, 테스크를 관리하는 등의 작업을 지원하는 도구다.
  • IEx: Elixir의 상호적인(interactive) shell로써, 자동완성, 디버깅, 코드 재로딩(code reloading) 등을 지원한다.
  • Phoenix: 아마 현존하는 가장 좋은 웹 프레임워크로 여겨진다. Ruby on Rails처럼 MVC(Model, View, Controller) 아키텍쳐에 기반해 만들어졌다.

Elixir의 사용

Elixir는 그 어떤 규모의 웹 어플리케이션에 적합하며, JSON 혹은 GraphQL로 결과를 반환하는 웹 API 개발에도 매우 유용하다. 또한 이벤트 기반 시스템(event-driven systems), 분산 시스템(distributed systems) 및IoT(internet of things), 임베디드 시스템 등등 여러 분야에 많이 활용될 수 있다. 아래는 Elixir를 백엔드로 활용하는 대표적인 어플리케이션이다.

  • Discord: 2017년부터 Elixir로 백엔드를 변환하여 이후 5백만 유저를 동시에 처리하고 수백만 이벤트를 초단위로 처리하는 것이 가능해졌다.
  • Pinterest: Elixir를 활용해 알림 시스템을 구현하여 활용되는 서버의 수를 최소화하고, 코드를 더 깔끔히 정리했다고 평가받는다. Elixir를 백엔드로 활용해 초당 1만 4천개의 알림을 원활하게 전송할 수 있을 정도로 성능이 개선되었다.
  • Adobe: 어도비는 Elixir를 활용해 사진 협업 클라이언트/클라우드 앱 상에서 협업 사진 작업의 workflow를 만들도록 했다.

Elixir의 함수형 프로그래밍

Elixir는 함수형 프로그램이라고 이야기했다. 이 특징 덕분에 CPU 멀티코어를 더욱 효율적으로 사용할 수 있고, 더 짧고 더 명확한 코드의 작성이 가능하다. 함수형 프로그래밍을 제대로 이해하려면, 불변성(immutability), 함수(functions)및 선언형 코드(declarative code)를 알아야한다.

함수형 프로그래밍에서는 프로그램내 활용되는 모든 값이 불변(immutable)하다. 기본적으로 각 함수는 고정값을 가지며, 이는 별도의 고정 메커니즘을 필요로하지 않는다는 의미다. 이는 많은 작업들을 단순화 시킬 수 있다. 이러한 불변성은 최근의 프로그래밍 언어에서 많이 나타나는데, 불변성의 데이터 타입을 제공하거나 특정 값을 불변화 시키는 메서드를 구현해 불변성을 구현하고 있다.

함수형 프로그래밍에서 함수란, 프로그램을 만드는데 있어 가장 기본적인 도구이다. 함수가 아래의 특성들을 가질 때, 대용량 어플리케이션의 복잡도를 줄일 수 있다. 이러한 특성을 가진 함수를 순수함수(pure functions)라고 한다. 이보다 더 복잡하고 예측불가한 성질을 가진 함수들은 비순수함수(impure functions)라 한다.

  • 불변성의 값(immutable values)
  • 함수의 결과값이 함수의 인자에게만 영향을 받는다.
  • 함수가 리턴값이 만들어진 이후에는 아무런 영향을 주지않는다.

함수형 프로그래밍에서는 값들이 항상 함수들 사이에서 명확하게 교환되며, 이는 입출력값을 명확하게 만든다. 함수들은 역시 그 자체가 인자(argument)나 다른 고차 함수(higher order function)의 결과값으로 활용될 수도 있다.

선언형 프로그래밍(declarative programming)이란 문제 해결에 무엇이 필요한지 집중하는 프로그래밍 방법론이다. 즉, 문제를 어떻게 해결해야하는지가 최고 우선순위가 아니라는 말이다. 일반적으로 선언형 프로그래밍은, 반대개념의 명령형 프로그래밍(imperative programming)보다 더 깔끔하고 명확하다. 코드가 상대적으로 더 깔끔하고 명확하므로, 버그를 만들 가능성도 상대적으로 줄이기 용이하다.

Elixir 코드 예제

문자열(Strings)

Elixir는 UTF-8 을 활용해 문자열을 인코딩한다. UTF-8은 변수길이 문자 인코딩 방식으로 8비트(bit) 단위 바이트(byte) 1개에서 4개까지를 활용해 각 코드를 저장한다. 문자열은 다른 언어들처럼 "" 이 감싼다. 예를 들어 IO.puts("Hello World!") 로 작성한다.

원자(atoms)

변수 이름 자체를 값으로 갖는 상수(constant)를 말한다. 다른 언어에서는 상징(symbol)이라고 일컬어지는 개념이다. 특정 고유 값(distinct value)에 따라 열거(enumerate)할 때 주로 활용된다.

iex> :cat
:cat
iex> :dog
:dog
iex> :fish
:fish

논리연산자(Booleans)

Elixir는 truefalse 의 값을 가지는 논리연산자를 지원한다.

iex> true
true
iex> true == false
false

산술연산자(Arithmetic Operators)

/ 를 활용해 나누기를 하면 항상 정수(integer)값이라도 실수(float)으로 표현된다.

iex> 2 + 2
4
iex> 10 * 2
20
iex> 8 / 2
4.0

키워드 리스트(keyword list)

Tuple의 배열(list)이 있고 Tuple내 첫 값이 원자(atom)이면, 이를 키워드리스트(keyword list)라 지칭한다.

iex> list = [{:c, 1}, {:d, 2}]
[c: 1, d: 2]
iex> list == [c: 1, d: 2]
true

모듈(Modules) 및 함수(Functions)

Elixir에서 복수의 함수는 모듈(module)로 그룹지어진다. 예를 들어 String 은 모듈이다. Java와 같은 언어에서는 클래스의 개념으로 볼 수 있다. 이외에도 컴파일(compilation), 스크립트 모드(scripted mode), 함수 포착(functions capturing), 기본 인자(default arguments) 등등 도 모듈로 볼 수 있다.

iex> String.length("elixir")
6

마치며

결론적으로 Elixir는 동적(dynamic)이며 함수형(functional) 언어로써, 스케일링이 용이(scalable)하고 유지보수가 용이(maintainable)한 웹 어플리케이션 개발에 적합하다. Elixir는 배우기 쉽고 재미있는 것으로 알려져있고, 이미 관련 커뮤니티도 매우 활성화 되어 있다. 현재 전세계적으로 많은 Elixir 개발자들의 수요가 존재하며, 그만큼 일자리도 많아지고 있다. Elixir를 조금 더 잘 활용하기 위해서 이전에 언급한 재귀(recursion), 고차함수(higher order functions), 메타프로그래밍(metaprogramming)의 개념을 인지하는 것이 좋다.

참조:

(1) https://storage.caktusgroup.com/media/blog-images/elixir.png

(2) https://www.educative.io/blog/elixir-functional-programming

--

--

배우는 자(Learner Of Life)
배우는 자(Learner Of Life)

Written by 배우는 자(Learner Of Life)

배움은 죽을 때까지 끝이 없다. 어쩌면 그게 우리가 살아있다는 증거일지도 모른다. 배움을 멈추는 순간, 혹은 배움의 기회가 더 이상 존재하지 않는 순간, 우리의 삶은 어쩌면 거기서 끝나는 것은 아닐까? 나는 배운다 그러므로 나는 존재한다. 배울 수 있음에, 그래서 살아 있음에 감사한다.

No responses yet