현재 회사에서 Elixir/Phoenix 기반으로 프로젝트를 진행하고 있어서, 생태계에 대해 공부하면서 정리해보고자 이렇게 글을 작성해봅니다.
Erlang은 Ericsson이라는 회사에서 전화 및 통신 어플리케이션을 위해 개발한 언어로서 핀테크, 보안, 블록체인 및 IoT등을 포함해 다양한 분야에서 사용되고 있습니다.
Erlang은 BEAM이라고 하는 VM 위에서 실행된다. 동시성 및 분산 시스템에 특화되어 있는 함수형 프로그래밍 언어이다.
Elixir는 José Valim이 개발한 고성능 분산 Erlang VM에서 돌아가는 함수형 프로그래밍 언어이다.
VM에서 자원을 할당받아 실행되기에 초경량 프로세스의 형태이다.
해외
국내
Erlang을 기반으로 Ruby on Rails의 장점을 포함해서 만들어진 언어로, Erlang의 장점 중 하나인 실시간 업그레이드 또한 지원한다. 실제로 백엔드 개발을 하고 있다 보면, 오류를 발견해 수정을 진행하게 된다. Java/Spring Boot 기반으로 개발할 때는, application을 중지 시키고 다시 실행시켜야 하지만, Elixir/Phoenix 기반에서는 코드를 변경하고 저장하기만 하면 관련 변경사항이 실시간으로 반영된다.
개인적으로 느끼고 있는 Elixir의 가장 큰 장점이다. 여러 개의 함수를 연결해서 사용하여야 할 때, 복잡해지지 않는 다는 큰 장점이 있다. ‘|>’를 통해 파이프 연산을 진행할 수 있는데, 엘릭서 스쿨의 예시를 가져와서 사용해보고자 한다. 아래와 같이, 파이프 연산자를 사용하게 되면, 좌측의 결과값을 우측의 첫 번째 매개변수로 활용하게 된다.
# 파이프 연산자 사용 전
foo(bar(baz(new_function(other_function()))))
# 파이프 연산자 사용 후
other_function() |> new_function() |> baz() |> bar() |> foo()
위와 같은 구조는 Map에 데이터를 삽입하거나 여러 비즈니스 로직이 연결되어있을 때, 가독성 좋게 코드를 작성하는데 많은 도움이 되고 있다.
패턴매칭은 장점 리스트 중 하나로 표현했지만, Elixir가 아직 익숙하지 않은 나에게는 장점이 아닌 특징 정도이다.
패턴매칭에 대해 예시 하나를 들어보자면, “Java, C++에서의 ‘=’과 Elixir에서의 ‘=’은 다르다.“라는 것이다. 이 문장을 더 설명해보자면, Java, C++에서 ‘=’은 우변의 값을 좌변에 대입하는 것을 의미한다. Elixir에서 ‘=’는 매치 연산자로서, 전체 표현식이 방정식이 되고 왼쪽의 값과 오른쪽의 값을 매치시키는 과정이 발생한다. 매치하는 과정이 성공한다면 방정식의 값을, 그렇지 않을 경우에는 에러를 발생시키게 된다.
x = 1 # x와 1을 매치 시킴.
1 = x # result: 1, x가 1이 되었기에, 성공되어 방정식의 값인 1을 반환
2 = x # result: (MatchError) no match of right hand side value: 1
Ecto 패키지의 Schema에서 지원하는 메서드로, 웹 서비스를 개발한다는 입장에서 좋은 기능이다.
inserted_at, updated_at이라는 칼럼을 서버에서 알아서 생성 및 관리하도록 하는 메서드로, Java로 개발할 때 추상 클래스로 만들어 상속받는 설정을 해야했던 불편함이 사라져서 좋아하는 메서드이다. 평상시 created_at, modified_at으로 명명지어 활용했던 부분이 약간 어색할 뿐이다.
백엔드 개발을 주로 하던 나에게는 어려운 내용이다. 그래서, LiveView를 사옹해보신 한 개발자 분의 블로그 글을 첨부한다.
현재 LiveView를 사용해서 개발한 결과, 불편한 점이 굉장히 많다. 파일 업로드 과정에서 띄어쓰기가 존재하는 파일이 정상적으로 가져와지지 않는 오류를 발견하기도 했으며, multipart/form-data형식의 API Request를 보내는 과정도 굉장히 복잡하다.
파일 업로드와 데이터 입력을 한 페이지 내에서 받고자 할 때, 제대로 파악하지 못한 상태에서 개발을 한 것일 수 있지만 텍스트를 입력 후 파일을 선택하면 입력한 텍스트가 사라지는 상황이 연출되고 있다.
엘릭서 문법에서 어색한 부분으로, if-else로 조건이 두 개로만 나누어지는 경우는 가능하지만, 조건이 세 개로만 나누어서 if-else if-else로 나누어보려고 하니 해당 방식은 지원하지 않으며, case문 또는 condition문을 활용하는 방식으로 제공되고 있다.
현재 사용하다 보니 case문과 condition문이 가독성 측면에서 많은 장점을 가지고 있다고 느끼는 편이다.
위 두 키워드는 문법적으로 체화하지 못해, 현재 컴파일 시점에서 오류로 발견되거나 테스트 과정 중 오류가 발견되면 수정하고 있는 문법적인 부분들이다.
어색함을 떨쳐내기가 아직도 어렵다.
트랜잭션의 커밋과 롤백을 핸들링하는 방법에 대해서 약간 어색한 거 같다. Spring Boot의 경우, 어노테이션을 이용하여 상대적으로 수월하게 관리를 할 수 있었지만, 찾아보니 Elixir에서는 트랜잭션 관리하는 방법이 Spring Boot에 비해 불편하게 느껴졌다.
엘릭서의 대표적인 웹 프레임워크로서, Ruby on Rails에서 착안되었기에 MVC 아키텍처에 기반하여 만들어졌다. 바로 다음에 나오는 기본 설치 및 환경 설정을 통해 phoenix 프로젝트를 생성하여 서버를 실행할 수 있다.
phoenix와 관련한 정보를 찾고, 개발하는 과정에서 많이 참고하고 있는 사이트는 아래와 같다.
brew install elixir
mix phx.new {PROJECT_NAME}
만약 생성되지 않고, The task “phx.new” could not be found 의 오류가 떴다면, 아래의 커맨드를 실행
mix archive.install hex phx_new
Elixir는 기본적으로 PostgreSQL에 최적화되어 있기에, Docker Image를 이용해서 Container로 띄워서 구동시켰다.
mix ecto.create
mix phx.server
레퍼런스
2024-03-22: 사용 후기 추가