Skip to content

필사 모드: 모던 Clojure 2026 완벽 가이드 — Clojure 1.12 · Babashka · ClojureScript · shadow-cljs · Datomic · XTDB · re-frame 심층 분석

한국어
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

프롤로그 — 왜 2026년에 Clojure인가

2026년 5월, 누군가 "요즘 Lisp을 쓰는 사람이 있나?"라고 묻는다면, 답은 명확하다. **있다, 그것도 아주 많다**. 브라질의 Nubank는 1억 1,000만 명의 고객을 보유한 세계 최대 디지털 은행이며, 그들의 백엔드는 거의 전체가 Clojure로 작성되어 있다. 마이크로서비스가 5,000개를 넘고, 매일 수십억 건의 트랜잭션을 처리한다. CircleCI는 CI/CD 파이프라인 코어를, Apple은 일부 내부 도구를, Cisco는 네트워크 분석 플랫폼을, Walmart Labs는 가격 엔진을 Clojure로 돌린다.

Clojure는 2007년 Rich Hickey가 발표한 후 20년 가까이 같은 철학을 유지해 왔다. **불변(immutable) 우선, 함수형, 동적 타입, JVM 호스트, 동시성을 일급 시민으로**. 그러나 2020년대 들어 Clojure 생태계는 조용히 진화했다. Leiningen 단일 빌드 시대를 지나 `deps.edn`과 `tools.deps`가 표준이 됐고, ClojureScript는 shadow-cljs를 통해 npm 생태계를 통째로 흡수했다. **Babashka**는 GraalVM 네이티브 이미지로 컴파일되어 시작 속도가 ~20ms — Python보다 빠르다. 셸 스크립트 시장에서 Bash와 Python을 동시에 위협한다.

2026년 5월, Clojure 1.12가 안정화되면서 **qualified method invocation** 같은 자바 상호운용성 개선이 들어왔고, `partial`과 `loop`가 더 똑똑해졌다. ClojureScript 측에서는 shadow-cljs 2.x가 React 18·Vite 6·esbuild 통합을 다듬었고, `re-frame 1.4`는 이펙트·이벤트 모델을 더 매끈하게 만들었다. Datomic은 Pro 라이선스가 사실상 무료가 되었고(Cloud는 유료 유지), XTDB 2.0은 bitemporal에 SQL-first를 더해 PostgreSQL 사용자에게도 접근 가능해졌다.

그리고 결정적으로, **LLM 시대가 Clojure에 의외의 순풍을 불어넣었다**. REPL 주도 개발은 본질적으로 "한 표현식씩 평가하고 결과를 본다"의 반복이다. LLM이 코드를 생성하고 사람이 한 단계씩 검증하는 워크플로와 완벽히 맞는다. Cursive·Calva·CIDER 같은 에디터들은 LLM 통합을 강화했고, REPL에서 LLM 응답을 직접 평가하는 패턴이 자리 잡았다.

이 글은 **Clojure 2026의 전체 그림**을 한 글로 정리한다. 언어 자체 → 빌드/배포 → 백엔드 스택 → 프런트엔드 → 데이터베이스 → 테스팅 → 에디터/REPL → 실전 운영. Nubank가 어떻게 5,000개 마이크로서비스를 굴리는지, 한국·일본 커뮤니티가 어디까지 왔는지, 그리고 2026년에 새로 시작하는 사람이 어떤 스택부터 잡아야 하는지까지 짚는다.

> Clojure는 "쓰는 사람이 적은 언어"가 아니다. **"안 보이는 곳에서 무거운 트래픽을 받는 언어"**다. 보여지는 라우저들의 자바스크립트 백엔드가 1% 시장이라면, 보이지 않는 1%의 백엔드가 Clojure다.

가격·버전 숫자는 빠르게 바뀐다. 이 글의 모든 수치는 **2026년 5월 기준**이며, 구조적 차이에 집중한다. 6개월 뒤 마이너 버전이 바뀌어도 의사결정 프레임은 유효해야 한다.

1장 · Clojure 1.12 — 무엇이 바뀌었고 왜 중요한가

Clojure 1.12는 2024년 9월에 처음 릴리즈됐고, 2026년 5월 시점에는 1.12.x 패치가 안정화되어 사실상 표준이다. 핵심 변화 세 가지를 본다.

**Qualified method invocation**

자바 상호운용성에서 가장 큰 변화다. 기존에는 `(.method obj arg)` 형태로만 호출 가능했고, 메서드를 함수처럼 다루려면 `#(.method % arg)` 같은 람다 래퍼가 필요했다. 1.12부터는 메서드를 **값으로** 취급할 수 있다.

;; 이전 (1.11 이하)

(map #(.toUpperCase %) ["foo" "bar" "baz"])

;; => ("FOO" "BAR" "BAZ")

;; 1.12 — qualified method invocation

(map String/.toUpperCase ["foo" "bar" "baz"])

;; => ("FOO" "BAR" "BAZ")

;; 정적 메서드

(map Math/abs [-1 -2 3])

;; => (1 2 3)

;; 생성자도 마찬가지

(map StringBuilder/new ["hello" "world"])

`String/.toUpperCase`처럼 `Class/.method` 형태가 인스턴스 메서드, `Class/method`가 정적 메서드 또는 생성자다. 자바 람다와 비슷한 느낌이지만, Clojure 의미론을 지킨다.

**`partial`의 인라인 최적화**

`(partial f x)`는 새 함수를 만들어 반환한다. 1.12부터는 컴파일러가 인라인할 수 있는 경우 람다와 동등한 성능을 낸다. 핫 패스에서 `partial`을 자유롭게 쓸 수 있게 됐다.

**`loop`의 타입 힌트 보존**

`loop`/`recur` 사이클에서 타입 힌트가 사라지던 문제가 수정됐다. 수치 계산 코드에서 박싱이 줄어 5~15% 성능 개선이 보고된다.

기타: `clojure.core/iteration` — lazy seq의 일반화. `update-vals`, `update-keys` — 맵 변환 헬퍼. `add-tap` — 디버깅 훅 표준화. `random-uuid` — 깔끔한 UUID 생성기.

> Clojure 1.12는 "혁명"이 아니라 "수공구가 더 잘 갈렸다"는 느낌의 릴리즈다. 그러나 자바 상호운용성이 매끈해진 건 큰 일이다. 자바 라이브러리를 부담 없이 호출할 수 있게 됐다.

2장 · tools.deps와 deps.edn — Leiningen 이후의 빌드

오랜 Clojure 사용자들에게 `project.clj`(Leiningen)는 익숙하다. 그러나 2026년 신규 프로젝트의 ~70%는 `deps.edn`과 `tools.deps`를 쓴다. 차이를 본다.

**`deps.edn` 기본 구조**

;; deps.edn

{:paths ["src" "resources"]

:deps {org.clojure/clojure {:mvn/version "1.12.0"}

ring/ring-core {:mvn/version "1.11.0"}

metosin/reitit {:mvn/version "0.7.0"}}

:aliases

{:dev {:extra-paths ["dev" "test"]

:extra-deps {nrepl/nrepl {:mvn/version "1.3.0"}

cider/cider-nrepl {:mvn/version "0.47.0"}}}

:test {:extra-paths ["test"]

:extra-deps {lambdaisland/kaocha {:mvn/version "1.91.0"}}

:main-opts ["-m" "kaocha.runner"]}}}

`clj -X:dev` 같은 alias 호출로 다양한 실행 모드를 정의한다. Maven 좌표를 그대로 쓸 수 있고, Git 좌표도 1급 지원이다.

;; Git에서 직접 의존성

{:deps {io.github.somelibrary/lib

{:git/url "https://github.com/somelibrary/lib.git"

:git/sha "a1b2c3d4..."}}}

이게 왜 중요한가. Maven에 올라가지 않은 라이브러리, 포크한 라이브러리, 내부 라이브러리를 별도 인프라 없이 의존성으로 쓸 수 있다.

**Leiningen은 죽었나**

아니다. Leiningen은 여전히 큰 시장이 있다. `lein` 명령으로 `repl`, `test`, `uberjar`까지 한 줄로 끝난다. 학습 곡선이 더 부드럽고, `project.clj`는 데이터가 아닌 코드라 매크로로 더 유연하다. 단점: 시작 속도가 느리고(JVM + Lein 부팅 ~3초), Maven 중심이라 Git 좌표 같은 기능이 어색하다.

**의사결정 가이드**

- 새 프로젝트 + 라이브러리 다양성 중요 → `deps.edn`

- 기존 Leiningen 프로젝트 유지 → `lein` 그대로

- 라이브러리 배포 → 둘 다 가능, 그러나 `deps.edn` + `build.clj` (`tools.build`) 조합이 점점 표준

**`tools.build`**

`build.clj`라는 빌드 스크립트를 Clojure로 작성한다. `Make`나 `package.json` scripts와 비슷하지만 전부 Clojure다.

;; build.clj 일부

(ns build

(:require [clojure.tools.build.api :as b]))

(def lib 'com.example/my-lib)

(def version "0.1.0")

(def class-dir "target/classes")

(defn clean [_]

(b/delete {:path "target"}))

(defn jar [_]

(b/write-pom {:class-dir class-dir

:lib lib

:version version})

(b/jar {:class-dir class-dir

:jar-file (format "target/%s-%s.jar" (name lib) version)}))

`clj -T:build jar`로 호출한다. 모든 빌드 단계가 Clojure 함수다.

3장 · Babashka 1.4 — Clojure가 들어간 셸

Babashka는 Michiel Borkent(`borkdude`)가 만든 **GraalVM 네이티브 이미지로 컴파일된 Clojure 인터프리터**다. 2026년 5월 기준 1.4.x가 안정 버전이며, 시작 속도가 **20~30ms**에 불과하다. Python(~50ms), Bash 스크립트(~10ms)와 경쟁할 만한 수준이다.

**왜 셸 스크립트로 Clojure를?**

세 가지 이유.

1. **데이터 처리** — JSON, EDN, CSV, YAML이 모두 1급 시민. `jq`보다 표현력이 강하다.

2. **에러 처리** — Bash의 `set -e`는 위험하다. Clojure의 예외와 `try`/`catch`로 견고한 스크립트.

3. **이식성** — `bb` 바이너리 하나만 있으면 어디서나 같은 코드가 돈다.

**실전 예시**

#!/usr/bin/env bb

(require '[babashka.curl :as curl]

'[cheshire.core :as json])

(defn fetch-github-stars [repo]

(-> (curl/get (str "https://api.github.com/repos/" repo))

:body

(json/parse-string true)

:stargazers_count))

(println "Stars:" (fetch-github-stars "clojure/clojure"))

`bb script.clj` 또는 chmod +x 후 직접 실행. JVM 없이 돈다.

**bb tasks**

`bb.edn` 파일에 작업을 선언한다. `npm run`과 비슷한 느낌이지만 Clojure 전체를 쓸 수 있다.

;; bb.edn

{:tasks

{test (shell "clj -X:test")

build (shell "clj -T:build jar")

deploy {:depends [build]

:task (shell "clj -T:build deploy")}

clean (shell "rm -rf target")}}

`bb test`, `bb build`, `bb deploy`처럼 호출. `:depends`로 작업 의존성을 선언할 수 있다.

**nbb — Node Babashka**

Node.js 런타임 위에서 도는 Babashka. npm 패키지를 그대로 쓸 수 있다. Node 생태계를 Clojure로 짧은 스크립트 형태로 다루고 싶을 때.

;; nbb로 npm 패키지 호출

(require '["fs" :as fs])

(println (fs/readdirSync "."))

**squint — CLJS to JS**

컴파일 없이 Clojure식 문법을 JS로 직접 변환. JSX 안에서도 쓸 수 있다. 작은 도구에서 점점 인기를 끈다.

> Babashka는 "Python을 대체하려는 게 아니라, Bash를 대체하고 싶다"고 borkdude가 말한 적 있다. 2026년에 그 야망은 충분히 현실적이다.

4장 · ClojureScript와 shadow-cljs 2.x — npm 생태계의 풀 액세스

ClojureScript는 Clojure 코드를 JavaScript로 컴파일하는 컴파일러다. 2026년 시점에 ClojureScript 개발의 ~80%는 **shadow-cljs**를 빌드 도구로 쓴다. Thomas Heller가 만든 이 도구의 핵심 가치는 **npm 통합**이다.

**shadow-cljs 설정 예시**

;; shadow-cljs.edn

{:source-paths ["src"]

:dependencies [[reagent "1.2.0"]

[re-frame "1.4.0"]

[metosin/reitit-frontend "0.7.0"]]

:builds

{:app {:target :browser

:modules {:main {:init-fn my-app.core/init}}

:output-dir "public/js"

:asset-path "/js"

:devtools {:after-load my-app.core/reload!

:http-root "public"

:http-port 8080}}}}

`npx shadow-cljs watch app`로 시작하면 핫 리로드, REPL, 빌드가 동시에 도는 개발 서버가 뜬다. 빌드는 esbuild 기반이라 빠르다.

**npm 패키지 직접 사용**

shadow-cljs의 결정적 장점이다. `package.json`에 패키지를 추가하면 ClojureScript에서 즉시 import할 수 있다.

(ns my-app.charts

(:require ["chart.js" :as Chart]

["d3" :as d3]))

(defn render-chart [el data]

(Chart/new el (clj->js {:type "bar"

:data data})))

`["chart.js" :as Chart]` — 문자열 라이브러리 이름이 핵심. 일반 Clojure 의존성과 npm 패키지를 같은 require 안에서 섞을 수 있다.

**Reagent — React 래퍼의 클래식**

Reagent는 React 위의 가장 오래된 ClojureScript 래퍼다. Hiccup 문법으로 React 컴포넌트를 작성한다.

(ns my-app.ui

(:require [reagent.core :as r]))

(defn counter []

(let [n (r/atom 0)]

(fn []

[:div

[:p "Count: " @n]

[:button {:on-click #(swap! n inc)} "+1"]])))

`[:div ...]` 같은 벡터가 React element가 된다. `r/atom`은 mutable state를 표현하며 변경 시 자동 리렌더링. React 18의 동시성 기능까지 지원한다.

**Helix — 새로운 React 래퍼**

Helix는 Hook 우선 설계. `defnc` 매크로로 함수형 컴포넌트를 정의한다.

(ns my-app.helix-ui

(:require [helix.core :refer [defnc $]]

[helix.hooks :as hooks]

[helix.dom :as d]))

(defnc Counter []

(let [[n set-n] (hooks/use-state 0)]

(d/div

(d/p "Count: " n)

(d/button {:on-click #(set-n inc)} "+1"))))

`$` 매크로로 다른 컴포넌트를 렌더링. React Hooks와 1:1로 매핑된다. JSX보다 깔끔하다는 평이 많다.

**UIx 2 — 가장 모던한 선택**

UIx 2는 Helix와 비슷한 철학이지만 더 빠른 렌더링 최적화를 강조한다. SSR(server-side rendering) 지원, React Server Components 호환이 작업 중이다. 2026년 신규 ClojureScript 프로젝트의 ~30%가 UIx 2를 택한다.

(ns my-app.uix-ui

(:require [uix.core :refer [defui $]]

[uix.dom]))

(defui counter []

(let [[n set-n] (uix.core/use-state 0)]

($ :div

($ :p "Count: " n)

($ :button {:on-click #(set-n inc)} "+1"))))

5장 · re-frame 1.4 — 큰 SPA의 상태 관리 답

Reagent로 카운터는 만들 수 있다. 그러나 100개 화면짜리 SPA에서 atom을 여러 컴포넌트에 흩뿌리면 디버깅이 지옥이 된다. **re-frame**은 그 답이다. Day8 팀이 만든 이 라이브러리는 ClojureScript의 사실상 표준 상태 관리다.

**re-frame의 핵심 모델**

1. **app-db** — 모든 상태를 담은 단일 큰 맵

2. **events** — 사용자 동작을 표현하는 키워드 (`:user/login`, `:cart/add-item`)

3. **handlers** — event를 받아 app-db를 변환하는 순수 함수

4. **subscriptions** — app-db에서 화면이 필요한 데이터를 뽑는 함수

5. **effects** — 외부 세계와의 상호작용 (HTTP, localStorage, 타이머)

(ns my-app.events

(:require [re-frame.core :as rf]))

;; 이벤트 핸들러

(rf/reg-event-db

:user/login-success

(fn [db [_ user]]

(assoc db :current-user user)))

;; 서브스크립션

(rf/reg-sub

:user/current

(fn [db _]

(:current-user db)))

;; 컴포넌트에서 사용

(defn user-panel []

(let [user @(rf/subscribe [:user/current])]

[:div "Hello, " (:name user)]))

;; 이벤트 디스패치

(rf/dispatch [:user/login-success {:name "Min-yong Kim"}])

**왜 re-frame인가**

세 가지.

1. **시간 여행 디버깅** — re-frame-10x 라이브러리로 모든 event를 트레이스. 특정 시점의 상태로 되감을 수 있다.

2. **순수 함수 우선** — handler가 순수 함수라 테스트하기 쉽다.

3. **이펙트 격리** — HTTP 호출 같은 부수 효과가 명시적이라 테스트와 모킹이 깔끔하다.

**re-frame 1.4의 변화**

- 인터셉터(interceptor) 체인 최적화 — 큰 앱에서 30% 빠른 디스패치

- `reg-fx`에 비동기 이펙트 지원

- Devtools 통합 강화 — Chrome Devtools 패널에서 event 트레이스

> "Reagent + re-frame은 React + Redux의 Clojure 답이다. 그러나 Redux가 보일러플레이트 지옥인 데 반해, re-frame은 매크로로 같은 일을 더 짧게 한다." — Day8 팀의 공식 정리.

6장 · Pathom 3 — 그래프 쿼리의 새 표준

REST나 GraphQL을 쓰면 클라이언트가 필요한 데이터를 서버에 요청한다. 그러나 데이터가 여러 백엔드(DB, 외부 API, 캐시)에 흩어져 있을 때, "이 데이터를 어떻게 모을 것인가"는 항상 백엔드의 고민이다. **Pathom 3**은 그 문제를 그래프 리졸버 방식으로 풀어낸다.

**Pathom 3의 모델**

각 데이터를 어떻게 가져오는지를 **resolver**로 선언한다. 클라이언트는 EQL(EDN Query Language)로 필요한 데이터를 요청하고, Pathom이 리졸버 그래프를 탐색해 답을 모은다.

(require '[com.wsscode.pathom3.connect.indexes :as pci]

'[com.wsscode.pathom3.connect.operation :as pco])

;; 리졸버 — user-id로 user 정보를 가져옴

(pco/defresolver user-by-id [{:keys [user-id]}]

{::pco/output [:user/name :user/email]}

(let [user (db/find-user user-id)]

{:user/name (:name user)

:user/email (:email user)}))

;; 리졸버 — user-id로 주문 목록을 가져옴

(pco/defresolver user-orders [{:keys [user-id]}]

{::pco/output [:user/orders]}

{:user/orders (db/find-orders-by-user user-id)})

(def env (pci/register [user-by-id user-orders]))

;; 클라이언트는 그래프 쿼리로 요청

(p.eql/process env

{:user-id 42}

[:user/name :user/email :user/orders])

;; => {:user/name "Min-yong" :user/email "..." :user/orders [...]}

Pathom이 알아서 두 리졸버를 호출하고 결과를 합친다. 클라이언트는 데이터 출처를 모른다.

**왜 좋은가**

- 백엔드를 점진적으로 리팩토링할 수 있다. 리졸버 안쪽을 바꿔도 클라이언트 쿼리는 그대로.

- N+1 문제를 Pathom이 자동으로 배치 처리.

- GraphQL과 달리 스키마 정의가 코드와 일체화.

**누가 쓰나**

Fulcro 풀스택 프레임워크의 백엔드 표준. Nubank의 일부 마이크로서비스가 Pathom으로 데이터 집계 레이어를 구성한다.

7장 · Datomic Pro · Cloud — 시간을 데이터로

Datomic은 Rich Hickey 자신이 설계한 데이터베이스다. Cognitect가 만들었고, 2023년부터 **Datomic Pro 라이선스가 무료**가 되어 진입 장벽이 사라졌다. 2026년 시점에 Datomic은 두 가지 제품군이 있다.

- **Datomic Pro** — 자체 호스팅, 무료. PostgreSQL/DynamoDB/Cassandra 등을 스토리지로 사용.

- **Datomic Cloud** — AWS 위 서버리스 매니지드, 유료.

**Datomic의 핵심 아이디어**

1. **immutable** — 데이터를 절대 덮어쓰지 않는다. 모든 변경이 append-only.

2. **bitemporal** — 트랜잭션 시간(언제 기록됐는지)과 valid 시간(언제 사실이었는지)을 별도로 추적.

3. **EAV 모델** — entity-attribute-value 트리플. RDF와 비슷.

4. **읽기와 쓰기의 분리** — peer/client가 인덱스를 로컬 메모리에 가져와 쿼리. transactor만 직렬화.

;; 스키마 정의

(def schema

[{:db/ident :user/email

:db/valueType :db.type/string

:db/cardinality :db.cardinality/one

:db/unique :db.unique/identity}

{:db/ident :user/name

:db/valueType :db.type/string

:db/cardinality :db.cardinality/one}])

(d/transact conn {:tx-data schema})

;; 데이터 삽입

(d/transact conn

{:tx-data [{:user/email "min@example.com"

:user/name "Min-yong Kim"}]})

;; Datalog 쿼리

(d/q '[:find ?name

:in $ ?email

:where

[?u :user/email ?email]

[?u :user/name ?name]]

(d/db conn)

"min@example.com")

;; => [["Min-yong Kim"]]

**bitemporal — 시간 여행 쿼리**

;; "2025년 12월 1일 시점의" DB로 같은 쿼리

(d/q '[:find ?name ...]

(d/as-of (d/db conn) #inst "2025-12-01"))

;; 어떤 entity의 모든 변경 이력

(d/history (d/db conn))

**왜 쓰나**

- 감사(audit) 요구사항이 강한 금융·의료 시스템에 적합.

- 스키마 마이그레이션 없이 새 속성을 추가할 수 있음.

- 읽기 캐시가 peer에 있어 read-heavy 워크로드에 강함.

**누가 쓰나**

Nubank의 거의 모든 백엔드 마이크로서비스가 Datomic을 쓴다(자체 인프라). 회계·법무·의료 도메인에서 점점 채택이 늘고 있다.

> Datomic은 "DB가 함수형이어야 한다"는 Rich Hickey의 주장의 결정체다. 비싸지 않다, 무료다. 그러나 사고방식의 전환이 필요하다.

8장 · XTDB 2.0 — bitemporal + SQL-first

XTDB(예전 이름 Crux)는 영국 JUXT 팀이 만든 bitemporal 데이터베이스다. 2026년 시점에 **XTDB 2.0**이 안정 버전이며, 1.x와 비교해 큰 변화가 있다.

**1.x → 2.0의 차이**

- 컬럼나 스토리지(Apache Arrow 기반)로 분석 쿼리 성능 대폭 향상

- **SQL을 1급 시민으로** — 더 이상 Datalog만 강요하지 않음

- 객체 스토리지(S3)에 데이터를 저장 — 비용 절감

-- XTDB 2.0 — 표준 SQL로 시간 여행

SELECT name, email

FROM users

FOR VALID_TIME AS OF DATE '2025-12-01'

WHERE name LIKE 'Min%';

-- 트랜잭션 시간과 valid 시간을 모두 지정

SELECT *

FROM users

FOR SYSTEM_TIME AS OF TIMESTAMP '2026-01-15 10:00:00'

FOR VALID_TIME AS OF DATE '2025-12-01';

Clojure에서도 호출 가능.

(require '[xtdb.api :as xt])

(xt/q node

'(from :users [name email]))

;; SQL도 동등

(xt/q node "SELECT name, email FROM users")

**왜 XTDB인가 vs Datomic**

- XTDB는 **SQL 호환**이 강점. PostgreSQL 사용자가 갈아타기 쉽다.

- Datomic은 **Datalog 우선**이며 더 깊은 그래프 쿼리에 강하다.

- XTDB 2.0의 컬럼나 스토리지는 분석 워크로드(OLAP)에 강하다.

- Datomic은 transactional 워크로드(OLTP)에 더 최적화.

**Datalevin과 Datahike**

임베디드/온디바이스 시나리오. Datalevin은 LMDB 기반 임베디드 Datalog DB. Datahike는 IPFS도 백엔드로 쓸 수 있는 분산 친화 Datomic-like DB. 모바일이나 Electron 앱에 묻어 쓰기 좋다.

9장 · next.jdbc · HoneySQL — 모던 SQL 스택

Datomic이나 XTDB가 모든 시나리오에 맞는 건 아니다. 기존 PostgreSQL·MySQL을 그대로 써야 할 때가 많다. 2026년 Clojure의 표준 JDBC 라이브러리는 **next.jdbc**이고, SQL DSL은 **HoneySQL**이다.

**next.jdbc 기본**

(require '[next.jdbc :as jdbc])

(def db {:dbtype "postgresql"

:dbname "myapp"

:user "postgres"

:password "secret"})

;; 쿼리

(jdbc/execute! db ["SELECT id, name FROM users WHERE id = ?" 42])

;; => [{:users/id 42 :users/name "Min-yong"}]

;; 트랜잭션

(jdbc/with-transaction [tx db]

(jdbc/execute! tx ["INSERT INTO users (name) VALUES (?)" "New User"])

(jdbc/execute! tx ["INSERT INTO accounts (user_id, balance) VALUES (?, ?)"

42 0]))

next.jdbc는 clojure.java.jdbc의 후속이며, 더 빠르고 더 작은 API다. 결과를 자동으로 키워드 키 맵으로 변환한다.

**HoneySQL — SQL을 데이터로**

(require '[honey.sql :as sql])

(sql/format

{:select [:id :name :email]

:from [:users]

:where [:and

[:= :status "active"]

[:> :age 18]]

:order-by [[:created-at :desc]]

:limit 10})

;; => ["SELECT id, name, email FROM users

;; WHERE status = ? AND age > ? ORDER BY created_at DESC LIMIT ?"

;; "active" 18 10]

EDN 맵으로 SQL을 표현한다. 동적으로 조건을 합치거나, 일부 절을 떼서 함수로 만들기 쉽다. ORM이 아니라 **데이터 우선 SQL 생성기**다.

10장 · Ring · Compojure · Reitit — HTTP 서버 3대장

Clojure 백엔드는 거의 모두 **Ring**을 베이스로 한다. Ring은 HTTP 요청/응답을 단순한 맵으로 표현하는 추상화다. 위에 여러 라우팅 라이브러리가 얹힌다.

**Ring 기본**

요청은 맵, 응답도 맵, 핸들러는 함수.

(defn handler [request]

{:status 200

:headers {"Content-Type" "text/plain"}

:body "Hello, world"})

;; jetty 서버로 실행

(require '[ring.adapter.jetty :as jetty])

(jetty/run-jetty handler {:port 3000})

미들웨어는 핸들러를 감싸는 고차 함수.

(defn wrap-logging [handler]

(fn [request]

(println "Request:" (:uri request))

(handler request)))

(jetty/run-jetty (wrap-logging handler) {:port 3000})

**Compojure — 고전 라우터**

(require '[compojure.core :refer [defroutes GET POST]])

(defroutes app

(GET "/" [] "Home")

(GET "/users/:id" [id] (str "User " id))

(POST "/users" req (create-user req)))

작은 앱에는 충분하지만, 큰 앱에서는 라우트 정의가 코드라 정적 분석이 어렵다.

**Reitit — 데이터 우선 라우터**

(require '[reitit.ring :as ring]

'[reitit.coercion.malli :as rcm])

(def app

(ring/ring-handler

(ring/router

[["/api"

["/users"

{:get {:handler list-users

:parameters {:query [:map [:limit int?]]}}

:post {:handler create-user

:parameters {:body [:map [:name string?] [:email string?]]}}}]

["/users/:id"

{:parameters {:path [:map [:id int?]]}

:get {:handler get-user}}]]]

{:data {:coercion rcm/coercion

:middleware [...]}})))

라우트가 **데이터**다(벡터+맵). 미들웨어, 입력 검증(coercion), OpenAPI 스펙 생성을 자동화할 수 있다. 2026년 신규 API 프로젝트 ~60%가 Reitit를 택한다.

**Pedestal**

Cognitect가 만든 대안. 인터셉터 체인 모델로 비동기·스트리밍을 1급으로 다룬다. Reitit보다 학습 곡선이 가파르지만, 복잡한 워크플로(예: SSE, 큰 파일 업로드)에 강하다.

11장 · Aleph · Manifold · core.async — 비동기와 스트림

Clojure의 동시성 모델은 세 축으로 나뉜다.

1. **core.async** — Go 채널 스타일. CSP 모델.

2. **Manifold** — 디퍼드(deferred)와 스트림. 더 함수형 친화.

3. **Aleph** — Netty 위의 비동기 HTTP/TCP 서버. Manifold를 쓴다.

**core.async**

(require '[clojure.core.async :as async :refer [go chan <! >!]])

(let [c (chan 10)]

(go (>! c "hello")

(>! c "world"))

(go (println (<! c))

(println (<! c))))

`go` 블록은 가벼운 코루틴, `<!`/`>!`는 채널에서 받고 보내는 연산. JVM 위에서 Go 같은 코드가 돈다.

**Manifold**

(require '[manifold.deferred :as d]

'[manifold.stream :as s])

;; deferred는 promise + future의 일반화

(def result (d/deferred))

(d/chain result inc inc inc) ; 함수 체이닝

(d/success! result 1) ; => 4

;; stream은 비동기 시퀀스

(def s (s/stream))

(s/consume #(println "got:" %) s)

(s/put! s 42) ; => "got: 42" 출력

**Aleph 서버**

(require '[aleph.http :as http])

(defn handler [req]

;; deferred를 반환하면 Aleph가 비동기로 처리

(d/future

(Thread/sleep 100)

{:status 200 :body "done"}))

(http/start-server handler {:port 3000})

Aleph는 Netty 위에 얹혀 있어 한 서버에서 수만 동시 연결을 다룬다. 웹소켓, SSE, gRPC도 자연스럽다.

> core.async가 Go의 채널이라면, Manifold는 Scala의 Future + Akka Stream의 Clojure 표현이다. 둘은 보완 관계이며 한 앱에서 같이 써도 된다.

12장 · Spec · Malli · Schema — 검증의 세 갈래

Clojure는 동적 타입이지만, 데이터 형태(shape)를 검증할 도구가 풍부하다. 세 라이브러리가 경쟁한다.

**clojure.spec — 공식 답**

(require '[clojure.spec.alpha :as s])

(s/def :user/email (s/and string? #(re-matches #".+@.+" %)))

(s/def :user/age (s/and int? #(<= 0 % 150)))

(s/def :user/user (s/keys :req-un [:user/email :user/age]))

(s/valid? :user/user {:email "min@example.com" :age 30})

;; => true

(s/explain :user/user {:email "bad" :age 30})

;; => :email failed: re-matches predicate

`s/keys`로 맵 형태를 정의하고, `s/and`/`s/or`로 조합. Spec은 **함수의 인자/반환값 명세**도 지원한다.

(s/fdef calc-tax

:args (s/cat :amount pos-int? :rate (s/and number? pos?))

:ret pos-int?)

`stest/instrument`로 활성화하면 함수 호출 시 자동 검증.

**Malli — 데이터 우선 + 빠름**

(require '[malli.core :as m])

(def User

[:map

[:email [:re #".+@.+"]]

[:age [:int {:min 0 :max 150}]]])

(m/validate User {:email "min@example.com" :age 30})

;; => true

(m/explain User {:email "bad" :age 30})

;; => {:errors [...]} 상세 에러

Malli는 **스키마가 데이터(EDN)** 라 직렬화·전송이 쉽고, Reitit의 입력 검증, OpenAPI 스펙 생성, 자동 문서화에 자연스럽게 연결된다. 2026년 신규 프로젝트의 다수가 Malli를 택한다.

**Plumatic Schema — 클래식**

가장 오래된 라이브러리. 매크로 기반이라 컴파일 타임 검증이 가능. 레거시 프로젝트에 많이 남아 있다.

**어떻게 고르나**

- 공식 도구로 가고 싶다 → Spec

- 데이터 우선 + Reitit·Malli 통합 → Malli

- 레거시 호환 → Schema

13장 · Mount · Integrant · Component — DI/라이프사이클

큰 시스템은 시작 순서(DB 연결 → 캐시 → HTTP 서버 → 백그라운드 작업)와 종료 순서가 중요하다. Clojure에는 이를 위한 세 라이브러리가 있다.

**Mount — 가장 단순**

(require '[mount.core :as mount])

(mount/defstate db

:start (open-connection "jdbc:...")

:stop (close-connection db))

(mount/defstate server

:start (start-server {:port 3000})

:stop (stop-server server))

(mount/start) ; 모두 시작

(mount/stop) ; 역순으로 종료

전역 상태를 쓰지만 매우 단순하다. 작은 프로젝트에 적합.

**Component — Stuart Sierra의 클래식**

(defrecord Database [config conn]

component/Lifecycle

(start [this] (assoc this :conn (open-connection config)))

(stop [this] (close-connection conn) (assoc this :conn nil)))

(def system

(component/system-map

:db (->Database db-config nil)

:server (component/using (->Server {}) [:db])))

의존성을 명시적으로 선언한다. 테스트에서 컴포넌트를 교체하기 쉽다.

**Integrant — 데이터 우선 Component**

(require '[integrant.core :as ig])

(def config

{:db/connection {:url "jdbc:..."}

:server/jetty {:db (ig/ref :db/connection) :port 3000}})

(defmethod ig/init-key :db/connection [_ {:keys [url]}]

(open-connection url))

(defmethod ig/init-key :server/jetty [_ {:keys [db port]}]

(start-server {:db db :port port}))

(def system (ig/init config))

(ig/halt! system)

설정이 EDN 데이터라 환경별 설정 파일로 분리 가능. Reitit와 자연스럽게 어울린다. 2026년 신규 프로젝트의 가장 흔한 선택.

14장 · 테스팅 — clojure.test부터 generative까지

**clojure.test — 표준**

(require '[clojure.test :refer [deftest is testing]])

(deftest user-creation-test

(testing "valid input creates user"

(is (= "Min-yong" (:name (create-user {:name "Min-yong"})))))

(testing "missing email throws"

(is (thrown? Exception (create-user {})))))

기본 내장. JUnit과 비슷한 느낌이지만 더 함수형.

**Kaocha — 모던 러너**

clojure.test 위에 얹는 러너. 컬러 출력, 워치 모드, 플러그인 시스템, JUnit XML 리포트.

clj -M:test # 또는 bb test

`tests.edn`으로 설정. CI에서 결정적인 출력을 내기 좋다.

**Eftest**

clojure.test 호환. 워치 모드와 병렬 실행에 강하다.

**clojure.test.check — Property-based testing**

(require '[clojure.test.check :as tc]

'[clojure.test.check.generators :as gen]

'[clojure.test.check.properties :as prop])

(def reverse-twice-is-identity

(prop/for-all [v (gen/vector gen/int)]

(= v (reverse (reverse v)))))

(tc/quick-check 100 reverse-twice-is-identity)

;; => 100개 임의 입력으로 검증

QuickCheck의 Clojure 포트. 입력을 무작위로 생성해 속성을 검증한다.

**clojure.spec.test — Spec과 통합**

(require '[clojure.spec.test.alpha :as stest])

(stest/check `calc-tax)

;; => spec fdef로 정의된 함수를 generative하게 테스트

Spec 명세가 있으면 자동으로 generative 테스트가 돈다.

15장 · 에디터 4파전 — Cursive · Calva · CIDER · Conjure

Clojure 개발은 **REPL이 핵심**이다. 코드를 파일로 저장하고 다시 시작하는 게 아니라, 실행 중인 REPL에 한 표현식씩 보내 즉시 평가한다. 그래서 에디터 선택이 다른 언어보다 더 결정적이다.

**Cursive — IntelliJ IDEA 플러그인**

가장 완성도 높은 상용 옵션. 코드 인텔리전스(자동완성, 리팩토링, 정적 분석)가 강력하다. 큰 프로젝트에서 정확한 navigation과 refactoring이 필요할 때 압도적. 개인 라이선스 연 99달러, 상용은 다른 요금. 무료 EAP 빌드도 있다.

**Calva — VS Code 확장**

무료, 오픈소스, 가장 많이 쓰는 에디터. REPL 통합, 패러디트(paredit) 편집, 인라인 평가 결과 표시, jack-in 자동화. VS Code 사용자라면 첫 선택. 2026년 Clojure 사용자의 ~45%가 Calva를 쓴다는 비공식 설문.

**CIDER — Emacs**

가장 오래되고 가장 강력. REPL 통합, 디버거, 트레이스, 매크로 단계별 확장 시각화까지 모두 1급. Emacs를 이미 쓰는 사람이라면 거의 디폴트.

**Conjure — Neovim**

Neovim 사용자를 위한 답. tmux-friendly. lightweight하지만 모든 핵심 기능을 갖춤.

**파일 → REPL 흐름**

Cursive·Calva·CIDER 모두 같은 흐름이다. 파일을 열고, "이 폼을 REPL에서 평가" 키(`Cmd-Enter`, `Cmd-Shift-Enter` 등)를 누르면 표현식이 REPL에 전송된다. 함수를 수정하고 다시 평가하면 즉시 새 정의가 살아 있는 시스템에 반영된다. 서버를 재시작하지 않는다.

> "REPL에 코드를 보내는 그 순간이 Clojure를 쓰는 가장 큰 이유다. 컴파일·실행·중단의 사이클이 없다. 코드는 항상 살아 있다." — Bruce Hauman, Figwheel 저자.

16장 · REPL 주도 개발 — 왜 LLM 시대에 가장 적합한가

REPL 주도 개발(REPL-driven development)은 Clojure 문화의 심장이다. 핵심 아이디어는 단순하다.

1. REPL을 항상 띄워 둔다.

2. 코드는 파일에 있지만, 실행은 REPL에서 한 표현식씩 한다.

3. 결과를 보고, 코드를 수정하고, 다시 평가한다.

4. 만족스러우면 그 코드를 파일에 두고 다음으로 넘어간다.

**왜 LLM 시대에 더 빛나는가**

LLM은 코드 블록을 생성한다. 사람은 그걸 검증해야 한다. 검증 방법은 두 가지.

- 전통적 방법: 파일에 붙여넣고, 빌드/테스트를 돌리고, 결과를 본다. 사이클이 길다(수십 초 ~ 수 분).

- REPL 방법: LLM이 생성한 표현식을 REPL에 바로 평가한다. 즉시 결과가 나온다. 잘못됐으면 다시 묻고, 다시 평가한다.

Clojure는 이 워크플로에 본질적으로 맞다. 데이터가 EDN으로 표현 가능하니 LLM이 생성한 데이터를 REPL에 그대로 붙여 평가할 수 있다. 매크로 시스템이 강해 LLM이 도메인 특화 코드를 짧게 표현할 수 있다.

**실전 LLM + REPL 워크플로**

;; LLM에게 "사용자 목록에서 30대 만 필터링하는 함수 작성"이라고 요청

;; LLM의 답을 REPL에 평가:

(defn users-in-30s [users]

(filter #(<= 30 (:age %) 39) users))

;; 즉시 테스트

(users-in-30s [{:name "A" :age 25}

{:name "B" :age 35}

{:name "C" :age 45}])

;; => ({:name "B" :age 35})

;; 잘 도네. 파일에 저장.

긴 빌드 사이클 없이 LLM 응답을 바로 검증할 수 있다. 2026년 Cursive·Calva 모두 LLM 응답을 REPL에 바로 보내는 단축키를 지원한다.

17장 · GraalVM Native Image — Clojure를 네이티브 바이너리로

GraalVM은 JVM 바이트코드를 ahead-of-time(AOT) 컴파일해 네이티브 실행 파일을 만든다. Clojure 프로그램을 GraalVM Native Image로 컴파일하면 시작 속도가 ~20ms로 떨어진다(JVM의 1~2초 vs).

**언제 유용한가**

- CLI 도구 (Babashka가 정확히 이 카테고리)

- AWS Lambda 같은 cold-start가 중요한 서버리스

- 작은 마이크로서비스 (예: 단일 헬스체크 엔드포인트)

**한계**

- 리플렉션, 동적 클래스 로딩에 제약이 있다. Clojure는 동적 언어라 일부 패턴이 안 된다.

- 빌드 시간이 매우 길다(분 단위).

- 메모리 풋프린트는 작지만, 피크 성능은 JIT보다 낮을 수 있다.

**실전 예**

Babashka 자체가 가장 큰 성공 사례. `bb` 바이너리는 GraalVM으로 컴파일된 약 80MB의 정적 바이너리. 시작 속도 ~20ms, 메모리 ~30MB. Python보다 가볍게 돈다.

자기 앱을 native-image로 만들 때는 `org.clj-easy/graal-build-time` 같은 헬퍼 라이브러리와 `clj.native-image` 같은 빌드 도구를 쓴다. JVM 호환성 옵션(--initialize-at-build-time 등)을 잘 설정해야 한다.

18장 · Nubank 사례 — 1억 사용자를 Clojure로

Nubank는 Clojure 세계 최대의 프로덕션 사례다. 브라질 발 디지털 은행으로 2026년 시점에 **1억 1,000만 고객, 마이크로서비스 5,000개 이상, 일 트랜잭션 수십억 건**을 처리한다. 그들의 백엔드는 거의 전체가 Clojure다.

**왜 Clojure를 택했나**

Nubank의 공동창업자이자 CTO인 Edward Wible의 설명(공개된 강연 다수에서). 세 가지 이유.

1. **함수형 + 불변 데이터** — 금융 데이터는 절대 임의 수정이 일어나면 안 된다. immutable이 자연스럽게 그 안전망을 준다.

2. **Datomic** — 모든 거래 이력을 bitemporal로 유지해야 한다. Datomic의 모델이 정확히 맞다.

3. **REPL 주도 개발** — 프로덕션 디버깅에 REPL을 띄워 라이브 데이터를 조사한다. 거래 사고가 났을 때 즉각 진단 가능.

**아키텍처 개요**

- 모든 마이크로서비스가 Clojure (일부 Kotlin/Go도 있음)

- Datomic이 메인 DB (자체 Pro 라이선스, AWS DynamoDB 백엔드)

- Kafka로 마이크로서비스 간 이벤트 스트림

- Pedestal/Aleph 기반 HTTP 서버

- Schema(레거시)와 Malli(신규)로 데이터 검증

- 자체 개발한 Pathom-like 그래프 쿼리 레이어

**팀 운영**

~2,000명의 엔지니어가 Clojure를 쓴다. 신규 채용 시 Clojure 경험은 필수가 아니다 — 자체 트레이닝 부트캠프로 가르친다. 함수형 사고가 있으면 빠르게 적응한다는 정책.

**성능**

- p99 응답 시간: 50ms 미만 (대부분 엔드포인트)

- 가용성: 99.99% 이상

- 한 마이크로서비스당 평균: 인스턴스 ~5개, 메모리 ~512MB

> "Clojure를 택한 게 사업에 가장 좋은 결정 중 하나였다. 단순함이 우리를 빠르게 했다." — Edward Wible, Nubank CTO.

19장 · 한국·일본 커뮤니티 — 어디까지 왔나

**Clojure Korea**

서울 중심으로 활동하는 커뮤니티. Slack 채널 `clojure-kr`, 정기 밋업, 페어 프로그래밍 세션. 김민용(Mun-yong Kim) 등 1세대 개발자들이 적극적으로 활동한다. 카카오·네이버 내부에서도 일부 팀이 Clojure를 쓴다(자세한 공개 자료는 적지만). 한국어 자료로는 위키북·인사이트의 번역서, 그리고 GitHub 한국어 튜토리얼이 있다.

**Clojure Tokyo / Clj-jp**

일본 커뮤니티는 한국보다 활동이 더 활발하다. 도쿄 정기 밋업, 후쿠오카·오사카 지부, 연 1회 컨퍼런스 `Clj-jp Conf`. Drip(주류), Cookpad(요리 레시피), Recruit 등 일부 일본 기업이 프로덕션에서 쓴다. 일본어 학습 자료가 풍부하다.

**아시아 컨퍼런스**

- **Clojure/conj** — 미국, 가장 큰 컨퍼런스 (연 1회)

- **Clojure/north** — 캐나다

- **re:Clojure** — 영국

- **EuroClojure** — 유럽

- **Clj-jp Conf** — 일본

2026년에는 한국에서도 작은 규모의 Clojure 컨퍼런스가 부활하려는 움직임이 있다.

20장 · 2026년에 시작하는 사람의 스택 추천

배경별로 정리한다.

**Java/Kotlin 출신**

- Clojure 1.12 + Leiningen → 익숙한 빌드 도구로 시작

- IntelliJ IDEA + Cursive

- Ring + Compojure(작은 앱) 또는 Reitit(중대형)

- PostgreSQL + next.jdbc + HoneySQL

- 첫 책: "Programming Clojure (4th edition)"

**JavaScript/TypeScript 출신**

- ClojureScript + shadow-cljs

- VS Code + Calva

- Reagent + re-frame(검증된 안정성) 또는 UIx 2(모던)

- npm 패키지를 그대로 가져다 쓰는 데서 시작

- 첫 책: "Learn ClojureScript" (무료, 온라인)

**Python/Ruby 출신**

- Babashka로 셸 스크립트부터 시작

- VS Code + Calva

- Datomic Pro 또는 SQLite + next.jdbc

- REPL 주도 개발 학습이 가장 큰 mind shift

- 첫 자료: 공식 사이트 "Getting Started"

**Lisp 경험자 (Scheme, CL)**

- 학습이 매우 빠르다

- Cursive 또는 Emacs+CIDER

- 함수형이 더 강조된다는 점만 적응

- 매크로 시스템은 Common Lisp과 비슷

**공통 학습 경로**

1. **REPL 켜고 한 줄씩 실험** — `lein repl` 또는 `clj`

2. **데이터 다루기 연습** — `map`, `filter`, `reduce`, `into`, `update-in`, `select-keys`

3. **상태 관리** — `atom`, `ref`, `agent`의 차이

4. **시퀀스 추상** — lazy seq, transducer

5. **매크로 — 마지막에**

> "Clojure를 일주일 만에 배웠다"고 말하는 사람이 있다. 사실 그게 가능하다. 그러나 그 후 6개월이 진짜 시작이다. 함수형 사고는 시간이 필요하다.

21장 · 자주 받는 의문에 답한다

**Q: 동적 타입이라 런타임에 깨지지 않나?**

A: 부분적으로 맞다. 그러나 Clojure는 데이터 형태를 EDN과 Spec/Malli로 명세화한다. 함수 경계에서 검증하고, 내부는 동적으로 다룬다. 큰 시스템에서도 잘 굴러간다 — Nubank가 증명한다.

**Q: 인재 풀이 작지 않나?**

A: 작다. 그러나 **남는 인재가 강하다**. Clojure 채용은 함수형 사고를 가진 사람을 거른다. 평균적으로 더 시니어한 팀이 된다는 보고가 일관된다. Nubank 채용 데이터: 이직률이 다른 핀테크 평균의 절반.

**Q: 채용이 어렵지 않나?**

A: 두 가지 답. (1) 다른 언어 출신을 채용해 가르치는 게 정답. Clojure는 빠르게 배울 수 있다. (2) Clojure를 쓴다는 사실 자체가 좋은 엔지니어를 끌어들이는 자석이 된다.

**Q: 성능은?**

A: JVM 위에서 도는 만큼 JIT 컴파일이 된 코드는 자바 수준. 핫 패스에서 박싱 회피, 타입 힌트 등 최적화 가능. Nubank의 p99 50ms는 일반 자바·Go 백엔드와 동등하거나 그 이상.

**Q: 학습 곡선?**

A: 가파른 부분이 두 군데. (1) 괄호와 prefix 표기법 적응 — 보통 1주일. (2) 함수형 사고 — 평균 3개월. 그 뒤로는 평탄하다.

**Q: 자바 라이브러리 호출은?**

A: 1급 시민. `(.method obj arg)` 또는 1.12부터 `Class/.method` 형태. 자바 라이브러리 거의 다 쓸 수 있다. JVM 호스트의 가장 큰 장점.

**Q: Clojure를 못 쓰는 경우는?**

A: 세 가지. (1) GC 일시정지를 절대 못 견디는 hard real-time. (2) 메모리 풋프린트가 매우 작아야 하는 임베디드 (단, Babashka로 일부 해결). (3) 팀 전체가 함수형에 거부감이 있을 때.

22장 · 2026년 이후의 방향

**예상되는 흐름**

1. **AI/LLM 통합 강화** — REPL 주도 개발과 LLM의 궁합이 좋아 IDE 통합이 깊어진다. Cursive·Calva가 Claude·Cursor 같은 도구와 더 가까워진다.

2. **ClojureScript의 부활** — UIx 2와 React Server Components의 만남, Bun·Deno 같은 새 런타임 지원이 작업 중.

3. **Babashka의 영역 확장** — 셸 스크립트 → CLI 도구 → 작은 서버까지. nbb·squint와 함께 점점 영역이 넓어진다.

4. **Datomic vs XTDB의 경쟁** — bitemporal DB 시장이 커지면서 두 진영이 발전을 가속.

5. **GraalVM Native Image의 안정화** — 더 많은 Clojure 라이브러리가 native-image 호환을 보장.

6. **WebAssembly 컴파일** — ClojureScript → WASM 실험이 진행 중. 브라우저 외 사용 가능성 열림.

**위험 요소**

- Rich Hickey의 후계 — Hickey는 2022년 Nubank에서 은퇴했다. Cognitect 팀이 잘 이어받고 있지만, 한 사람의 비전이 사라진 후 장기적 일관성이 시험대에 오른다.

- Datomic의 미래 — Cognitect가 Nubank에 인수된 후, Datomic의 오픈소스화가 어디까지 갈지 불투명.

- 다른 함수형 언어와의 경쟁 — Elixir·Gleam·Roc 등이 새로 떠오른다. Clojure는 어떻게 차별화를 유지할 것인가.

**낙관적 시나리오**

Nubank의 성공이 다른 핀테크·바이오·헬스 도메인에 퍼진다. 한국·일본 대기업에서도 점진 채택. ClojureScript의 React 통합이 더 매끄러워져 프런트엔드 시장에서 의미 있는 점유율 확보.

23장 · 결론 — Clojure가 살아남은 이유

20년 가까이 일관성을 지킨 언어는 많지 않다. Rich Hickey의 원칙 — "단순함은 쉬움보다 중요하다(simple is better than easy)" — 이 Clojure의 모든 결정에 깔려 있다. 그 결과 Clojure는 트렌드를 따르지 않고 자기 길을 갔다.

그게 살아남은 이유다. 핀테크, 의료, 회계, 컴플라이언스 — **정확성이 속도보다 중요한 도메인**에서 Clojure는 절대적이다. Nubank가 1억 사용자를 굴린다는 사실은 우연이 아니다.

2026년에 Clojure를 시작하는 사람에게 줄 한 마디.

> 빠르게 배우려고 하지 마라. **REPL을 띄워 두고, 한 표현식씩, 천천히 익혀라.** Clojure는 한 번에 배우는 게 아니라, 한 표현식씩 길러지는 언어다. 6개월 뒤에는 다른 언어로 못 돌아간다.

행운을 빈다. REPL을 켜고 시작하자.

References

1. Clojure 공식 사이트 — https://clojure.org

2. Clojure 1.12 Release Notes — https://github.com/clojure/clojure/blob/master/changes.md

3. Rich Hickey, "Simple Made Easy" — https://www.youtube.com/watch?v=SxdOUGdseq4

4. Rich Hickey, "Hammock Driven Development" — https://www.youtube.com/watch?v=f84n5oFoZBc

5. Babashka 공식 — https://babashka.org

6. Michiel Borkent, "Babashka: A native Clojure interpreter for scripting" — https://blog.michielborkent.nl

7. ClojureScript 공식 — https://clojurescript.org

8. shadow-cljs 공식 — https://github.com/thheller/shadow-cljs

9. re-frame 공식 — https://day8.github.io/re-frame

10. Reagent 공식 — https://reagent-project.github.io

11. Helix 공식 — https://github.com/lilactown/helix

12. UIx 2 공식 — https://github.com/pitch-io/uix

13. Pathom 3 공식 — https://pathom3.wsscode.com

14. Datomic 공식 — https://www.datomic.com

15. XTDB 2.0 공식 — https://xtdb.com

16. next.jdbc 공식 — https://github.com/seancorfield/next-jdbc

17. HoneySQL 공식 — https://github.com/seancorfield/honeysql

18. Reitit 공식 — https://github.com/metosin/reitit

19. Pedestal 공식 — https://pedestal.io

20. Aleph 공식 — https://github.com/clj-commons/aleph

21. Manifold 공식 — https://github.com/clj-commons/manifold

22. core.async 공식 — https://github.com/clojure/core.async

23. clojure.spec 공식 — https://clojure.org/about/spec

24. Malli 공식 — https://github.com/metosin/malli

25. Integrant 공식 — https://github.com/weavejester/integrant

26. Kaocha 공식 — https://github.com/lambdaisland/kaocha

27. clojure.test.check 공식 — https://github.com/clojure/test.check

28. Cursive 공식 — https://cursive-ide.com

29. Calva 공식 — https://calva.io

30. CIDER 공식 — https://docs.cider.mx

31. Nubank Engineering Blog — https://building.nubank.com.br/tag/clojure

32. Edward Wible, "Why Clojure?" — https://www.youtube.com/results?search_query=edward+wible+nubank+clojure

33. Clojure 2024 State of Clojure Survey — https://clojure.org/news/2024/05/01/state-of-clojure-2024

34. Clojure Korea Slack — https://clojurians.slack.com (#clojure-kr 채널)

35. Clj-jp 공식 — https://clj-jp.org

36. GraalVM Native Image — https://www.graalvm.org/native-image

37. clj.native-image — https://github.com/taylorwood/clj.native-image

38. Programming Clojure (4th ed) — https://pragprog.com/titles/shcloj4/programming-clojure-fourth-edition

39. Learn ClojureScript (무료 책) — https://www.learn-clojurescript.com

40. ClojureVerse 커뮤니티 포럼 — https://clojureverse.org

현재 단락 (1/669)

2026년 5월, 누군가 "요즘 Lisp을 쓰는 사람이 있나?"라고 묻는다면, 답은 명확하다. **있다, 그것도 아주 많다**. 브라질의 Nubank는 1억 1,000만 명의 고객...

작성 글자: 0원문 글자: 26,151작성 단락: 0/669