함수형 언어, 두 개의 길
함수형 프로그래밍에 관심을 갖다 보면 결국 두 산 앞에 서게 돼요. 한쪽은 Haskell이에요. 정적 타입, 게으른 평가, 모나드. "수학처럼 코드를 짠다"는 평을 받는 언어죠. 다른 한쪽은 Lisp/Scheme 계열이에요. 1958년부터 살아남은 가장 오래된 고급 언어 가문이고, 괄호로 가득한 그 모습 때문에 한 번씩 놀림받지만 여전히 단단한 팬층이 있어요. 최근 한 개발자가 "나는 왜 여전히 Haskell이 아니라 Lisp/Scheme을 잡는가"라는 글을 올려서 양 진영의 차이를 다시 환기시켰어요.
글쓴이가 말하는 핵심
글쓴이의 입장은 단순해요. "Lisp는 도구이고, Haskell은 철학이다"라는 거예요. Lisp는 만들고 싶은 게 있을 때 거의 마찰 없이 바로 쓸 수 있어요. REPL(코드를 한 줄씩 쳐서 바로 결과를 보는 대화형 환경)을 켜놓고 함수 하나 만들고, 데이터 갖고 놀고, 매크로(코드를 만드는 코드)로 도메인에 맞는 작은 언어를 그 자리에서 찍어내는 게 가능해요. 이게 "image-based development"라는 워크플로우인데, 시스템이 살아있는 채로 그 안을 계속 수정하는 방식이에요.
반면 Haskell은 그렇지 않아요. 무언가를 짜려고 하면 먼저 타입을 어떻게 잡을지부터 고민하게 돼요. "이 효과는 IO 모나드 안에 있어야 하나, State 모나드를 쓸까, 아니면 Reader로 묶을까?" 같은 질문이 끝없이 따라붙죠. 잘 잡으면 컴파일 통과 = 거의 정답이라는 멋진 경험을 주는데, 그 "잘 잡기"까지가 길어요. 그래서 글쓴이는 "빨리 만들어서 돌려보고 싶을 때 Haskell이 발목을 잡는다"고 표현해요.
매크로의 힘
Lisp의 진짜 무기는 매크로예요. 다른 언어에서 매크로는 보통 "문자열 치환"이거나 좀 더 좋아도 "AST 변환"인데, Lisp의 매크로는 차원이 달라요. 코드 자체가 리스트(데이터)이기 때문에, 코드를 데이터처럼 받아서 가공하고 다시 코드로 돌려보낼 수 있어요. 이걸 homoiconicity(동질구조성, 코드와 데이터가 같은 모양)라고 불러요.
예를 들어 "DB 트랜잭션 안에서 코드를 실행하라"는 패턴을 만들고 싶다고 해봐요. 다른 언어에선 데코레이터, 콜백, async context manager 같은 걸 동원해야 하는데, Lisp에선 (with-transaction db ...) 같은 새 문법을 매크로로 그냥 만들어버려요. 언어를 문제에 맞게 늘리는 게 가능한 거죠. Clojure(JVM 위의 Lisp), Racket(현대화된 Scheme) 사용자들이 이 매력에 빠져 있어요.
Haskell이 잘하는 영역
그렇다고 Haskell이 별로라는 얘기는 아니에요. 컴파일러, 결제 시스템, 항공/금융 같은 "틀리면 큰일 나는 영역"에선 Haskell의 타입 시스템이 빛나요. GHC의 최적화는 무서울 정도고, 동시성 모델(STM, async)은 우아해요. Pandoc(문서 변환기), Cardano 블록체인, 일부 트레이딩 시스템이 Haskell로 만들어진 이유가 있어요.
결국 "빨리 탐색하면서 만드는" 작업과 "한 번에 완벽하게 정의하는" 작업의 차이예요. 데이터 분석, 스크립팅, 도메인 특화 언어 만들기엔 Lisp가, 신뢰성이 생명인 시스템엔 Haskell이 자연스럽게 맞아요.
비교할 만한 다른 선택지들
요즘은 둘만 있는 게 아니에요. OCaml은 ML 가문의 실용주의 노선으로 컴파일러 분야에서 강세고(Facebook의 Hack, Jane Street의 트레이딩 시스템), F#은 .NET에서 같은 역할을 해요. Elixir는 Erlang 위에 Lisp 매크로의 영혼을 얹어 놓아서 Phoenix LiveView 같은 멋진 프레임워크를 낳았고요. Roc, Gleam 같은 신생 언어들도 "Haskell의 안전성 + 더 친근한 문법"을 노리고 있어요.
한국 개발자에게 주는 시사점
한국 채용 시장에서 Lisp나 Haskell로 밥 벌어먹기는 솔직히 어려워요. 하지만 "한 가지 함수형 언어를 깊이 파보는 경험"은 주력 언어가 무엇이든 코드를 보는 눈을 바꿔줘요. JavaScript의 map/filter/reduce, Kotlin의 data class와 sealed class, TypeScript의 discriminated union, React의 순수 함수형 컴포넌트 — 이 모두가 함수형 사고에서 나온 개념이에요. Clojure로 작은 사이드 프로젝트 하나 해보거나, Haskell로 "Real World Haskell" 따라 해보는 것만으로 본업 코드의 품질이 올라가요.
마무리
타입 안전성과 빠른 탐색은 함수형 세계의 두 축이에요. 어느 쪽이 더 좋다기보다, 지금 풀려는 문제가 어느 축에 가까운지가 중요한 거죠. 여러분은 새로운 언어 하나를 배운다면 "안전하게 짜는 법"과 "빠르게 탐색하는 법" 중 어느 쪽을 먼저 배우고 싶으세요?
🔗 출처: Hacker News
TTJ 코딩클래스 정규반
월급 외 수입,
코딩으로 만들 수 있습니다
17가지 수익 모델을 직접 실습하고, 1,300만원 상당의 자동화 도구와 소스코드를 받아가세요.
"비전공 직장인인데 반년 만에 수익 파이프라인을 여러 개 만들었습니다"
실제 수강생 후기- 비전공자도 6개월이면 첫 수익
- 20년 경력 개발자 직강
- 자동화 프로그램 + 소스코드 제공