서론: 이 글이 왜 흥미로운가
Haskell이라는 언어가 있다. 1990년 학계에서 태어났고, 30년 동안 “수학 전공자나 좋아하는 언어”, “프로덕션에서는 못 쓰는 도구”라는 평을 들어왔다. 그런데 미국 핀테크 Mercury는 이 언어로 짠 200만 줄짜리 백엔드 하나로 한 해 $248B(약 360조 원) 규모 거래를 처리한다.
2026년 3월 30일, Mercury의 엔지니어 Ian Duncan이 그 운영 경험을 한 편의 글로 공개했다. Hacker News에서 397점, 196 댓글이 달렸고, 댓글의 절반은 “함수형 언어로도 진짜 굴러가긴 하는구나”, 나머지 절반은 “Rust로 다시 쓰면 더 빠르다”였다.
결론부터 말하면 — Haskell이 부활한 게 아니다. 노동시장 문제를 영리하게 우회한 회사 하나가 살아남은 사례일 뿐이다. 다만 그 우회법이 한국 스타트업에도 시사점이 있다.
본문을 따라가기 위한 짧은 용어 정리:
- Haskell: 함수형 언어. “같은 입력은 항상 같은 출력”을 강제하는 순수 함수가 기본 단위.
- 함수형 프로그래밍 (FP): 객체와 상태 변경 대신 함수 합성으로 프로그램을 짠다. Java/Python의 클래스·필드 대신, 입력 → 출력만 있는 함수들의 결합.
- 타입 시스템: 변수에 어떤 종류의 값이 들어가는지 컴파일러가 검사. TypeScript의 훨씬 엄격한 사촌이라고 봐도 큰 그림은 맞다.
이 정도만 알아도 본문은 따라온다.
Mercury라는 회사
미국 핀테크다. 창업자는 Y Combinator 시절부터 결제·결제망 스타트업을 굴려온 Immad Akhund. 본업은 스타트업·중소기업 대상 디지털 뱅킹 — 예금, 카드, 송금(미국 ACH/Wire 표준)을 파트너 은행 뒤에 두고 SaaS로 제공한다. 한국으로 치면 자체 은행 라이선스 없이 신한·하나 같은 기존 은행 위에 SaaS UX만 입혀 굴리는 모델에 가깝다.
| 지표 | 값 |
|---|---|
| 비즈니스 고객 | 30만+ |
| 2025년 거래액 | $248B (≈ 360조 원) |
| 2025년 ARR | $650M (전년 대비 +50%) |
| 직원 | ~1,500명 (엔지니어 ~200명) |
| GAAP 흑자 | 3년 연속 |
| 2025-03 Series C | $300M @ $3.5B (Sequoia 리드) |
| 2026-04 신규 라운드 | $5B+ 협상 중 (Crowdfund Insider) |
핀테크는 “Haskell이 어울릴 리 없는” 도메인의 표상이다. 거래량은 폭증하고, 규제는 빡빡하고, 다운타임 1분이 헤드라인을 만든다. 그런데 Mercury는 2023년 3월 SVB(실리콘밸리은행) 파산 위기 5일간 $20억 예금 유입을 무손실 흡수했다. 다른 은행이 흔들릴 때 그쪽 고객이 한꺼번에 옮겨오는 건 보통의 백엔드라면 즉사 시나리오다.
코드베이스 규모
| 시점 | LOC |
|---|---|
| 2024 (Serokell 인터뷰) | 1.2M 줄 |
| 2026 (Ian Duncan 글) | ~2M 줄 |
주석을 뺀 순수 코드 기준이다. 2년 만에 1.7배. 이 200만 줄이 분리된 마이크로서비스가 아니라 하나의 거대한 백엔드(모놀리식) 안에 모듈 1만 개 이상으로 들어 있다. 직접 의존하는 OSS Haskell 패키지(Hackage 의존성, Hackage = Haskell의 npm/PyPI)도 194개다(2024 기준).
비교 한 줄 — Standard Chartered 은행은 자체 Haskell 방언 Mu로 650만 줄 이상을 운영하지만, 자체 컴파일러까지 만들어 쓴다. Mercury는 표준 GHC(Haskell 공식 컴파일러, JVM이 자바에서 차지하는 위치)를 그대로 쓴다. 즉 “특수한 사내 도구로만 가능한” 사례가 아니라는 점이 이 케이스의 무게중심이다.
기술 스택을 말로 풀어보면
Haskell (GHC 9.x)
├── 웹 프레임워크 : Yesod
├── DB ORM : Persistent
├── 부수효과 관리 : ReaderT-over-IO + mtl (RIO 패턴)
├── 워크플로 엔진 : Temporal + 자체 hs-temporal-sdk
├── 빌드/배포 : Nix (개발/CI/배포 통일), NixOS, Buck2
├── DB : PostgreSQL
└── 클라우드 : AWS
처음 보는 단어가 많을 테니 한 줄씩 풀어쓴다.
- Yesod / Persistent: 각각 Haskell판 Rails / Hibernate. 둘 다 Michael Snoyman 한 사람이 주축이다.
- ReaderT-over-IO + mtl (RIO 패턴): Haskell이 부수효과(DB 접근, 로깅, 외부 API 호출)를 다루는 가장 보수적인 표준 패턴. Spring의 ApplicationContext처럼 “전역 설정과 DB 핸들 한 통”을 모든 함수에 자동으로 흘려보내는 것으로 큰 그림을 잡으면 된다. mtl은 그 흐름을 표현하는 표준 라이브러리.
- Temporal: 며칠씩 걸리는 작업(예: 송금 후처리)을 안전하게 재시도하고, 중간에 죽었다 살아나도 이어가는 오케스트레이션 엔진. Mercury는 Temporal의 Rust SDK를 Haskell에서 호출하기 위해
hs-temporal-sdk를 직접 만들었다. - Nix: “내 노트북, 동료 노트북, CI 서버, 프로덕션 서버에서 똑같은 빌드를 재현”이 목표인 패키지 관리자 겸 빌드 도구. 학습 곡선이 가파른 걸로 악명 높다. CTO 본인이 후술하는 인터뷰에서 “내가 가장 자신 없는 아키텍처 선택”이라고 말한다.
- Buck2: Meta가 만든 빌드 시스템. Mercury는 빌드 캐싱 가속용으로 도입.
이 스택에서 두 가지 선택이 흥미롭다.
1. Mercury는 “최신 Haskell 트렌드”를 거부한다. Haskell 커뮤니티는 지난 5년간 effectful, polysemy, fused-effects, cleff 같은 차세대 부수효과 관리 라이브러리(advanced effect system)를 두고 격론을 벌여왔다. Mercury는 이걸 다 거른다. CTO Max Tagher는 Serokell 인터뷰에서 단호하다 — “limited benefits, higher complexity, numerous unknown unknowns”(이득은 작고 복잡도는 높고 모르는 위험이 너무 많다). 15년 된 mtl 패턴이면 충분하다는 입장이다.
2. Mercury는 외부 라이브러리보다 자체 클라이언트를 선호한다. 외부 OSS Haskell 라이브러리는 1인 메인테이너가 취미로 만든 경우가 많다. Mercury는 운영성 — 모니터링, 에러 처리, 재시도 — 을 그 사람의 여유 시간에 맡기지 않는다.
빌드 시간은 정직하게 적었다. 클린 빌드 약 12분, 프로덕션 빌드 약 30분. 200만 줄 모놀리식의 현실이다.
채용 역설: “Haskell이 가장 뽑기 쉬운 포지션”
이 글에서 가장 충격적인 인용은 한 줄짜리다.
“Backend Haskell engineer is the easiest role to hire for in all of Mercury.” — Max Tagher, Mercury CTO
상식과 정반대다. Haskell 개발자 풀이 Python보다 작은 건 누구나 안다. 그런데 가장 쉽다고?
답은 Python Paradox다. Paul Graham이 2004년에 쓴 짧은 글의 요지는 이렇다 — “우리는 어려운 언어 X를 씁니다”라고 적어두면, 정말로 X에 관심 있는 사람만 지원한다. 풀의 크기는 줄지만 풀의 평균 품질이 위로 옮겨간다(셀프 셀렉션). Haskell은 이 효과가 가장 강하게 걸리는 언어다. “Haskell 한번 해보고 싶어서요”라고 말하는 지원자의 평균 코딩 실력은, “Java 잘해요”의 평균보다 위쪽이라는 가설이다.
HN의 spopejoy는 이걸 한 줄로 정리했다 — “Haskell’s biggest problem by far is the tiny labor pool, which Mercury seems to wisely avoid”(가장 큰 문제는 노동 풀이 작다는 것인데, Mercury는 이걸 영리하게 피해 가는 것으로 보인다).
추가 데이터 — Mercury는 Production Haskell이라는 책을 쓴 Matt Parsons를 사내 트레이너로 둔다. 이 글에는 “Haskell 책을 쓴 사람을 두 명 채용할 수 있는 회사”라는 표현이 등장한다. 한국 IT로 옮기면 “Spring 입문서 베스트셀러 저자 두 명을 풀타임으로 채용한 SaaS”인 셈이다.
2주 부트캠프: 모르는 사람을 키워서 쓴다
채용 풀이 너무 작다면? Mercury의 답은 “Haskell 모르는 generalist를 뽑아서 사내에서 가르친다”이다. 공식 부트캠프는 이렇게 운영된다.
- 외부 책·강의 0개. 전부 사내 자료.
- 10세트 연습문제 + 200단어 미만 입문 글 + 90초짜리 YouTube + 잘 짜인 예시 코드.
- 1:1 멘토링이 핵심인데, 멘토는 답을 직접 주지 않는다. 학습자가 스스로 떠올리도록 유도하는 방식(active recall).
- 학습자 50명 이상. 인턴부터 시니어, 매니저까지 다 통과.
- 영업일 10일 안에 monad transformer stack(Haskell이 부수효과를 누적해 다루는 표준 추상 — 정확한 정의는 몰라도 된다)에 도달하는 게 일반적.
- 풀 생산성까지 6~8주.
HN의 maz1b는 이 전략의 함의를 이렇게 짚었다 — “hiring generalists with no prior experience…helped them, because they got to instill their culture and style from the ground up.”(경험 없는 generalist 채용이 오히려 도움이 됐다, 회사 문화와 스타일을 처음부터 심을 수 있었기 때문에.) 경험자가 없는 것이 culture lock-in 방지에 오히려 유리하다는 역설이다.
한국 스타트업이 채용 어려움을 호소할 때 가장 자주 듣는 조언이 “경력자를 뽑아라”인데, Mercury는 정확히 반대로 갔다.
강점: 타입이 실제로 뭘 막아주는가
이 글의 진짜 가치는 추상적 “Haskell의 우월성” 자랑이 아니라, 운영에서 실제로 막힌 사고들을 구체적으로 나열한 점이다.
1. Transact 타입 캡슐화. DB에 쓰는 모든 작업을 Transact라는 타입에 가둬뒀다. 그리고 외부에는 commit 함수 하나로만 노출한다.
-- 의사 코드
newtype Transact a = ...
commit :: Transact a -> IO a
이게 왜 중요한가 — 이벤트 발행을 빠뜨리거나, 트랜잭션 원자성을 깨뜨리는 흔한 실수가 컴파일 타임에 막힌다. 잘못 쓰려면 컴파일이 안 되도록 만들어 둔 것이다. Ian Duncan은 이걸 “올바른 운영 절차가 가장 저항이 적은 경로가 되도록”(the correct operational procedure the path of least resistance)이라고 표현한다.
2. 도메인 에러 ≠ HTTP 에러. “잔액 부족”(InsufficientFunds)은 비즈니스 도메인의 개념이다. HTTP 402는 그걸 외부에 노출하는 한 가지 방식일 뿐이다. Mercury는 둘을 다른 타입으로 분리해서, 같은 도메인 에러를 HTTP 핸들러에서도, 백그라운드 워커에서도, Temporal 워크플로에서도 똑같이 재사용한다.
3. ID 혼동 방지. 미국에는 SSN(개인 사회보장번호)과 EIN(사업자번호)이 있다. 둘 다 9자리 정수다. 다른 나라 개발자라면 “그냥 string으로 다루지 뭐”라고 넘길 일이지만, 둘이 섞이면 KYC가 망가진다. Mercury는 이 둘을 다른 타입으로 만들어 컴파일러가 혼동을 차단한다. CTO 인터뷰에서 자주 인용되는 사례다.
4. 트랜잭션 안에서 외부 HTTP 호출 차단. DB 트랜잭션 락을 잡은 상태에서 외부 API를 호출하면 락이 길어지고 데드락 위험이 커진다. 거의 모든 시스템에서 일어나는 클래식한 사고다. Mercury는 타입으로 “트랜잭션 안에서는 이런 IO를 못 쓰게” 강제한다. 글의 표현으로는 “다른 언어라면 코드 리뷰에서 항상 경계해야 할 일”을 컴파일러가 대신 해 주는 셈이다.
5. JSON 디코딩 보안. Ruby/Python의 일부 JSON 라이브러리에서는 잘못 다루면 임의 코드 실행 취약점이 나오기도 한다. Haskell의 정적 디코딩은 이런 카테고리의 취약점 자체가 발생할 수 없다.
약점도 솔직하게 적었다
이 글이 호평받은 이유 중 하나는 약점을 숨기지 않았다는 점이다.
unsafePerformIO(Haskell의 “비상 탈출구” — 순수 함수 행세를 하지만 실제로는 부수효과를 일으키는 함수)가 핵심 라이브러리(bytestring,text)에서도 성능을 위해 쓰인다. 글의 입장은 “purity는 절대적 속성이 아니라 캡슐화된 위험”이다.- Hackage 라이브러리 다수가 1인 메인테이너의 취미 프로젝트라 테스트가 부족하다.
- HTTP 클라이언트 라이브러리(
http-client)는 아직 HTTP/1.1만 지원해서 회피책이 필요하다. - 타입은 만능이 아니다. cents(센트)와 dollars(달러)를 둘 다
Int로 두면 단위 실수는 컴파일러가 못 잡는다. 의미론적 정확성은 별도 설계 작업이다. - Day-1 속도는 Rails나 Next.js보다 느리다. Passport(Node.js의 통합 인증 미들웨어), Devise(Rails의 인증 솔루션) 같은 “올인원 패키지”가 Haskell에는 없다.
- Nix 학습 곡선이 가파르다. CTO 본인이 “내가 가장 자신 없는 아키텍처 선택”이라고 했다.
- 부분 함수와
error호출(예외 던지기)이 “여기 도달하면 버그”라는 마킹과 함께 프로덕션에 잔존한다.
특히 observability(서비스를 운영 중에 들여다보는 능력 — 로그·트레이스·메트릭) 섹션이 글 전체에서 가장 길다. HN의 GuB-42는 이걸 두고 “Harder to do when the language goes out of its way to hide the state from you”(언어가 일부러 상태를 숨기려고 하니, 그걸 들여다보는 게 더 어렵다)라고 했다. Haskell의 “순수성”이라는 강점이 운영에서는 비용으로 돌아온다는 뜻이다. Mercury의 해법은 라이브러리가 직접 로그를 찍지 않게 하고, “함수 묶음”(records-of-functions) 패턴으로 외부에서 로그·트레이스를 끼워넣을 수 있게 만든 다음 hs-opentelemetry-api로 OpenTelemetry에 연결하는 것이다. 즉 “기본은 깔끔하게, 측정은 외부에서 주입”.
HN 196 댓글의 핵심 5쟁점
1. 타입 시스템의 ROI
- 친 (bri3d): “Haskell은 잊혀지면 안 되는 규칙들을 타입에 박아넣을 수 있는 도구를 준다.”
- 반 (jappgar): “결국 자기 타입에 갇힌다. 정책이 바뀔 때마다 대형 리팩토링이 따라온다.”
2. Rust vs Haskell
이번 토론에서 가장 많이 인용된 반대 입장이다.
- 친 Rust (xedrac): 3년 Haskell 경험에도 Rust에서 2배 빠르게 일한다. Nix와의 결합도, 흩어진 language extension(컴파일러 옵션 같은 것), “거의 write-only(읽기보다 쓰기 편한 — 다시 말해 남이 읽기 어려운)” 가독성을 비판.
- 친 Haskell (Darmani): Haskell이나 Java에서 사소한 고차 함수 패턴이 Rust 전문가에게도 거의 불가능에 가깝다.
- 암묵적 합의: 도메인 의존이다. 핀테크 백엔드는 Haskell, 시스템 프로그래밍은 Rust.
3. 운영 측 부채
이미 위에서 다뤘다. 글의 가장 긴 섹션이 observability라는 사실 자체가 운영 비용이 적지 않다는 메타 비평으로 이어졌다.
4. 노동시장
spopejoy의 “tiny labor pool which Mercury seems to wisely avoid”가 합의에 가깝다. 우회는 가능하다. 다만 그게 모든 회사의 답은 아니다.
5. 타입 vs affordance
- **회의 (mhh__)**: “C#에서도 다 할 수 있다. 타입이 아니라 affordance(언어가 어떤 행동을 권장하는가) 문제다.”
- 반박 (dirkt): “TypeScript도 Rust도 타입 레벨에서 순수성을 강제하지는 못한다. 그게 Haskell의 차별점이다.”
“FP가 부활했다”는 잘못된 해석이다
이 글을 “함수형 프로그래밍이 마침내 메인스트림에 진입했다”로 읽는 건 과장이다. HN 댓글에 그런 언급은 거의 없고, 2010년대의 Scala·Clojure 부흥과 비교하는 댓글도 안 보인다.
분위기는 더 온건하다 — “Mercury 같은 회사가 영리한 우회 전략으로 운영 가능하다.” 그게 전부다. Discourse의 dschrempf는 “small ecosystem”을 1차 약점으로 짚으면서도 글 자체는 “blind praise를 피한 균형 잡힌 사례 보고”라고 호평했다.
한국 개발자에게 남는 세 가지
1. “사람이 없어서 못 한다”는 핑계가 무너진다. Mercury는 노동시장 문제가 가장 심한 언어를 일부러 골랐고, 경험 없는 generalist를 사내에서 키워 200명짜리 팀을 만들었다. “한국에 그 기술 경험자가 없다”는 통상의 변명이 데이터로 반박된다.
2. 단일 언어 모놀리식이 유리한 도메인이 있다. 마이크로서비스 + 다언어 스택의 운영 비용을 Mercury는 200만 줄짜리 한 덩어리로 회피한다. 200명이 같은 언어, 같은 코드베이스, 같은 컨벤션을 본다. 컨텍스트 스위칭 비용이 거의 0이다. 모든 회사에 맞는 처방은 아니지만, “마이크로서비스가 항상 정답”이라는 통념엔 분명한 반례다.
3. 타입은 사람보다 오래 산다. 작성자가 퇴사해도 살아남는 지식 인코딩 메커니즘이 타입이다. 한국 IT의 인력 회전율을 생각하면 이 가치가 더 절실하다. 주석은 거짓말을 하지만, 컴파일러가 강제하는 타입은 거짓말을 못 한다.
2026년 Haskell 생태계 한 줄 요약
- GHC 9.12.4 (2026-03-27 릴리스), 9.14.1 (2025-12-19).
- GHC 9.14가 첫 LTS(장기 지원) 버전이 됐다. 최소 2년 버그픽스 + LTS 간 6개월 오버랩.
- GHC 10.0 (옛 9.16) 브랜치는 2026-04-01 fork.
- HLS(Haskell Language Server)·Cabal·Stack 모두 9.12 정식 대응.
- Mercury 같은 대규모 사용자는 Stack 대신 Nix + Cabal 조합으로 직접 운영.
- Well-Typed가 Mercury 의뢰로 HLS 성능 개선 작업 중.
- Haskell Debugger (hdb) — 9.14에서 바이트코드와 컴파일된 코드의 stack trace를 통합.
생태계는 죽지 않았다. 다만 Q1 2026 Well-Typed 리포트에서 보듯 LTS 정책 안착, Hackage 거버넌스 강화, observability 도구 발전 — 즉 “운영성 개선”이 메인 트랙이다. 이건 Mercury 같은 production user가 생태계의 무게중심을 옮기고 있다는 신호다.
다음 글
- Ollama를 멈춰야 할 이유와 2026년 로컬 LLM 대안 가이드 — 단일 도구 락인 vs 다양한 백엔드 트레이드오프
- GPT-5.4 Cyber와 AI 사이버보안의 비대칭 구조 — 도메인 특화 모델의 의미
참고
- A couple million lines of Haskell: Production engineering at Mercury (Ian Duncan, 2026-03-30)
- Hacker News 토론 (397pt, 196 comments)
- Discourse 토론
- Max Tagher Serokell 인터뷰
- Mercury Engineering: Learn Haskell in Two Weeks
- MercuryTechnologies GitHub
- Standard Chartered Core Strats (비교 사례)
- Well-Typed Q1 2026 Haskell Ecosystem Report

