┌─────────────────────────────────┐
│ BEAM VM (Erlang VM) │
├─────────────────────────────────┤
│ 수백만 경량 프로세스 동시 실행 │
│ 프로세스 간 메모리 격리 │
│ 프로세스 크래시 → 다른 프로세스 무영향 │
│ 핫 코드 스와핑 (무중단 배포) │
│ 분산 노드 간 투명한 통신 │
└─────────────────────────────────┘
경량 프로세스: OS 스레드가 아닌 BEAM 프로세스 (각 ~2KB, 수백만 개 생성 가능)
“Let it crash”: 프로세스 크래시를 허용하고 Supervisor가 자동 재시작
선점형 스케줄링: 하나의 프로세스가 CPU 독점 불가 → 안정적 응답 시간
핫 코드 스와핑: 서버 재시작 없이 코드 업데이트
Erlang과의 관계
항목
Erlang
Elixir
출시
1986년 (Ericsson)
2012년
문법
Prolog 영향, 독특함
Ruby 영향, 친숙함
메타프로그래밍
제한적
강력한 매크로
도구
rebar3
Mix (빌드/의존성/태스크)
패키지
hex.pm 공유
hex.pm 공유
상호운용
-
Erlang 함수 직접 호출 가능
커뮤니티
통신/인프라
웹/스타트업
→ Elixir = Erlang의 모든 장점 + 현대적 문법/도구
핵심 문법
# 패턴 매칭{:ok, result} = {:ok, 42}# 파이프 연산자"hello world"|> String.upcase()|> String.split(" ")# => ["HELLO", "WORLD"]# 모듈과 함수defmodule Math do def factorial(0), do: 1 def factorial(n) when n > 0 do n * factorial(n - 1) endend# 동시성 — 프로세스 생성pid = spawn(fn -> receive do {:hello, name} -> IO.puts("Hello #{name}") endend)send(pid, {:hello, "World"})# GenServer (OTP 패턴)defmodule Counter do use GenServer def init(initial), do: {:ok, initial} def handle_call(:get, _from, count), do: {:reply, count, count} def handle_cast(:increment, count), do: {:noreply, count + 1}end
defmodule MyAppWeb.CounterLive do use Phoenix.LiveView def mount(_params, _session, socket) do {:ok, assign(socket, count: 0)} end def handle_event("increment", _, socket) do {:noreply, update(socket, :count, &(&1 + 1))} end def render(assigns) do ~H""" <h1><%= @count %></h1> <button phx-click="increment">+1</button> """ endend
Ecto
항목
내용
역할
데이터베이스 라이브러리 (ORM 대안)
특징
Changeset (검증), 마이그레이션, 쿼리 DSL
지원 DB
PostgreSQL, MySQL, SQLite
# 스키마defmodule User do use Ecto.Schema schema "users" do field :name, :string field :email, :string timestamps() endend# 쿼리from(u in User, where: u.age > 18, select: u.name)|> Repo.all()
# Supervisor 트리defmodule MyApp.Application do use Application def start(_type, _args) do children = [ MyApp.Repo, # DB 연결 풀 MyAppWeb.Endpoint, # 웹 서버 {MyApp.Cache, []}, # 캐시 프로세스 {Oban, oban_config()} # Job 큐 ] Supervisor.start_link(children, strategy: :one_for_one) endend