Advent of Code를 위해 Gleam을 사용해 본 후기
(blog.tymscar.com)- Advent of Code 2025의 12일간 퍼즐을 Gleam으로 해결하며, 언어의 Rust 수준 오류 메시지와 파이프라인 중심 함수형 스타일이 특히 인상적이었음
-
echo,fold_until,list.transpose등 내장 함수들이 디버깅과 조합 문제 해결을 단순화하며, 옵션 타입 기반 안전성이 그리드 퍼즐 처리에 유용하게 작동함 - 표준 라이브러리에 파일 IO와 정규식 기능이 포함되지 않은 점, 리스트 패턴 매칭 제약, 명시적 비교 구문 등은 반복 사용 시 불편 요소로 지적됨
- Erlang VM과 JavaScript 타깃 간 정수 처리 차이로 인해
bigi사용이 필요했으며, 일부 퍼즐에서는 외부 도구(glpsol) 호출로 문제를 해결함 - 전반적으로 함수형 사고 전환이 퍼즐 풀이를 명확하게 만들었으며, Gleam을 실제 프로젝트(예: 웹서버 개발)에 적용해 보고 싶다는 기대를 표현함
Advent of Code 2025과 Gleam 선택
- 매년 Advent of Code를 완주해 온 작성자는 올해 Gleam 언어를 선택해 12일간의 퍼즐을 해결함
- 올해 행사는 25일 대신 12일로 축소되었으며, 각 문제의 난이도는 높았지만 학습에는 적합한 구조였음
- 퍼즐 진행 속도가 빠르고 도구 세트가 완성되기 전에 복잡한 문제를 만나, 새 언어 학습에 이상적인 환경이 되었음
Gleam의 언어적 장점
- 간결한 문법, 유용한 컴파일러 오류 메시지, Rust 수준의 친절한 피드백이 특징
- 파이프 연산자 중심의 함수형 스타일이 AoC 문제 구조(파싱→변환→fold)에 잘 맞음
- IntelliJ용 Gleam 확장과 LSP가 안정적으로 작동해 개발 환경이 쾌적했음
- 함수형 프로그래밍(FP)은 명령형 코드보다 문제의 본질을 기술하는 방식으로 사고를 전환하게 함
주요 기능과 코드 활용 사례
-
echo: 파이프라인 중간에서 값 확인이 가능한 단순 출력 함수로, 문자열 포맷 없이 디버깅 가능- 문자열 보간 기능이 없어 텍스트 생성 시
<>"연산이 많아지는 점은 불편 요소로 언급
- 문자열 보간 기능이 없어 텍스트 생성 시
-
옵션 타입(
dict.get) : 그리드 퍼즐에서 경계 검사 없이 안전한 이웃 탐색 가능 -
리스트 유틸리티
-
list.transpose: 행렬 전치 연산으로 퍼즐 구조 단순화 -
list.combination_pairs: 3D 포인트 쌍 생성 시 중첩 루프 없이 한 줄로 처리 -
fold_until: 조건 충족 시 조기 종료 가능한 fold 함수로, 퍼즐 반복 계산에 효율적
-
Gleam의 제약과 불편 요소
-
표준 라이브러리에 파일 IO 부재,
simplifile패키지로 대체 사용 -
정규식 기능도 외부 의존(
gleam_regexp) 필요 -
리스트 패턴 매칭 제약:
[first, ..middle, last]형태 불가 -
비교 연산의 명시적 처리:
order타입을 사용해야 하며, 단순 비교 시 구문이 장황해짐
고급 활용과 퍼즐별 사례
-
bigi: JavaScript 타깃 시 정수 오버플로 방지를 위해 사용 - XOR 비트마스크: Day 10-1에서 조명 토글 문제를 XOR 연산으로 모델링해 효율적 해결
-
glpsol호출: Day 10-2에서 선형 방정식 풀이를 위해 LP 파일 생성 후 외부 명령 실행 - 메모이제이션 키: Day 11-2에서 노드와 상태를 함께 키로 사용해 즉시 계산 완료
-
마지막 퍼즐은 입력 가정에 의존적이었으며, 단순 면적 비교(
heuristic_area <= max_area)로 해결
결론과 향후 계획
- Gleam은 표준 라이브러리 한계에도 불구하고 안전성과 표현력에서 강점을 보임
-
파이프라인, 옵션/결과 타입, 리스트 함수,
fold_until등은 퍼즐 풀이를 명확하게 만듦 - 향후 웹서버 개발 등 실제 프로젝트 적용을 계획하며, 다음 해 Advent of Code에서도 Gleam을 계속 사용할 의향을 밝힘
- 전체 소스코드는 GitHub 저장소에 공개됨 (
tymscar/Advent-Of-Code/2025/gleam/aoc/src)
Hacker News 의견들
-
Gleam은 정말 아름다운 언어임. Elixir가 타입 시스템 면에서 이런 방향으로 발전했으면 좋겠다는 생각을 함
Gleam도 Erlang VM인 BEAM 위에서 동작하며, 덕분에 동시성과 큐 처리가 매우 쉬움
생태계도 훌륭함. 다만 LLM 시대 이후로 2021년 이후의 언어 발전이 멈춘 것 같아 걱정됨
그래도 Gleam이 그 문 닫히기 직전에 잘 들어왔고, 곧 LLM들도 따라잡을 거라 기대함- 왜 LLM이 언어 발전을 멈추게 한다고 생각하는지 궁금함. 최신 모델들은 올해까지의 지식을 포함하고 있고, 새로운 언어도 예시 몇 개만 있으면 꽤 잘 배움
언어들이 문법적으로나 철학적으로 완전히 다를 수는 없으니까 큰 문제는 아닐 것 같음 - Gleam이 OTP 위에 만들어졌다는 건 정확하지 않음. Erlang VM은 BEAM이고, OTP는 Erlang의 라이브러리와 설계 원칙 모음임
Gleam은 자체적으로 타입 안전한 OTP 서브셋을 제공함. 관련 라이브러리는 gleam-lang/otp 참고 - 맞음, Erlang VM은 BEAM이고 OTP는 아님. Gleam의 OTP 구현은 Elixir나 Erlang만큼 완성도 높지는 않음
- 나도 최근 Elixir로 LLM 기능을 포함한 프로젝트를 처음 만들어봤는데, 오히려 이런 흐름이 언어 채택을 촉진할 수도 있다고 느낌
- Elixir도 점진적으로 set-theoretic typing을 도입 중임. 관련 문서: gradual-set-theoretic-types
- 왜 LLM이 언어 발전을 멈추게 한다고 생각하는지 궁금함. 최신 모델들은 올해까지의 지식을 포함하고 있고, 새로운 언어도 예시 몇 개만 있으면 꽤 잘 배움
-
올해 Advent of Code를 Gleam으로 풀어봤는데 꽤 인상 깊었음
장점으로는 성능이 좋고, 언어 서버가 놀라울 정도로 강력함. 자동 포맷팅, 자동 import, 패턴 매칭 보완 등 개발 경험이 훌륭함
단점은 포매터가 지나치게 세로로 코드를 늘리고, 단순함을 중시하다 보니list.map처럼 반복 입력이 많음. 또 라이브러리 생태계가 아직 부족함- 나도 성능에 놀랐음. C만큼은 아니지만 예상보다 훨씬 빠름. 언어 서버도 거의 모든 IDE에서 잘 작동함
list.map은import gleam/list.{range, map}식으로 줄일 수 있음. C 라이브러리 포팅도 흥미로울 듯함 - 단점들은 감수할 만하지만, if/else나 guard가 없어서 불편함. 불리언 분기 처리가 너무 장황해짐
- F#로 AoC를 했는데 비슷한 느낌이었음.
List.map같은 네임스페이스 반복이 탐색성(discoverability) 을 떨어뜨림 - 인자 포매팅은 아마 Prettier 알고리즘 때문일 것임. 그래도 clang-format의 binpacking보다 훨씬 낫다고 생각함
- 나도 성능에 놀랐음. C만큼은 아니지만 예상보다 훨씬 빠름. 언어 서버도 거의 모든 IDE에서 잘 작동함
-
Gleam을 좋아하지만, 재귀 함수 호출 제약이 아쉬움. 내부 함수 호출이 자유롭지 않음
문법적으로는 Scheme보다 덜 우아하고, 개념적으로는 Erlang보다 단순함. 그래도 정적 타이핑은 장점임
OCaml도 써봤지만 opam의 lock 파일 문제 등으로 환경 재현성이 떨어졌음. SML 생태계가 더 컸으면 좋겠다는 생각임- 나도 비슷한 생각임. Haskell은 이론적으로는 멋지지만, 단순한 hello world도 리소스 소모가 큼
Idris 2는 의존 타입과 우아한 설계를 갖췄지만 생태계가 작고, PureScript는 Haskell보다 실용적이지만 JS 런타임에 묶여 있음 - ML 계열을 좋아한다면 ReScript v12를 추천함. OCaml과 Gleam 사이의 균형 잡힌 위치에 있음
- 나도 비슷한 생각임. Haskell은 이론적으로는 멋지지만, 단순한 hello world도 리소스 소모가 큼
-
echo기능을 보며 디버거에 이런 중간 결과 확인 기능이 기본으로 있었으면 좋겠다고 느낌
배열 슬라이스나 필터 체인 중간 결과를 코드 수정 없이 볼 수 있으면 좋겠음
또 2차원 배열을 그리드로 쓰는 건 비효율적이라 생각함. 1차원 배열 + 경계 정보가 더 안전하고 효율적임 -
Gleam은 잘 모르지만
list.map(fn(line) { line |> calculate_instruction })은
그냥list.map(calculate_instruction)으로 쓸 수 있지 않나 싶음- 맞음, 나도 종종 더 복잡한 처리를 하다 지우고 저 형태를 남겨둔 적이 있음
- 네, 그게 맞음
-
Gleam은 훌륭한 언어임. 나에겐 크게 와닿진 않았지만, 사람들이 즐기는 걸 보니 반가움
Gleam + Lustre 조합이 새로운 Elm이 될 수도 있겠다는 생각을 함- 백엔드 개발자로서 Elm은 매력적이었지만, 창작자와의 갈등과 릴리스 중단으로 멀어졌음. 그래도 그 아키텍처는 다른 프로젝트에서도 유용했음
- 나도 최근 Gleam + Lustre로 작은 앱을 만들어봤는데, Elm + PostgREST보다 훨씬 잘 됐음. 이제 더 큰 프로젝트에도 쓸 예정임
- Lustre를 살펴봤는데 생태계가 아직 작음. 인증 관련 예시도 없어서 LiveView로 갔음. 그래도 ergonomics가 좋아서 성장하길 바람
-
요즘 LLM 시대에 새로운 언어를 배워야 할 가치가 있을지 고민됨
LLM이 학습하지 않은 언어라면 도구로서의 효용이 떨어질까 걱정임- 장기적으로 LLM이 새로운 언어를 학습하지 못한다면, 일반 지능으로서의 목표에 실패한 것임
- 1~2년 전엔 그런 우려가 있었지만, 지금은 Claude Code가 Elixir 코드도 꽤 잘 씀. 학습 데이터가 적어도 문제없음
- Claude는 Gleam도 잘 다룸. 문서와 진단 메시지 품질이 좋아서 LLM이 배우기 쉬움. Rust 수준의 진단을 제공함
반면 Swift는 문법이 복잡해 LLM이 다루기 어려움 - 언어를 도구로 본다면, 시장 수요 부족이 더 큰 제약일 수도 있음
- 새로운 언어들이 LLM의 한계 때문에 멈추지 않길 바람
-
예전에 Gleam을 봤을 때 동적 디스패치(interface나 type class)가 없어 보였는데, 지금은 어떤지 궁금함
- 보통 “함수 구조체를 전달하라”는 식으로 해결함. 명시적 접근이라 오히려 제네릭의 복잡함에서 자유로워 좋음
- Gleam은 일급 함수를 지원하므로 동적 디스패치가 가능함. type class나 interface는 결국 고차 함수로 풀 수 있음
-
[first, ..rest]나[first, second]는 가능하지만[first, ..middle, last]는 안 됨.
아마 비용이 비싸서 의도적으로 막은 것 같음 -
다행히도 블로그 제목 경찰이 빠르게 출동했음
관련 링크