Skip to content
Published on

모던 Erlang & BEAM 2026 — OTP 27 / OTP 28 preview / Cowboy 3 / Bandit / Khepri / Gleam / Nerves / AtomVM 심층 가이드

Authors

프롤로그 — 30년 된 가상머신이 왜 2026년에도 매력적인가

1986년. Ericsson의 한 통신 스위치 팀이 새로운 언어를 만든다. 이름은 Erlang. 목적은 단 하나 — 죽지 않는 시스템. 9개의 9, 즉 99.9999999%의 가용성을 가진 전화 교환기.

40년이 지난 2026년. Erlang은 더 이상 통신사만의 언어가 아니다. WhatsApp이 20억 명의 메시지를 BEAM 위에서 처리하고, Discord가 수억 명의 음성·텍스트를 Elixir로 라우팅하며, Klarna가 결제 트랜잭션을 Erlang으로 처리한다. RabbitMQ는 사실상 모든 마이크로서비스 백본에 깔려 있고, Akamai DNS는 Erlang으로 돌아간다.

BEAM은 멈추지 않았다. 2024년 5월 OTP 27이 나왔고, OTP 28이 preview를 거쳐 안정화로 향한다. Cowboy 3가 HTTP/2와 WebSocket을 다시 다듬었고, Bandit이 순수 Elixir로 Cowboy의 대안을 제시했다. RabbitMQ 팀은 Mnesia를 대체할 Khepri를 Raft 위에 올렸다. gleam은 정적 타입을 들고 BEAM 생태계에 합류했고, Nerves는 임베디드를, AtomVM은 ESP32 마이크로컨트롤러까지 침투했다.

이 글은 2026년 BEAM 생태계의 전체 지도다. OTP 27/28의 새 기능, HTTP 스택, 분산 데이터, 임베디드, 새 언어, 그리고 누가 실제로 쓰는지까지.

"Erlang은 우리에게 더 적은 사람으로 더 많은 일을 하게 해줬다." — Jan Koum, WhatsApp 공동창업자, 50명의 엔지니어로 9억 사용자를 운영하던 시절


1장 · 2026년 Erlang/BEAM 지도 — 왜 여전히 매력적인가

먼저 BEAM이 무엇인지, 왜 다른 가상머신과 본질적으로 다른지 정리한다.

BEAM의 4가지 핵심 자산

  1. 경량 프로세스(green process) — OS 스레드가 아니다. BEAM 내부의 가상 프로세스. 하나당 약 300바이트. 단일 노드에서 수백만 개를 띄울 수 있다.
  2. 선점형 스케줄러(preemptive scheduler) — Go의 협동형 스케줄러와 다르다. BEAM은 reduction(축약) 카운트로 강제 컨텍스트 스위치를 한다. 한 프로세스가 무한 루프를 돌아도 다른 프로세스가 굶지 않는다.
  3. share-nothing 메시지 전달 — 프로세스 간 메모리 공유 없음. 모든 통신은 메시지. 락이 없다. 데드락 카테고리 자체가 사라진다.
  4. OTP (Open Telecom Platform) — supervisor, gen_server, gen_statem 같은 행위 패턴(behavior). 30년간 검증된 분산·내결함성 라이브러리의 표준 모음.

BEAM이 빛나는 곳 vs 빛나지 않는 곳

빛나는 영역                          빛나지 않는 영역
────────────────────────             ────────────────────
대규모 동시 연결 (수백만)             ⛔ 숫자 계산 (CPU bound)
실시간 메시징/채팅                    ⛔ 단일 스레드 처리량
분산 시스템 / 클러스터링             ⛔ 머신러닝 학습
긴 시간 유지되는 연결 (LiveView)     ⛔ GUI 데스크탑 앱
내결함성 임계 시스템                  ⛔ 시스템 프로그래밍
프로토콜 게이트웨이 (MQTT, AMQP)      ⛔ 게임 엔진

핵심: CPU가 아니라 동시성(concurrency)이 병목인 곳. 그리고 죽으면 안 되는 곳.

2026년 BEAM 생태계 한 페이지

              ┌────────────────────────────────────────┐
              │             BEAM 가상머신               │
              │      (JIT, ETS, supervisor, OTP)       │
              └───────┬────────────────┬───────────────┘
                      │                │
        ┌─────────────┼───┐    ┌───────┼──────────┐
        │             │   │    │       │          │
     Erlang        Elixir gleam    Lustre     Phoenix
       │              │     │       (web)   (LiveView)
       │              │     │
       ▼              ▼     ▼
  ┌────────┐     ┌─────────┐  ┌─────────┐
  │Cowboy 3│     │ Bandit  │  │ AtomVM  │
  │  HTTP  │     │(Plug용) │  │ (ESP32) │
  └────────┘     └─────────┘  └─────────┘

  Storage:      Mnesia / Khepri (Raft) / ETS / DETS
  Distribution: distributed Erlang / partisan
  Embedded:     Nerves (Linux) / AtomVM (MCU)
  Foundation:   Erlang Ecosystem Foundation (EEF)

이 글의 나머지는 이 지도의 각 부분을 차례로 본다.


2장 · Erlang/OTP 27 (2024년 5월) — 문자열 보간과 persistent_term의 재발견

2024년 5월, Erlang/OTP 27이 정식 출시됐다. 2026년 현재 대부분의 프로덕션 시스템이 27로 이동 중이거나 이미 이동했다. 27이 가져온 가장 눈에 띄는 변화 3가지.

2-1. Triple-quoted string + string interpolation

Erlang은 30년 동안 문자열 보간이 없었다. 2026년에야 마침내 추가됐다. 그것도 두 가지 형태로.

%% Triple-quoted string (OTP 27)
Greeting = """
   Hello, World!
   Multi-line, no escaping needed.
   """,

%% Sigil 형식 (~b는 binary)
Name = <<"Alice">>,
Greeting2 = ~b"Hello, #{Name}!".
%% => <<"Hello, Alice!">>

~b sigil로 binary 문자열에, ~B sigil로 비보간 binary에 쓴다. Elixir의 ~s, ~S 시질과 비슷한 디자인이다.

현실: Erlang 사용자는 30년 동안 io_lib:format("Hello, ~p!", [Name])을 써왔다. 이제는 ~b"Hello, #{Name}!"이다. 코드가 훨씬 읽기 좋아졌다.

2-2. set_node_lookup_node / 노드 검색 개선

분산 Erlang 클러스터에서 노드 검색은 EPMD(Erlang Port Mapper Daemon)에 의존했다. OTP 27은 EPMD를 우회하고 직접 노드 이름을 등록할 수 있는 콜백 API를 정식화했다.

  • 컨테이너 환경(쿠버네티스)에서 EPMD가 거추장스러웠던 문제를 해결.
  • libcluster 같은 라이브러리가 이미 비슷한 일을 했지만, OTP 27에서 표준 인터페이스가 생긴 셈.

2-3. persistent_term 개선 — 더 빠른 읽기

persistent_term은 거의 변하지 않는 전역 상수를 빠르게 읽기 위한 ETS의 사촌이다. 쓰기는 매우 느리지만(전체 시스템 GC 트리거), 읽기는 거의 zero-cost.

OTP 27은 persistent_term의 내부 구현을 다듬어, 메모리 사용량과 쓰기 시 GC 비용을 줄였다. 설정값·키·라우팅 테이블 같은 "거의 영구" 데이터에 쓰기 좋아졌다.

%% 한 번 쓰고, 수억 번 읽기
persistent_term:put({config, max_connections}, 100000),

%% 핫 패스에서 거의 무료
Max = persistent_term:get({config, max_connections}).

2-4. JIT 개선과 컴파일러 다이아그노스틱

  • BEAMAsm JIT이 ARM64에서도 안정화 (Apple Silicon, AWS Graviton에서 직접적 성능 향상).
  • 컴파일러 경고가 더 정확해지고, 더 친절한 에러 메시지.
  • maps 모듈에 iterator/2, filtermap/2 등 추가.

OTP 27 마이그레이션 체크리스트

□ Rebar3 / Mix를 OTP 27 호환 버전으로 업데이트
□ Dialyzer 재실행 (타입 시스템 미세 변화)
□ EPMD 대체 콜백을 쓸 거면 net_kernel 설정 확인
□ Triple-quoted string은 IDE 지원 확인 (Erlang LS, ElixirLS)
□ 의존성 중 OTP 27 비호환 라이브러리 확인 (대부분 호환됨)

3장 · OTP 28 preview — 다음에 오는 것

2026년 5월 현재 OTP 28은 release candidate 단계. 정식 출시는 2026년 여름 예정. 주요 변화.

3-1. JIT의 추가 최적화

  • BEAMAsm이 register allocation 알고리즘을 다시 손봐, 핫 루프에서 10~15% 추가 성능.
  • 함수 호출 인라이닝 휴리스틱 개선.

3-2. set / map 표준 라이브러리 확장

%% OTP 28 preview에서 추가될 것으로 예상되는 maps 함수
maps:groups_from_list(fun(X) -> X rem 2 end, [1,2,3,4,5]).
%% => #{0 => [4,2], 1 => [5,3,1]}

%% set 모듈에도 비슷한 편의 함수

3-3. ssl 스택 현대화 — TLS 1.3 완성

  • TLS 1.3의 0-RTT 모드 완전 지원.
  • post-quantum 키 교환 알고리즘(Kyber/ML-KEM) 실험적 지원.

3-4. logger 와 telemetry 통합 강화

  • OpenTelemetry와의 호환성을 위한 인프라 확장.
  • 구조화된 로깅 메타데이터 표준화.

3-5. 분산 모니터링 개선

  • monitor/2, link/1의 분산 환경 에러 메시지 개선.
  • 노드 간 monitor 메시지 손실 시 복구 동작 명확화.

요약: OTP 28은 혁명이 아니다. **연마(polish)**다. 30년 된 시스템이 매년 어떻게 계속 더 좋아질 수 있는지를 보여주는 좋은 사례.


4장 · Cowboy 3 — BEAM의 표준 HTTP 서버

Cowboy는 Loïc Hoguin이 만든 작은 빠른 Erlang HTTP 서버다. Plug, Phoenix, RabbitMQ Management UI, 거의 모든 Erlang/Elixir 웹 스택의 기본 HTTP 서버.

2024년 말 Cowboy 3가 출시됐다. 핵심 변화.

4-1. HTTP/2 완전성

  • Cowboy 2도 HTTP/2를 지원했지만 일부 corner case에서 RFC 9113과 어긋났음.
  • Cowboy 3는 HTTP/2 명세를 다시 한번 통째로 훑고 fuzzing 테스트 케이스 추가.
  • 특히 GOAWAY 처리, flow control window 업데이트 race condition 수정.

4-2. WebSocket 안정화

  • WebSocket 압축(permessage-deflate) 옵션 정리.
  • 부분 메시지(framing) 처리에서 메모리 누수 가능성 패치.

4-3. HTTP/3 — 실험적 지원

  • QUIC 트랜스포트를 통한 HTTP/3가 experimental 단계로 들어왔다.
  • 프로덕션 권장은 아직 아니지만, 베타 도입을 시작한 팀들이 있다.

4-4. 간단한 Cowboy handler 예시

%% rebar.config에 cowboy 의존성 추가 후

-module(hello_handler).
-export([init/2]).

init(Req0, State) ->
    Req = cowboy_req:reply(200,
        #{<<"content-type">> => <<"text/plain">>},
        <<"Hello from Cowboy 3!">>,
        Req0),
    {ok, Req, State}.

%% 라우터에 등록
start() ->
    Dispatch = cowboy_router:compile([
        {'_', [{"/", hello_handler, []}]}
    ]),
    {ok, _} = cowboy:start_clear(my_http_listener,
        [{port, 8080}],
        #{env => #{dispatch => Dispatch}}).

Cowboy를 쓰는 대표 시스템

  • Phoenix (Elixir 웹 프레임워크) — 기본 어댑터 중 하나.
  • RabbitMQ Management Plugin.
  • Akamai의 일부 엣지 서비스.
  • WhatsApp 내부 도구.

5장 · Bandit — 순수 Elixir로 다시 쓴 HTTP 서버

Cowboy는 Erlang으로 작성됐다. Plug/Phoenix는 Elixir로 작성됐다. 이 둘을 잇는 어댑터(Plug.Cowboy)는 항상 존재했지만, 일부 사용자들은 "Elixir 스택 전체가 Elixir로 작성되면 어떨까?"를 원했다.

Bandit(2022년 시작, Mat Trudel 주도)이 그 답이다.

5-1. Bandit이 노린 것

Cowboy:   Erlang  →  Elixir 어댑터(Plug.Cowboy)  →  Plug/Phoenix
Bandit:   Elixir  →                              →  Plug/Phoenix
  • 순수 Elixir로 HTTP/1.1, HTTP/2, WebSocket 구현.
  • Plug 인터페이스와 직접 통합 (어댑터 레이어 불필요).
  • Cowboy 대비 일부 마이크로벤치마크에서 10~30% 빠름.

5-2. Phoenix와의 통합

Phoenix 1.7부터 Bandit을 Plug.Cowboy의 드롭인 대체로 쓸 수 있다.

# config/config.exs
config :my_app, MyAppWeb.Endpoint,
  adapter: Bandit.PhoenixAdapter,
  http: [port: 4000]

이 한 줄이면 끝. Phoenix LiveView, channels, controllers 모두 동작.

5-3. Bandit vs Cowboy — 2026년 비교

                      Cowboy 3            Bandit
호스트 언어           Erlang              Elixir
HTTP/1.1              ✅ 검증됨            ✅ 검증됨
HTTP/2                ✅ RFC 9113          ✅ RFC 9113
HTTP/3                실험적              아직 없음
WebSocket             ✅                   ✅
Plug 통합             어댑터 통해          네이티브
운영 검증             10년 이상            3~4년
프로덕션 추천         보수적이면 ✓        Phoenix 신규는 ✓

5-4. 어느 쪽을 골라야 하나

  • 기존 Erlang 시스템 → Cowboy 3.
  • 신규 Phoenix 프로젝트 → Bandit이 점점 디폴트로 자리잡는 중.
  • HTTP/3가 필요 → Cowboy 3 (현재).
  • 순수 Elixir 코드베이스를 원함 → Bandit.

6장 · Khepri — RabbitMQ 팀이 만든 Mnesia 후속

Mnesia는 1990년대 Erlang의 분산 DBMS다. 메모리·디스크 하이브리드, 트랜잭션, ETS 호환 인터페이스. 그러나 netsplit(네트워크 분할) 동작이 잘 알려진 약점이었다 — 분할이 일어나면 양쪽이 살아남아 데이터가 갈라지고, 다시 합치려면 수동 개입이 필요했다.

RabbitMQ 팀(Pivotal/VMware/Broadcom 산하)이 이 문제를 정면으로 풀려고 만든 게 Khepri다.

6-1. Khepri의 핵심 아이디어

"Mnesia를 대체하되, Raft 합의를 깔자."

  • 트리 형태의 키-값 저장소(Zookeeper / etcd와 비슷한 데이터 모델).
  • 모든 쓰기는 Raft 합의를 거친다 → 과반수가 살아 있어야 쓰기 가능.
  • netsplit 상황에서 양쪽이 자기가 진실이라고 우기는 일이 사라진다(소수 쪽이 쓰기 불가).
  • Erlang/OTP로 작성, 외부 의존성 없음.

6-2. Khepri의 데이터 모델

%% 경로 기반 트리 구조
ok = khepri:put([app, config, max_users], 1000),
{ok, 1000} = khepri:get([app, config, max_users]),

%% 와일드카드 쿼리
{ok, Map} = khepri:get_many([app, config, ?KHEPRI_WILDCARD_STAR]).

Zookeeper의 znode, etcd의 키 트리와 매우 유사한 디자인.

6-3. RabbitMQ에서의 채택

  • RabbitMQ 4.0 (2024년 9월)부터 Khepri가 메타데이터 저장소로 선택 가능.
  • 4.x 후반에는 기본값이 될 예정.
  • 대체 대상은 RabbitMQ 내부의 Mnesia(큐 정의, 사용자, vhost 같은 메타데이터).
  • 메시지 본체는 별도의 큐 엔진(quorum queue 등)이 처리하므로, Khepri는 "제어 평면(control plane)"에 집중.

6-4. Khepri를 자기 시스템에 쓰려면

%% rebar.config에 khepri 추가
{deps, [
    {khepri, "0.14.0"}
]}.

%% 시작
{ok, _} = khepri:start(),

%% 트랜잭션
khepri:transaction(fun() ->
    khepri_tx:put([users, alice], #{role => admin}),
    khepri_tx:put([users, bob], #{role => user})
end).

결론: Khepri는 Mnesia를 "조용히" 대체하고 있다. 신규 분산 BEAM 시스템에서 메타데이터 저장소를 고를 때는 Khepri가 점점 더 합리적인 선택이 되고 있다.


7장 · Mnesia / partisan — 분산 데이터와 분산 통신

7-1. Mnesia — 여전히 살아 있다

Khepri가 등장했다고 Mnesia가 사라진 건 아니다. 2026년에도:

  • 트랜잭션이 필요한 곳, 표 형태 데이터, ETS와 똑같은 인터페이스가 필요한 곳에서 여전히 쓰인다.
  • ejabberd(XMPP 서버), 일부 게임 서버, 통신 장비 안에 여전히 Mnesia가 살아 있다.
  • 약점은 변하지 않았다: netsplit 대응이 약하고, 큰 데이터셋에서 운영 부담이 있다.

원칙:

  • 데이터 양이 작고 노드 수가 적으면 → Mnesia 여전히 OK.
  • netsplit 일관성이 중요하면 → Khepri 또는 외부 DB.
  • 단순 캐시면 → ETS 만으로 충분.

7-2. partisan — 분산 Erlang 자체에 대한 도전

기본 분산 Erlang(net_kernel)은 풀 메시(full mesh) 토폴로지를 가정한다. 모든 노드가 모든 노드와 직접 연결. 노드 수가 100을 넘기 시작하면 메시지 폭주와 head-of-line blocking 문제가 생긴다.

partisan(Christopher Meiklejohn 외)이 이걸 다시 설계했다.

distributed Erlang:  N개 노드 → N*(N-1)/2 연결 (풀 메시)
partisan:            여러 토폴로지 옵션
                     - full mesh
                     - hyparview (peer-to-peer overlay)
                     - client-server
                     - PG2 기반 정적 그룹

핵심 아이디어:

  1. 다중 채널(multi-channel) — 한 노드 쌍 사이에 여러 TCP 연결. 작은 메시지가 큰 메시지에 막히지 않는다.
  2. 모놀리식 vs P2P — 토폴로지를 선택 가능.
  3. 백워드 호환gen_server 인터페이스를 그대로 쓰면서 내부만 교체.

2026년 현재 partisan은:

  • 학술 연구에서 시작해서 일부 프로덕션(특히 IoT 백엔드, 게임 서버)에서 채택.
  • 메인스트림은 아직 distributed Erlang이지만, 대규모 클러스터에서는 partisan을 고려하는 팀이 늘고 있다.

8장 · Nerves — 임베디드 Erlang/Elixir

Nerves는 Frank Hunleth 주도의 임베디드 프레임워크다. 핵심 아이디어:

"Linux 위에서 BEAM만 돌리자. 사용자 영역 전체가 Elixir/Erlang."

8-1. Nerves가 노린 것

  • Raspberry Pi, BeagleBone, Industrial single-board computers.
  • 기존 임베디드 Linux 배포판(buildroot, yocto)의 복잡성을 줄이고, 재현 가능한 펌웨어 빌드.
  • A/B 파티션을 통한 안전한 OTA 업데이트.
  • BEAM의 supervisor 모델을 펌웨어 전체에 적용.

8-2. 전형적인 Nerves 프로젝트 구조

# 새 Nerves 프로젝트 생성 (Raspberry Pi 4 타겟)
mix nerves.new my_iot_device --target rpi4

cd my_iot_device

# 펌웨어 빌드
MIX_TARGET=rpi4 mix deps.get
MIX_TARGET=rpi4 mix firmware

# SD 카드에 굽기
MIX_TARGET=rpi4 mix firmware.burn

펌웨어 안에는 부트로더, 리눅스 커널, BEAM, 그리고 Elixir 애플리케이션이 들어있다. 사용자 영역에는 거의 다른 게 없다.

8-3. 실제 사용 사례

  • FarmBot — 오픈소스 농업 로봇.
  • GRiSP — 산업용 임베디드 보드, Erlang을 베어메탈(또는 RTOS 위) 직접 구동.
  • 물류·창고 자동화 장비 — 일부 회사들이 Nerves 기반 PLC 대체 솔루션.
  • 음향 장비, 디지털 사이니지.

8-4. NervesHub — OTA 관리

Nerves 팀이 만든 NervesHub는 펌웨어 업데이트의 중앙 관리 시스템. 디바이스 함대 전체에 점진적 롤아웃을 할 수 있다.

포인트: Nerves는 "임베디드도 BEAM의 supervisor 안에서 돌아가면 안 죽는다"는 가설을 실증하는 프로젝트.


9장 · gleam — 정적 타입 BEAM 언어

gleam(Louis Pilfold 창시, 2016년 시작)은 BEAM 위에서 도는 정적 타입 함수형 언어다. 2024년 시드 투자를 받고 1.0이 출시되면서 본격적으로 주목받기 시작했다.

9-1. gleam이 제시하는 것

import gleam/io
import gleam/list

pub fn main() {
  let numbers = [1, 2, 3, 4, 5]
  let doubled = list.map(numbers, fn(n) { n * 2 })
  io.debug(doubled)
}
  • 타입 추론 — 변수 선언에 타입을 거의 쓰지 않아도 컴파일 타임에 모든 타입이 결정된다.
  • 표현식 기반 — Erlang/Elixir과 비슷한 함수형 스타일.
  • BEAM과 JavaScript 두 타겟으로 컴파일. (네! gleam은 JS도 만든다.)
  • Erlang FFI — 기존 Erlang/OTP 라이브러리를 그대로 호출 가능.

9-2. 왜 정적 타입을 BEAM에 가져왔나

  • Elixir, Erlang은 동적 타입. dialyzer(success typing)가 있지만 한계가 있다.
  • gleam은 처음부터 강력한 정적 타입(Hindley-Milner 계열)으로 설계.
  • 결과: 컴파일이 통과하면 대부분의 실수가 잡힌다 — Rust나 Haskell처럼.

9-3. 간단한 OTP 스타일 액터 (gleam_otp)

import gleam/erlang/process
import gleam/otp/actor

pub fn main() {
  let assert Ok(subject) = actor.start(0, handle_message)
  process.send(subject, Increment)
  process.send(subject, Increment)
  // 두 번 증가
}

pub type Message {
  Increment
  GetCount(reply_to: process.Subject(Int))
}

fn handle_message(message: Message, count: Int) -> actor.Next(Message, Int) {
  case message {
    Increment -> actor.continue(count + 1)
    GetCount(reply_to) -> {
      process.send(reply_to, count)
      actor.continue(count)
    }
  }
}

타입이 있는 OTP. 보내는 메시지의 종류가 컴파일 타임에 확인된다.

9-4. gleam 1.0 이후의 흐름

  • 에코시스템 빠르게 성장 — hex.pm에 gleam 패키지 수 빠르게 증가.
  • 2024년 시드 투자 — Pilfold가 풀타임으로 gleam 개발에 전념.
  • JavaScript 타겟 — gleam 코드 일부를 프론트엔드에 쓸 수도 있다.
  • 커뮤니티 분위기 — Elixir 커뮤니티에서 친화적으로 수용되는 분위기.

9-5. gleam을 골라야 할 때

  • 정적 타입에서 오는 안정감을 원할 때.
  • BEAM의 동시성/내결함성을 원하면서 타입 안전성도 원할 때.
  • 새 프로젝트로 시작할 수 있을 때(기존 Elixir 코드베이스를 마이그레이션하는 건 다른 이야기).

10장 · Lustre — gleam의 웹 프레임워크

Lustre는 Hayleigh Thompson이 만든 gleam의 프론트엔드 프레임워크다. Elm에서 영감을 받은 The Elm Architecture(TEA) 패턴.

10-1. Lustre의 모델

        ┌─────────┐     Msg     ┌─────────┐
        │  View   │────────────▶│ Update  │
        │ (HTML)  │             │ (모델   │
        └─────────┘◀──────│     │  변경)  │
            ▲       Model       └─────────┘
            └──── 사용자 인터랙션 ────┐
                              (브라우저)

10-2. 간단한 카운터 (Lustre)

import lustre
import lustre/element/html.{button, div, text}
import lustre/event

pub fn main() {
  let app = lustre.simple(init, update, view)
  let assert Ok(_) = lustre.start(app, "#app", Nil)
}

fn init(_) {
  0
}

pub type Msg {
  Incr
  Decr
}

fn update(model: Int, msg: Msg) -> Int {
  case msg {
    Incr -> model + 1
    Decr -> model - 1
  }
}

fn view(model: Int) {
  div([], [
    button([event.on_click(Decr)], [text("-")]),
    text(int.to_string(model)),
    button([event.on_click(Incr)], [text("+")]),
  ])
}

10-3. Lustre의 두 가지 모드

  1. 클라이언트 사이드 — gleam을 JavaScript로 컴파일하여 브라우저에서 직접 실행.
  2. 서버 컴포넌트 — Phoenix LiveView 스타일로 서버에서 상태를 보유하고, 브라우저는 얇은 클라이언트.

서버 컴포넌트 모드는 LiveView와 비슷하지만, gleam의 타입 안전성을 가져온다는 점이 차별점이다.

10-4. 2026년의 위치

  • Lustre는 아직 메인스트림은 아니다.
  • 작은 프로젝트, 사이드 프로젝트, gleam 풀스택을 원하는 팀들이 채택 중.
  • LiveView 대안으로서의 가능성을 탐색하는 단계.

11장 · AtomVM — ESP32에서 Erlang 돌리기

AtomVM(Davide Bettio 외)은 BEAM 바이트코드를 마이크로컨트롤러에서 실행하는 가상머신이다.

11-1. AtomVM이 노린 곳

  • ESP32 (와이파이/블루투스 내장 MCU, 매우 저렴)
  • STM32
  • Raspberry Pi Pico (RP2040)

이 보드들은 Linux를 돌리기에 너무 작다(보통 수백 KB ~ 수 MB RAM). Nerves는 못 가지만, AtomVM은 갈 수 있다.

11-2. 어떻게 동작하나

  • BEAM 표준 바이트코드(.beam 파일)를 그대로 읽고, 마이크로컨트롤러에서 해석/실행.
  • 표준 라이브러리의 소수만 지원 (메모리 제약).
  • supervisor, gen_server 같은 OTP 패턴은 사용 가능.

11-3. ESP32에서 "Hello, Erlang" 같은 시작

-module(blink).
-export([start/0]).

start() ->
    Pin = 2,
    gpio:set_pin_mode(Pin, output),
    loop(Pin, high).

loop(Pin, State) ->
    gpio:digital_write(Pin, State),
    timer:sleep(500),
    NextState = case State of
        high -> low;
        low -> high
    end,
    loop(Pin, NextState).
# 컴파일 후 ESP32에 굽기 (개략)
erlc blink.erl
atomvm_packbeam blink.avm blink.beam
esptool.py write_flash 0x250000 blink.avm

LED 깜빡임 같은 입문 예제부터 시작해서, BLE 기반 IoT 장치, 작은 메시지 게이트웨이까지 만들 수 있다.

11-4. AtomVM vs Nerves

            AtomVM                    Nerves
타겟        MCU (ESP32, STM32)        SBC (Pi, BeagleBone)
RAM         수백 KB                    수 GB 가능
OS          없음 (bare metal/FreeRTOS) Linux
BEAM        AtomVM (subset)            정식 OTP
유스케이스   센서 노드, BLE 장치        엣지 게이트웨이

가장 작은 노드는 AtomVM, 그것이 모이는 허브는 Nerves, 클라우드 백엔드는 정식 OTP — 이런 그림이 가능하다.

11-5. 2026년 현재

  • AtomVM 0.6 시리즈가 안정화 단계.
  • Erlang/Elixir 모두 지원(둘 다 .beam으로 컴파일되니까).
  • 커뮤니티가 활발하지만 작다. IoT/엣지에 관심 있는 BEAM 사용자들이 모이는 곳.

12장 · RabbitMQ — Erlang으로 짜여진 메시지 브로커의 대명사

RabbitMQ는 별도의 글로 다룬 적이 있으므로 여기서는 간단히. 핵심은 이 회사가 Erlang을 메인스트림으로 끌고 온 가장 큰 한 축이라는 점.

12-1. RabbitMQ가 Erlang을 고른 이유

  • AMQP 메시지 브로커는 본질적으로 동시 연결을 수만~수십만 단위로 다뤄야 한다.
  • 죽으면 안 된다 — supervisor 트리.
  • 분산 클러스터링이 처음부터 필요했다.
  • Erlang이 정확히 그 일을 위해 만들어진 언어였다.

12-2. 2026년의 RabbitMQ

  • 버전 4.x.
  • Quorum Queue가 기본. Raft 합의 기반의 큐 (옛 클래식 미러 큐 대체).
  • Khepri가 메타데이터 저장소로 이동 중.
  • MQTT 5.0, Streams(Kafka 풍 추가) 지원.

12-3. Erlang 생태계에 끼친 영향

  • Erlang을 단순히 "통신사 언어"에서 메인스트림 인프라 컴포넌트로 끌어올린 1등 공신.
  • 많은 회사가 RabbitMQ를 통해 "어? Erlang 시스템 잘 안 죽네?"를 처음 경험.

13장 · 실제 사용 — WhatsApp / Klarna / Discord / Riot / Cisco / Akamai

BEAM을 진지하게 쓰는 회사들의 짧은 케이스 스터디.

13-1. WhatsApp — Erlang 스케일의 전설

  • 2009년 창업. Jan Koum이 ejabberd(XMPP 서버, Erlang) 출신이라 처음부터 Erlang.
  • 한 서버에서 200만 동시 연결을 처음 보여준 시스템.
  • 2014년 Facebook 인수 당시 9억 사용자를 50명 엔지니어로 운영.
  • 인수 후에도 코어는 여전히 Erlang/FreeBSD 기반.
  • "적은 사람으로 거대한 동시성" — BEAM의 마케팅 카피가 됐다.

13-2. Klarna — Erlang at 핀테크

  • 스웨덴 BNPL(buy now, pay later) 핀테크.
  • 2005년부터 Erlang 사용. 결제 트랜잭션 처리, 위험 평가 일부.
  • 모놀리식 Erlang 시스템에서 점진적 마이크로서비스화. 그러나 Erlang은 여전히 코어.
  • Erlang의 hot code swap 기능을 무중단 배포에 적극 사용.

13-3. Discord — Erlang/Elixir 하이브리드

  • 보이스/텍스트 게이트웨이는 Elixir(BEAM).
  • 한 채널에 수백만 사용자가 동시에 메시지를 받는 시나리오를 BEAM의 프로세스 모델로 처리.
  • 일부 코어 데이터 평면은 Rust로 다시 작성(Erlang/Elixir로 안 되는 부분은 솔직하게 다른 언어).
  • 그러나 세션·라우팅·실시간 통신은 Elixir가 담당.

13-4. Riot Games — Erlang으로 만든 채팅

  • "League of Legends" 인게임 채팅이 Erlang(ejabberd 변형) 기반.
  • 수천만 동시 사용자 채팅을 안정적으로 처리.

13-5. Cisco — XMPP/통신 인프라

  • 일부 통신 장비, IP 전화, 협업 도구 백엔드에 Erlang.
  • Cisco Webex의 일부 컴포넌트도 Erlang을 사용한 것으로 알려짐.

13-6. Akamai — DNS의 일부

  • CDN 거인 Akamai가 일부 DNS 인프라에 Erlang 기반 서비스 운용.
  • 초당 수십만 쿼리 처리에서 BEAM의 동시성 이점.

케이스 스터디의 공통점

  • 죽으면 안 되는 시스템.
  • 수만~수백만 동시 연결.
  • 메시징/실시간 프로토콜.
  • 분산 클러스터링.

CPU bound가 아닌, 동시성 bound 작업이 본질인 회사들.


14장 · 한국 / 일본 — 동아시아의 BEAM

서구권에서 BEAM은 잘 알려져 있지만, 동아시아에서의 채택은 어떻게 보일까.

14-1. 한국 — 카카오, 통신사, 일부 스타트업

  • 카카오의 일부 메시징·노티피케이션 인프라가 Erlang/Elixir 사용한 시기가 있었다. 대규모 알림 fanout에서 BEAM 모델이 적합.
  • 당근(Carrot) — 채팅·푸시 일부에서 Elixir Phoenix 활용한 사례 (사내 컨퍼런스 토크 등에서 언급).
  • 통신사 — KT, SK텔레콤 일부 통신 인프라에서 Erlang 기반 미들웨어 사용 사례. ejabberd 기반의 메시징 시스템도.
  • 스타트업·게임사 — 일부 모바일 게임 백엔드(매치메이킹, 채팅 서버)에서 Elixir 채택.

현실: 한국에서 BEAM은 메인스트림은 아니다. 그러나 메시징/실시간이 본질인 회사에서는 조용히 쓰이고 있다.

14-2. 일본 — ピクシブ(Pixiv), NTT, 통신 인프라

  • ピクシブ(Pixiv) — 일부 메시징·통지 시스템에서 Elixir/Erlang 사용한 시기. 컨퍼런스 발표 사례 있음.
  • NTT — 통신 인프라의 백본 일부에 Erlang 기반 미들웨어. 통신 장비 제조사 NEC, 후지쯔도 마찬가지로 일부 영역.
  • DMM — 일부 마이크로서비스에 Elixir 시도.
  • Drecom 등 게임사 — 일부 실시간 백엔드.

14-3. 동아시아에서 BEAM 채용이 더디게 보이는 이유

  • 레퍼런스 인력 풀이 작다 — 자바·고·러스트 대비 채용 시장이 좁다.
  • 교육 시스템에서 함수형 언어 노출이 적다.
  • 한국·일본의 기업 문화가 보수적 — 검증된 스택 선호. (역설적으로 BEAM은 매우 검증됐지만, 동아시아 시장 인식은 그렇지 않다.)
  • 그러나 메시징/실시간/IoT 회사에서는 도입 사례가 꾸준히 늘고 있다.

15장 · 누가 BEAM을 골라야 하나 — 의사결정 가이드

마지막으로, 2026년 시점에서 "이 프로젝트에 BEAM이 맞을까?"를 결정하는 실용 가이드.

15-1. BEAM이 강한 영역

실시간 메시징·채팅 — Discord, WhatsApp, Slack 백엔드 일부. ✅ 메시지 브로커 — RabbitMQ가 증명. ✅ 장기 유지 연결 — WebSocket, MQTT, SSE 다수 동시 연결. ✅ 분산 시스템 — 클러스터링이 처음부터 내장. ✅ 내결함성 임계 시스템 — supervisor 트리, "let it crash" 철학. ✅ 프로토콜 게이트웨이 — XMPP, AMQP, MQTT, 통신사 시그널링. ✅ IoT 백엔드 — 수만 디바이스 동시 연결.

15-2. BEAM이 약한 영역

숫자 계산 / 머신러닝 학습 — CPU bound 워크로드에는 NIF로 우회해야 한다. ❌ 단일 스레드 처리량 — Go, Rust, C++가 더 빠르다. ❌ 시스템 프로그래밍 — 커널, 드라이버, 게임 엔진. ❌ GUI 데스크탑 앱. ❌ 빠른 시장 진입 — 인력 채용이 어렵다.

15-3. 언어 선택 — Erlang vs Elixir vs gleam

              Erlang              Elixir              gleam
타입          동적                동적(dialyzer)      정적
문법          Prolog 풍           Ruby 풍             Rust/Elm 풍
생태계        오래됨, 안정         가장 활발            빠르게 성장
도구          rebar3              mix (훌륭)          gleam (간결)
주된 사용처   기존 시스템·OTP     신규 웹·Phoenix     신규 타입 안전
학습 곡선     문법 때문에 가파름   부드러움             함수형 친숙 시 빠름

권장:

  • 신규 BEAM 프로젝트 → 대부분의 경우 Elixir.
  • 타입 안전성이 중요 → gleam.
  • 기존 Erlang 시스템 유지·확장 → Erlang.
  • 둘을 섞어도 된다 — 같은 BEAM 위에서 상호 호출 가능.

15-4. HTTP 서버 선택

  • 신규 Phoenix → Bandit.
  • 기존 Erlang/Cowboy 스택 → Cowboy 3 유지.
  • HTTP/3 필요 → Cowboy 3.

15-5. 분산 데이터 선택

  • 작은 메타데이터, 강한 일관성 필요 → Khepri.
  • 트랜잭션이 많은 표 데이터, 작은 클러스터 → Mnesia.
  • 캐시·읽기 중심 → ETS (단일 노드) 또는 외부 KV(Redis, FoundationDB).
  • 본격 OLTP/OLAP → 외부 DB (PostgreSQL, ClickHouse 등).

15-6. 임베디드 선택

  • SBC(Pi, BeagleBone) → Nerves.
  • MCU(ESP32, STM32) → AtomVM.

16장 · 마치며 — BEAM은 사라지지 않는다

40년 동안 BEAM은 통신사의 비밀 무기에서 시작해, 인터넷 메시징 인프라의 척추가 됐다. 2026년의 BEAM은:

  • OTP 27 / 28로 여전히 다듬어지고 있고,
  • Cowboy 3 / Bandit으로 HTTP 스택이 현대화됐고,
  • Khepri로 분산 데이터의 약점을 메우고 있고,
  • gleam으로 타입 안전 옵션을 얻었으며,
  • Nerves / AtomVM으로 임베디드 영역까지 확장했다.

BEAM의 약속은 변하지 않았다 — "죽지 않는 시스템". 30년 전 통신 교환기에 필요했던 것이, 2026년의 LLM 추론 게이트웨이, 메시지 큐, IoT 백엔드, 실시간 협업 도구에도 그대로 필요하다.

만약 당신의 시스템이 "동시에 수많은 연결을 유지하고, 절대 죽으면 안 되는" 종류라면, BEAM을 진지하게 고려할 가치가 있다. 그게 메시징이든, 결제든, IoT든, 채팅이든.

BEAM은 30년 후에도, 아마 50년 후에도, 여전히 누군가의 백엔드에서 조용히 돌아가고 있을 것이다.


참고 / References