Clojure CLI

Clojure CLI (클로저 CLI)

Clojure 프로그램을 돌리려면 우선 JVM(Java Virtual Machine) 위에서 코드를 실행할 도구가 필요해요. 그 역할을 하는 게 바로 Clojure CLI예요. 커맨드라인 도구라서 터미널에서 clojureclj라고 입력해 쓰죠. 이 CLI는 deps.edn 파일을 읽어 프로그램에 필요한 의존성(dependency)을 구성하고 다운로드해서 JVM 클래스패스에 포함시켜 줘요. 이 글에서는 CLI의 실행 방식부터 옵션, 의존성·클래스패스 처리, 그리고 부가 프로그램(programs)과 도구(tools)까지 차례로 살펴볼게요.

출처: Clojure 공식문서

본문

설치

Clojure CLI는 다양한 방법으로 설치할 수 있어요. 자세한 방법은 설치 가이드에서, 버전 정보는 릴리스 페이지에서 확인할 수 있어요. 더 긴 튜토리얼을 원하면 가이드를, 아티팩트(artifact) 빌드가 필요하면 tools.build 가이드를 읽어 보세요.

어떤 버전의 CLI든 어떤 버전의 Clojure 언어든 함께 쓸 수 있어요. 일반적으로는 가장 최신 CLI 버전을 쓰는 게 최신 기능과 수정을 누릴 수 있어 좋아요. CLI 버전이 A.B.C[.D]라면 REPL에서 기본으로 쓰는 Clojure 버전A.B.C예요. 다만 의존성에서 언어 버전을 더 오래된 것(또는 더 새로운 것!)으로 명시하면 그 버전을 쓸 수 있어요.

사용법 (Usage)

CLI는 clojure 또는 clj로 호출해요. 대체로 둘은 서로 바꿔 쓸 수 있는데, clj에는 rlwrap이 포함되어 있어 키보드 편집 기능이 확장돼요. 특히 REPL에서 유용하죠. 이 참조는 REPL 예시에는 clj를, REPL이 아닌 예시에는 clojure를 사용할게요.

Clojure CLI를 실행하면 모든 경로(path)와 의존성, 메인 진입점(main entry point)을 결정한 뒤 JVM에서 프로그램을 호출해요. 실행의 주된 방식은 -X, -T, -M(또는 그 없음)에 따라 정해져요. 설정은 하나 이상의 deps.edn 파일과 커맨드라인 옵션이 합쳐져 정의돼요.

주요 커맨드

  • REPL 시작 (기본): clj [clj-opts] [-Aaliases]
  • 함수 실행 (-X): clojure [clj-opts] -X[aliases] my/fn? [kpath v ...] kv-map?
  • 도구 실행 (-T): clojure [clj-opts] -T[name|aliases] my/fn [kpath v ...] kv-map?
  • 메인 네임스페이스 또는 스크립트 실행 (-M): clojure [clj-opts] -M[aliases] [init-opts] [main-opts] [args]

참고로 이 문서는 원문의 화면에 보이는 옵션 인덱스 문법 블록을 생략하고, 각 옵션을 본문의 해당 절에서 설명하고 있어요.

REPL 시작

clj [clj-opts] [-Aaliases]

REPL을 실행하려면 clj를 인자 없이 호출하면 돼요. 이 명령은 어떤 디렉토리에서든 동작해요. deps.edn이 있든 없든 상관없죠. 프로젝트 디렉토리가 아니라면 사용되는 Clojure 버전은 루트 deps.edn의 org.clojure 의존성에 따른 버전(CLI 버전과 숫자가 일치)이나 설정 디렉토리의 유저 deps.edn(보통은 지정 안 함)에 따르게 돼요.

클래스패스나 JVM 프로퍼티를 바꾸는 앨리어스를 적용하려면 -A에 앨리어스 키워드를 하나 이상 이어 붙여 써요:

clj -A:test

clj -A:test:dev

함수 실행 (-X)

Clojure CLI는 프로젝트 클래스패스 위의 어떤 함수든 실행할 수 있어요. 단 그 함수는 키워드 인자를 맵 형태로 받아야 해요.

clojure [clj-opt*] -X[aliases] [a/fn] [kpath v]* kv-map?

함수 실행에는 결국 다음 정보가 필요해요.

함수와 인자는 앨리어스의 데이터 또는 커맨드라인에서 제공될 수 있어요.

앨리어스는 다음과 같은 arg map 키를 담을 수 있어요.

  • :exec-fn — 커맨드라인에 함수가 없을 때 쓸 함수 심볼
  • :exec-argsexec-fn 실행 시 포함할 키-값 맵
  • :ns-default — exec-fn을 해석할 때 쓸 기본 네임스페이스 심볼
  • :ns-aliases — exec-fn 해석 시 사용할 앨리어스 심볼→네임스페이스 심볼 맵

호출할 함수가 지정된 앨리어스에 정의되어 있다면 커맨드라인의 함수는 선택 사항이에요. 커맨드라인에 함수 심볼을 명시하면 앨리어스의 :exec-fn을 덮어쓰고, 앨리어스의 :ns-default:ns-aliases 기준으로 해석돼요.

:exec-args는 기본 맵을 이루고, 커맨드라인의 키-값과 마지막 kv-map이 그 순서대로 병합돼요.

커맨드라인의 키는 키워드일 수도, 중첩 키를 가리키는 벡터 키 경로(assoc-in에서 쓰는 방식)일 수도 있어요. 커맨드라인의 마지막 인자는 키-값을 담은 선택적 맵이에요. edn 키·값을 올바르게 지정하는 방법은 뒤의 키와 키 경로인용 quoting 절에서 자세히 다룰게요.

도구 실행 (-T)

도구(tool)는 프로젝트 클래스패스 외부에 있는 함수예요. -T로 도구 함수를 실행하는 건 -X로 프로젝트 함수를 실행하는 것과 같지만, 프로젝트 클래스패스가 포함되지 않는다는 점만 달라요.

clojure [clj-opt*] -T[name|aliases] a/fn [kpath v]* kv-map?

도구용 클래스패스를 만들 때는 프로젝트의 :deps:paths가 포함되지 않아요.

도구 의존성은 도구 앨리어스나 도구 이름을 통해 포함돼요. 도구는 로컬에 짧은 이름으로 설치해 사용할 수 있어요. 설치된 도구는 같은 유저 설정을 가진 어떤 프로젝트에서든 쓸 수 있죠. 자세한 내용은 도구 설치에서 다룰게요.

이름으로 도구를 실행하려면 -Tlinter처럼 -T 뒤에 도구 이름을, 앨리어스로 실행하려면 -T:linter처럼 앨리어스를(앨리어스는 항상 키워드예요) 붙이면 돼요.

-X와 달리 도구 함수는 커맨드라인에서 반드시 지정해야 하고, 도구 앨리어스나 설치된 도구 설정에는 지정할 수 없어요. 그 외에는 도구 함수와 인자를 지정하는 방식이 앨리어스와 커맨드라인 모두 -X와 동일해요.

메인 네임스페이스 또는 스크립트 실행 (-M)

-M exec-opt로 clojure.main을 호출할 수 있어요. -main 함수를 가진 네임스페이스를 호출하거나 Clojure 스크립트를 실행하는 방식이죠.

clojure [clj-opt*] -M[aliases] [main-opts]

-M 앨리어스는(제공되면) deps.edn에서 가져와 병합되어 arg map을 이뤄요. arg map은 클래스패스를 바꾸거나 :main-opts(문자열 메인 옵션 벡터)를 제공할 수 있어요. 사용 가능한 main-opts에 대한 자세한 내용은 clojure.main 페이지에서 확인할 수 있어요.

대표적인 사용 예는 이래요.

# 단일 표현식 실행:
clojure -M -e '(+ 1 1)'

# 메인 진입점이 있는 네임스페이스 실행:
clojure -M -m my.app

# 독립 Clojure 스크립트 실행
clojure -M script.clj

main opts는 앨리어스의 arg map 키 :main-opts로 제공할 수도 있어요. 앨리어스가 병합될 때 어떤 :main-opts가 들어오면 이전 앨리어스의 것을 대체해요. -M 뒤 커맨드라인의 추가 옵션은 병합된 앨리어스 arg map의 것 뒤에 덧붙여져요.

옵션 (Options)

-Aaliases-A는 하나 이상의 이어붙인 앨리어스를 받아요. 앨리어스는 항상 단순 또는 한정(qualified) 키워드예요. 예: -A:test, -A:test:perf/benchmark. -A는 모든 실행 커맨드와 쓸 수 있지만, REPL 실행에 쓸 수 있는 유일한 exec-opt이고 그게 가장 흔한 용도예요.

-X[aliases]-X는 선택적으로 이어붙인 앨리어스를 받아요(항상 키워드). -X exec-opt는 함수 실행을 뜻하고, -X 뒤의 모든 인자는 CLI가 아니라 실행되는 함수의 인자예요. 모든 clj-opts(-S, -P 등)는 커맨드라인에서 -X보다 앞에 와야 해요.

-Ttoolname, -T[aliases]-T는 도구 이름(항상 심볼, 키워드 아님) 또는 이어붙인 앨리어스(항상 키워드)를 받아요. -T exec-opt는 도구 실행을 뜻하고, -T 뒤의 모든 인자는 도구 함수의 인자예요. 모든 clj-opts는 -T보다 앞에 와야 해요.

-M[aliases]-M은 선택적으로 이어붙인 앨리어스를 받아요. -M exec-opt는 clojure.main 실행을 뜻하고, -M 뒤의 모든 인자는 clojure.main이 해석해요. 모든 clj-opts는 -M보다 앞에 와야 해요.

-P — 다른 exec-opt(-A, -X, -M, -T) 앞에 -P를 쓰면 의존성 전체를 확장하고 다운로드하며 클래스패스를 캐시하되, 실제로 함수·도구·메인 등을 실행하지는 않아요.

-Jopt-J로 프로그램에 전달할 JVM 옵션에 접두사를 붙여요(-J는 제거됨). 예: -J-Xmx1g, -J-XX:+HeapDumpOnOutOfMemoryError. -J는 프로그램을 실행하는 모든 모드(repl, -X, -T, -M)에서 쓸 수 있어요. JVM 옵션을 제공하는 다른 방법은 JVM 프로퍼티 절을 참고해요.

-Sdeps deps — 커맨드라인에서 추가 deps.edn 데이터 또는 deps.edn 파일 경로를 제공해요. 병합에서 마지막 deps 소스로 사용되고, 데이터는 커맨드라인에 맞게 인용해야 해요.

-Srepro — deps 소스에서 유저 deps.edn을 뺀다는 뜻이에요. 유저 개인 설정을 빼서 다른 사람에게도 동일하게 재현되는 명령을 만들 때 유용하죠.

-Spath — 클래스패스를 계산해 출력해요.

-Stree — 의존성 트리를 계산해 출력해요. 트리 출력에 대한 자세한 내용은 의존성 확장 페이지에서 확인할 수 있어요.

-Scp CP — 이 옵션을 쓰면 클래스패스를 계산하지 않고 주어진 클래스패스를 그대로 사용해요. 주로 테스트나 디버깅에서 유용해요. 일반적으로는 deps.edn 설정에 따라 CLI가 클래스패스를 계산(하고 캐시)하게 두는 게 좋아요.

-Sforce — 기존에 캐시된 클래스패스(있으면)를 stale로 표시해요. 클래스패스를 다시 계산하고 캐시해요.

-Sverbose — CLI가 찾고 사용한 환경과 경로 정보를 출력해요. 여러 설정·캐시 디렉토리의 위치를 디버깅할 때 주로 유용하죠. 이 플래그는 커맨드라인에 지정된 다른 실행을 바꾸지 않아서, 특정 커맨드의 캐시 파일 위치를 디버깅하는 데 쓸 수 있어요.

-Sthreads N — 기본적으로 deps 확장은 프로세서 수에 맞춰 크기가 정해진 스레드 풀을 사용해요. 이 설정으로 확장 중 사용할 스레드 수를 바꿀 수 있어요. 1로 설정하면 단일 스레드로 직렬 확장을 해요.

-Strace-Stree-X:deps tree가 출력하는 의존성 트리는 왜 특정 라이브러리(또는 버전)가 선택됐는지 디버깅하기에 충분한 경우가 많아요. 더 많은 정보가 필요하다면 이 플래그는 훨씬 큰 정보를 trace.edn 파일에 기록해요. 이를 tools.deps에 이슈를 등록할 때 Ask Clojure에 사용할 수 있어요.

--version, -version — Clojure CLI 버전을 stdout(--version) 또는 stderr(-version)로 출력하고 종료해요. CLI 버전이 기본 Clojure 버전을 결정하지만, 어떤 CLI 버전도 어떤 Clojure 버전이든 쓸 수 있고, Clojure 버전은 deps.edn에서 바꿀 수 있다는 점을 기억해 두세요. 자세한 버전·변경 내역은 tools 릴리스 페이지를 참고해요.

--help, -h, -? — 도움말을 콘솔에 출력해요. man clojure도 참고하세요.

앨리어스 (Aliases)

프로젝트 맥락에서 커맨드를 호출할 때는 커맨드라인에 인용하기 어려운 복잡한 데이터를 지정해야 하는 경우가 흔해요. Clojure 프로그래머는 그런 데이터를 Clojure 문법, 즉 edn으로 지정하는 것을 선호해요. deps.edn 형식은 임의의 Clojure 데이터를 정의하고, 그 데이터에 앨리어스로 이름을 붙일 수 있게 해줘요. 앨리어스는 간단히 edn 데이터에 이름을 붙인 키워드예요.

CLI의 각 실행 모드에는 많은 설정 옵션(arg map)이 있어요. 이들은 앨리어스로 edn 맵에 정의되고, -A, -X, -T, -M에서 앨리어스를 통해 커맨드라인에서 선택돼요. 아래는 모든 arg map 키 목록이에요 — 별도로 표시되지 않는 한 모든 실행 모드에서 유효해요.

  • 프로젝트 의존성 수정자
    • :extra-deps — 루트 deps에 추가할 lib→coords 맵
    • :override-deps — 루트 deps의 deps를 대체할 lib→coords 맵
    • :default-deps — 루트 또는 전이 deps에서 coord가 nil일 때 쓸 lib→coords 맵
  • 클래스패스 수정자
    • :extra-paths — 기본 경로 앞에 붙일 문자열 경로 벡터(또는 그에 대한 키워드 앨리어스)
    • :classpath-overrides — 클래스패스의 lib를 대체할 lib→문자열 경로 맵
  • 도구 deps와 경로 (주로 -T에서 사용)
    • :replace-deps (동의어: :deps) — 프로젝트 deps를 대체할 lib→coords 맵
    • :replace-paths (동의어: :paths) — 프로젝트 경로를 대체할 경로 문자열 벡터
  • JVM 옵션
    • :jvm-opts — JVM 옵션으로 전달할 문자열 벡터
  • 네임스페이스 해석 (주로 -X와 -T에서 사용)
    • :ns-aliases — 심볼(:exec-fn 등)을 해석하는 데 쓰는 앨리어스 심볼→네임스페이스 심볼 맵
    • :ns-default — 한정되지 않은 심볼(:exec-fn 등)의 기본 네임스페이스
  • 함수 실행 (-X와 -T만)
    • :exec-fn-X로 실행할 함수
    • :exec-args-X에 전달할 함수 인자(커맨드라인에서 덮어쓸 수 있음)
  • main (-M만)
    • :main-opts — clojure.main에 전달할 문자열 인자 벡터

여러 앨리어스를 주면 앨리어스 arg map의 키들이 다음 의미로 병합돼요(이어붙인 앨리어스의 순서대로):

  • :extra-deps — 병합
  • :override-deps — 병합
  • :default-deps — 병합
  • :extra-paths — 이어붙이고 중복 제거
  • :classpath-overrides — 병합
  • :replace-deps / :deps — 병합
  • :replace-paths / :paths — 이어붙이고 중복 제거
  • :jvm-opts — 이어붙임
  • :ns-aliases — 병합
  • :ns-default — 교체 (마지막이 이김)
  • :exec-fn — 교체 (마지막이 이김)
  • :exec-args — 맵이면 병합, 아니면 교체
  • :main-opts — 교체 (마지막이 이김)

커스텀 용도의 앨리어스

위 앨리어스 키들은 CLI 실행에 의미가 있지만, 어떤 용도로든 앨리어스를 정의할 수 있어요. 설정이 필요한 커스텀 도구를 만들 때는 잘 알려진, 네임스페이스화된 앨리어스나 앨리어스 키를 도구가 쓰도록 정의하는 게 좋은 관행이에요. deps.edn 파일에 최상위 키를 함부로 추가하는 일은 피해 주세요. 프로그램적 도구에서 항상 사용 가능하지 않을 수 있어요.

CLI가 실행하는 프로그램에는 실행을 위한 런타임 basis가 모든 앨리어스 데이터와 함께 주어져요. Clojure 1.12에서 추가된 clojure.java.basis API로 프로그램 런타임에 앨리어스 데이터를 가져올 수 있어요.

네임스페이스 해석

exec-opt나 arg map의 심볼(:exec-fn 같은 것)은 다음 규칙으로 해석돼요.

  • 함수가 한정되지 않으면 arg map의 :ns-default 키의 네임스페이스를 사용(없으면 오류)
  • 함수가 한정되고, 그 한정자가 :ns-aliases의 앨리어스라면 그 네임스페이스 사용
  • 그 외에는 완전히 한정된 함수 심볼 사용

의존성 (Dependencies)

각 의존성은 deps.edn 형식으로 lib과 coord(좌표)와 함께 정의돼요. 여러 deps는 맵으로 합쳐져요(앨리어스 arg map 키도 같은 형식을 사용).

deps.edn 소스

Clojure CLI는 최대 네 개의 deps edn 소스를 합쳐 사용할 경로·의존성·앨리어스 맵을 구성해요.

  • 루트 deps — tools.deps 라이브러리에 내장된 리소스로 정의. Clojure 자체만 의존성(버전은 CLI 버전과 일치)으로 두고, :deps:test 두 내장 앨리어스를 정의. Maven Central과 Clojars 두 내장 Maven 저장소 포함.
  • 유저 deps (선택)유저 설정 디렉토리의 deps.edn. 파일은 빈 상태로 시작하지만 프로젝트를 넘나드는 추가 설정과 도구가 정의될 수 있어요.
  • 프로젝트 deps (선택) — 현재 디렉토리(프로젝트 디렉토리)의 deps.edn
  • 추가 deps (선택)-Sdeps로 커맨드라인에 제공

deps 소스는 위에 나열된 순서대로 단일 마스터 deps edn으로 병합되며, 다음 예외가 있어요:

  • -T 도구 실행 — 프로젝트 :deps는 제거되고, 프로젝트 :paths["."]로 교체
  • -Srepro — 유저 :deps는 무시

병합은 기본적으로 merge-with merge와 같아요. 단 :paths는 마지막 deps 소스의 :paths만 사용해요.

클래스패스 (Classpath)

JVM 클래스패스는 일련의 루트(디렉토리 경로 또는 jar 파일 경로)로 이뤄져요. 클래스(와 Clojure 파일)는 패키지·네임스페이스를 통해 클래스패스 루트에 대한 상대 경로로 연결돼요. 예를 들어 java.lang.String 클래스는 java/lang/String.class에서, clojure.set 네임스페이스는 clojure/set.class(AOT), clojure/set.clj, clojure/set.cljc에서 찾을 수 있어요. JVM이 이 파일 중 하나를 로드할 필요가 있을 때 각 루트에서 상대 경로를 검색해 찾으면 로드해요.

Clojure CLI는 다음에 기반해 클래스패스를 계산해요.

결국 이 모든 것이 다음으로 합쳐져요.

  • 프로젝트 경로
  • deps (외부 라이브러리와 그 전이 의존성)

프로젝트 경로

deps와 앨리어스 인자의 병합이 끝나면 deps.edn의 :paths와 앨리어스의 :extra-paths가 있어요. 둘 다 벡터이고 그 순서는 유지돼요. extra paths가 항상 paths보다 앞에 와서, 앨리어스가 프로젝트 설정을 덮어쓸 수 있어요.

프로젝트 경로와 extra-paths 모두 현재 디렉토리 기준으로 해석되며, 프로젝트 안쪽 경로만 가리켜야 해요(상위·형제 디렉토리 금지). 현재 프로젝트 밖을 가리키면 경고가 나오지만, 이 지원은 deprecated라 나중에 제거될 거예요(대신 로컬 deps를 사용).

의존성 확장

deps가 병합되면 최상위 의존성 집합이 있고, 이들은 의존성 그래프의 루트가 돼요. 그래프는 위에서 아래로 탐색되고 각 의존성은 적절한 프로큐어러(procurer)(Maven, Git, local)로 차례로 확장돼요. 사이클은 감지되어 다시 검사되지 않아요.

같은 라이브러리의 여러 버전이 발견되면 버전 선택 과정이 일어나요. 의존성 확장 페이지에 이 과정의 자세한 내용이 있지만, 일반적으로 라이브러리의 가장 새로운 버전이 사용돼요. 다만 최상위 의존성 버전은 항상 수정 없이 사용돼요 — 특정 버전을 지정하거나 충돌을 해결해야 한다면 그 버전을 최상위 의존성에 설정하면 돼요.

의존성은 그래프 위에서부터 깊이 순서로 정렬되고, 각 레벨에서 lib 이름으로 알파벳순 정렬돼요.

:extra-deps, :override-deps, :default-deps 같은 arg map 수정자에 대한 자세한 내용은 deps.edn 참조 페이지를 참고해요.

클래스패스 구성

클래스패스에는 다음이 들어가요.

  • Extra paths (프로젝트 기준) — 마지막으로 지정한 앨리어스의 선언 순서대로
  • Source paths (프로젝트 기준) — 마지막으로 지정한 deps의 선언 순서대로
  • Dependency paths (보통 절대 경로) — 적절한 프로큐어러 다운로드 위치의 jar나 디렉토리. 의존성은 그래프 위에서 깊이 순서로, 그다음 lib 이름으로 알파벳순 정렬

클래스패스는 arg map 키 :classpath-overrides로 더 수정될 수 있어요(deps.edn 참조). 계산된 클래스패스는 -Spath로 출력할 수 있어요.

JVM 프로퍼티

JVM 프로퍼티에는 여러 소스가 있어요.

  • 하드코딩된 옵션: -XX:-OmitStackTraceInFastThrow
  • $JAVA_OPTS 환경 변수
  • 앨리어스 arg map 키 :jvm-opts (마스터 deps에서 앨리어스 간 병합됨)
  • 커맨드라인 -J 옵션

모든 JVM 커맨드라인 옵션은 위 순서대로 이어붙여져요. 대부분의 경우 커맨드라인에서 나중에 온 JVM 옵션이 이전 설정을 덮어쓰지만, 어느 경우든 이어붙인 옵션의 의미는 JVM의 의미를 따라가요. 옵션의 중복 제거나 교체는 없어요.

CLI 커맨드

cljclojure 커맨드는 호스트별 스크립트로 다음 일을 해요.

  1. CLI 인자를 파싱
  2. (캐시되지 않았다면) JVM을 띄워 클래스패스와 기타 설정을 계산·캐시
  3. JVM을 띄워 exec-opt -X, -T, -M가 지정한 대로 유저 프로그램을 실행

2단계는 Clojure CLI 설치에 포함된 uberjar로 수행돼요. 일반적으로 그 JVM의 클래스패스나 설정을 제어하지는 않아요(일부 예외는 환경 변수 참조).

Java

Clojure CLI를 쓸 때는 Java를 설치하고 몇 가지 방법 중 하나로 사용 가능하게 해야 해요. Java 8 이상이 요구되고, 아무 Java 배포판이든 동작해요.

Java는 다음 순서로 찾아요.

못 찾으면 CLI가 오류 메시지와 함께 멈춰요. clj -h가 성공하면 Java 실행 파일이 찾아진 거예요.

디렉토리와 캐시

Clojure CLI가 쓰는 중요한 디렉토리가 몇 개 있어요. 이 절에서는 그것들이 어떻게 계산되는지 자세히 다룰게요.

프로젝트 디렉토리

프로젝트 디렉토리는 현재 디렉토리예요. 프로젝트 디렉토리에 deps.edn 파일이 있으면 그 파일이 프로젝트 deps 소스로 사용돼요. 원격 프로젝트 디렉토리 맥락에서 실행하는 옵션은 없어요.

설정 디렉토리

설정(config) 디렉토리에는 다음이 들어가요.

설정 디렉토리는 다음과 같이 계산돼요.

  • $CLJ_CONFIG가 설정되면 그 경로 사용
  • $XDG_CONFIG_HOME이 설정되면 $XDG_CONFIG_HOME/clojure 사용
  • 그 외에는 $HOME/.clojure 사용

설정 디렉토리가 없으면 만들고 다음 파일을 복사해요.

  • deps.edn — 기본 유저 deps.edn (사실상 빈 상태)
  • tools/tools.edn — 도구를 관리하는 내장 도구 “tools”
캐시 디렉토리

CLI 실행마다 계산된 클래스패스와 기타 파일을 저장할 캐시 디렉토리를 사용해요.

캐시 디렉토리는 다음과 같이 계산돼요.

  • 현재 디렉토리에 프로젝트 deps.edn이 있고 현재 디렉토리가 쓰기 가능하면 ./.cpcache 사용
  • 그 외에는 설정 디렉토리.cpcache 사용

캐시 디렉토리의 파일은 이미 계산된 클래스패스를 쓸 때 시작 시간을 개선하기 위한 캐시예요. 일반적으로 이 캐시는 절대 stale하지 않지만, 특정 커맨드에서 -Sforce로 강제 재계산을 하거나 불확실하면 캐시 디렉토리를 rm하면 돼요.

새 CLI 버전을 설치하면 캐시 키 형식이 바뀐 경우 때때로 캐시가 무효화되어, 이전에 실행한 커맨드가 클래스패스를 다시 계산하기도 해요.

Clojure CLI는 캐시 디렉토리의 파일을 절대 삭제하지 않아요. 주기적으로 정리하는 건 사용자 몫이죠. 프로젝트 .gitignore.cpcache/를 포함시키는 게 좋은 관행이에요 — 거기 있는 어떤 것도 다른 프로젝트 사용자와 공유할 가치가 없어요.

환경 변수

다음 환경 변수가 CLI 실행에 영향을 줄 수 있어요(대부분 이 페이지其他地方에서 더 자세히 설명).

  • CLJ_CONFIG — 유저 설정 디렉토리. 유저 deps.edn, 도구 설정, 프로젝트 deps.edn이 없는 커맨드의 cpcache를 저장 (기본 = ~/.clojure)
  • XDG_CONFIG_HOME — 이 표준 변수가 설정되면 $XDG_CONFIG_HOME/clojure를 유저 설정 디렉토리로 사용
  • CLJ_CACHE — 유저 캐시 디렉토리 (기본 = <config-dir>/.cpcache)
  • XDG_CACHE_HOME — 이 표준 변수가 설정되면 $XDG_CACHE_HOME/clojure를 유저 캐시 디렉토리로 사용
  • CLJ_JVM_OPTS — 클래스패스 빌드 과정의 내부 호출에 포함할 JVM 옵션. 내부 아티팩트 다운로드에 쓰는 자체 서명 인증서의 truststore 같은 것을 제공할 때 유용
  • JAVA_CMD — 사용할 Java 실행 파일 경로
  • JAVA_HOME$JAVA_CMD도 path의 java도 없으면 $JAVA_HOME/bin/java 시도
  • JAVA_OPTS — 실행되는 유저 커맨드에 포함할 JVM 옵션. 캐시되지 않음. -J 커맨드라인 파라미터와 :jvm-opts보다 먼저 포함됨
  • AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY 및 기타 AWS 환경 변수 — S3 기반 Maven 저장소 접근에 사용
  • GITLIBS — gitlibs 저장 디렉토리 경로 (기본 = ~/.gitlibs)
  • GITLIBS_COMMAND — 실행할 git 커맨드 (기본 = git)
  • GITLIBS_DEBUGtrue로 설정하면 실행 중인 모든 git 커맨드 출력
  • CLOJURE_CLI_ALLOW_HTTP_REPOtrue로 설정하면 http:// 저장소 URL 허용 (의존성 다운로드가 중간자 공격에 노출될 수 있음)

키와 키 경로

-X 또는 -T exec-opt로 커맨드라인에 키-경로/값 쌍을 제공할 수 있어요. 키-경로는 단일 키 또는 중첩 키를 가리키는 키 벡터(assoc-in처럼)예요. 각 키-경로는 원래 :exec-args 맵에 assoc-in하는 데 쓰여 그 값을 덮어써요.

# 최상위 키 덮어쓰기
clj -X:my-fn :val 789

# 중첩 키 덮어쓰기
clj -X:my-fn '[:my :data]' 789

키-경로/값 쌍과 키 경로를 커맨드라인에 전달하는 것 외에도, 값 매핑을 제공하는 선택적 맵을 마지막 인자로 전달할 수 있어요. 이 맵은 앞서 제공된 키-경로/값 매핑과 병합되고 어쩌면 덮어쓸 수도 있어요.

# my-fn 인자 증강
clj -X:a-tool my-fn :val 789 '{:val2 123}'

# my-fn 인자 덮어쓰기
clj -X:a-tool my-fn :val 789 '{:val 123}'

# 맵 하나만 (kv 없음) my-fn 인자 제공
clj -X:a-tool my-fn '{:val 789}'

인용 (Quoting) 키와 값

커맨드라인의 키와 값은 edn으로 읽혀요. 다음 데이터는 인용 없이 쓸 수 있어요.

  • 숫자 — 123, 12.4
  • 불리언 — true, false
  • nil — nil
  • 심볼 — name, foo/bar
  • 키워드 — :id, :company/name

다음 데이터 타입은 단일 인용부호로 감싸야 해요.

  • 문자열 — '"hi there"' — 셸용 단일 인용부호와 edn 문자열로 읽기 위한 이중 인용부호를 모두 사용
  • 벡터 — '[1 2 3]'
  • 맵 — '{:a 1, :b 2}'
  • 집합 — '#{:a :b}'
  • 리스트 — '(1 2 3)'

Windows에서 WSL2 셸은 위 조언을 따르면 되지만, clojure.exe를 쓰면 문자열 값에 추가 이스케이프 인용이 필요해요. Windows 프로그램 인자의 커맨드라인 변환, 인용, 단어 분할의 조합이 매우 복잡하기 때문이에요.

최상위 문자열 값을 전달할 때 공백이 없으면 '\"str\"'를, 공백이 있으면(또는 없으면) '"""str value"""'를 사용해요.

PS D:> clj -X clojure.core/prn :string1 '\"no-spaces\"' :string2 '"""has spaces"""'
{:string1 "no-spaces", :string2 "has spaces"}

다른 컬렉션 안에 중첩된 문자열 값은 공백이 있으면 이중 인용부호, 없으면 삼중 인용부호를 사용해요.

PS D:> clj -X clojure.core/prn :val '{:s1 """nospaces""" :s2 ""has spaces""}'
{:val {:s1 "nospaces", :s2 "has spaces"}}

프로그램 (Programs)

Clojure CLI는 독자적인 클래스패스를 가진 다른 라이브러리의 프로그램(함수)에 접근할 수 있게 설계돼요. 이 기능은 루트 deps.edn의 내장 :deps 앨리어스로 확장된 기능을 제공하는 데 활용되는데, 이 앨리어스가 tools.deps.cli(API)를 제공해요.

의존성 목록

clj -X:deps list

클래스패스에 선택된 모든 전이 의존성의 정렬된 목록과 라이선스 정보(찾으면)를 출력해요. 추가 옵션으로 앨리어스를 선택하거나 다른 클래스패스 수정을 하거나 출력 정보를 바꿀 수 있어요. API 문서 참조.

의존성 트리

clj -X:deps tree

의존성 확장 동안 결정된 포함/제외 정보와 함께 의존성 트리를 출력해요. 추가 옵션으로 앨리어스나 다른 클래스패스 수정을 선택하거나 출력 정보를 바꿀 수 있어요.

예를 들어 :test 앨리어스의 deps 트리를 출력하려면:

clj -X:deps tree :aliases '[:test]'

API 문서 참조.

앨리어스 목록

clj -X:deps aliases

현재 deps 환경에 기반해 커맨드라인에서 사용 가능한 모든 앨리어스를 출력해요. 추가 옵션으로 앨리어스나 다른 클래스패스 수정을 선택할 수 있어요. API 문서 참조.

도움 함수

help/dochelp/dir 함수는 도구를 어떻게 쓸 수 있는지 들여다보는 함수예요. :deps 앨리어스는 프로젝트 클래스패스를 포함하지 않기 때문에, 이들은 현재 자신의 프로젝트에서 함수를 실행할 때는 유용하지 않아요.

  • -X:deps help/doc — 키 :ns로 주어진 함수(또는 추가 키 :fn으로 지정된 함수)의 doc 문자열과 파라미터 목록을 보여줌. 둘 다 없으면 :ns-default 사용
  • -X:deps help/dir — 키 :ns로 주어진(없으면 :ns-default) 네임스페이스의 공개 함수를 출력

내장 tools 도구의 :ns-default 함수 집합을 나열하는 예:

clojure -A:deps -Ttools help/dir

앨리어스의 함수 집합을 나열하는 예:

clojure -X:deps:my-alias help/dir

help 네임스페이스 자신의 doc 문자열 출력(help:deps:ns-aliases 맵에 정의되어 있어요):

clojure -X:deps help/doc :ns help

API 문서 참조.

Prep 라이브러리

Clojure 소스가 있는 소스 lib는 그것을 쓰는 프로젝트의 클래스패스에 즉시 추가될 수 있어요. 하지만 일부 소스 lib는 Java 컴파일이 필요하다든지, 리소스 파일을 복사·교체해야 한다든지 하는 이유로 추가되기 전에 준비(prep)가 필요해요. Clojure CLI는 이제 준비가 필요한 프로젝트를 감지해서, prep 단계가 완료되지 않으면 소스에서 프로그램이 실행되지 못하게 해요.

라이브러리가 준비를 필요로 한다면 deps.edn에 :deps/prep-lib 키를 추가해요.

{:paths ["src" "target/classes"]
 :deps/prep-lib
 {:ensure "target/classes"
  :alias :build
  :fn compile-java}}

:deps/prep-lib 아래의 키는:

  • :ensure — 디렉토리 존재 여부가 prep 필요 여부를 결정 (존재하면 prep가 된 것)
  • :alias — prep 동안 -T로 호출할 앨리어스
  • :fn — prep 동안 -T로 호출할 함수

따라서 deps.edn에는 지정된 fn을 실행할 수 있는 앨리어스도 있어야 해요. 호출 가능한 함수로 빌드 스크립트를 정의하는 방법은 tools.build 가이드에서 확인할 수 있어요.

이 git 라이브러리를 의존성으로 추가하고 프로그램을 실행하려 하면, CLI는 다운로드하고 준비가 필요하며 준비되지 않았음을(“target/classes” 경로가 없음) 감지하고 종료해요.

의존성 트리에서 lib를 찾아 준비하려면 내장 :deps 앨리어스가 제공하는 prep 도구를 쓸 수 있어요.

clj -X:deps prep

prep 태스크는 의존성 확장의 모든 lib를 찾아, 소스 lib이면서 prep가 필요하고(:deps/prep-lib 키 기준) 아직 prep되지 않은 lib(:deps/prep-lib 맵의 :ensure 디렉토리 기준)를 찾아요. 그 lib들에 대해 지정된 앨리어스와 함수로, 마치 clj -T:<alias> <fn>처럼 커맨드를 실행해요.

라이브러리가 한 번 prep되면, 이 git 라이브러리 버전의 다른 사용자가 다시 prep할 필요가 없어요.

참고: Clojure 코드를 컴파일하는 prep 단계를 써야 할까요? 일반적으로는 No예요. 이 git 라이브러리를 사용하는 그 기계의 모든 사용자는 prep 단계가 만든 준비된 클래스패스를 공유해요. Clojure 컴파일러와 의존 라이브러리 선택은 각 애플리케이션이 알아서 하는 게 낫죠. 개발 시 컴파일 사용에 대한 자세한 내용은 Dev Startup Time 가이드를 참고해요.

API 문서 참조.

버전 찾기

Maven 또는 git lib의 사용 가능한 버전을 검색하려면 내장 :deps 앨리어스가 제공하는 find-versions 도구를 사용해요.

clj -X:deps find-versions ...

제공할 수 있는 파라미터는:

  • :lib — git 또는 Maven lib 이름. git url은 git 라이브러리 이름에서 자동 구성돼요. 예를 들어 :git/libio.github.clojure/tools.deps.graph면 git url은 https://github.com/clojure/tools.deps.graph.git이 돼요. Maven은 org.clojure/tools.deps.graph 같은 Maven lib 이름을 사용해요.
  • :tool — 도구가 이미 설치되어 있다면 도구 이름

find-versions는 git 또는 Maven 좌표를 한 줄에 하나씩 콘솔에 출력해요. API 문서 참조.

로컬 Maven 설치

-X:deps mvn-install 프로그램은 편의를 위해 CLI와 함께 제공돼요. -X로 실행해 jar를 로컬 Maven 캐시에 설치할 수 있어요.

설치 파라미터에는 다음 옵션이 있어요.

Required:
:jar - jar 파일 경로, 기본적으로 jar 안의 pom 사용

명시적 pom 파일을 제공하려면:
:pom - pom 파일 경로 (jar 안의 pom 대신 사용)

최소 pom 파일을 생성하려면:
:lib - my.org/lib 같은 한정 심볼
:version - 문자열
:classifier - 문자열

기타 옵션:
:local-repo - 로컬 저장소 경로 (기본 = ~/.m2/repository)

필요에 따라 커맨드라인에서 덮어쓰기를 전달할 수 있어요.

clj -X:deps mvn-install :jar '"/path/to.jar"'

앞서 언급했듯이 edn 문자열은 이중 인용부호에 있어야 하고, 셸을 위해 단일 인용부호로 감싸야 해요.

pom 파일은 명시적으로 제공되거나, :lib/:version으로 생성되거나, .jar 파일 안에서(기본) 찾아야 해요. API 문서 참조.

Maven pom 생성

다음 프로그램으로 프로젝트의 deps와 paths로 기존 pom.xml을 생성하거나 업데이트해요.

  • -X:deps mvn-pom — deps와 paths로 pom.xml을 생성(또는 기존 것 업데이트)

API 문서 참조.

도구 (Tools)

도구는 lib로 배포된 함수의 모음이에요. 도구 함수는 프로젝트 클래스패스와 독립된 자체 클래스패스를 가진 별도 프로세스에서 실행돼요. 도구 함수는 맵 인자 하나를 받고 -T로 호출돼요(-X 스타일 실행과 같은 키-값 인자 문법).

도구는 프로젝트의 다른 사용자가 공유할 수 있는 앨리어스로, 또는 프로젝트를 넘나들어 공유할 수 있는 기계에 설치된 로컬 도구 이름으로 설명돼요.

도구 설치

도구를 관리하는 도구가 CLI에 의해 “tools”라는 이름으로 자동 설치돼요. 유용한 함수가 몇 개 제공돼요.

  • install — 도구 설치 또는 재설치
  • install-latest — 도구의 최신 버전 설치 또는 재설치
  • list — 설치된 모든 도구 나열
  • remove — 설치된 도구 제거
  • show — 도구의 정보와 사용법 출력
Install

설치할 도구 버전을 정했다면 install 함수로 도구를 이름으로 설치해요.

clj -Ttools install ...

install-tool의 인자는:

  • lib — 값은 deps.edn대로 coord 맵
  • :as — 도구 이름, 이후 호출에 사용

예:

clj -Ttools install io.github.clojure/tools.deps.graph '{:git/tag "v1.0.63"}' :as deps-graph

Windows에서는 추가 이스케이프 인용이 필요해요.

clj -Ttools install io.github.clojure/tools.deps.graph '{:git/tag """v1.0.63"""}' :as deps-graph

git deps는 도구 설치 시점에 git lib 이름(관례상 git url을 형성)과 git tag만으로 완전히 기술될 수 있어요. 대신 coord에 명시적 :git/url이나 :git/sha가 있을 수도 있어요.

Install latest

도구의 최신 버전을 한 단계로 찾아 설치하려면:

clj -Ttools install-latest :lib io.github.clojure/tools.deps.graph :as deps-graph

기존 도구를 최신 버전으로 업데이트하려면 도구를 이름으로 지정하기만 해도 돼요.

clj -Ttools install-latest :tool deps-graph
List

설치된 모든 도구를 나열하려면:

clj -Ttools list

설치된 도구를 제거하려면:

clj -Ttools remove :tool name

도구 작성자를 위한 모범 사례

모범 사례는:

  • 도구를 공개 git 라이브러리로 제공
  • 도구 API를 하나 이상의 Clojure 네임스페이스에서 맵을 받는 함수로 정의
  • deps.edn 루트에 :tools/usage 키를 만들고, API 네임스페이스용 :ns-default 및/또는 :ns-aliases 키를 넣기
  • git 저장소를 태그해 릴리스를 만들되, 사용자가 순서를 쉽게 알 수 있는 체계를 사용. 흔한 관례는 “v1.2.3” 같은 버전 문자열

도구는 사용자에게 다음 지침을 제공할 수 있어요.

  • 도구 버전 찾기: clj -X:deps find-versions :lib io.github.USER/TOOL
  • 도구 설치: clj -Ttools install io.github.USER/TOOL '{:git/tag "VERSION"}' :as NAME
  • 도구 호출: clj -TNAME f args...

함수 실행 프로토콜

일부 도구는 다른 프로세스에서 프로그램적으로 실행되도록 설계된 함수를 제공해요. 다음 제약과 기대가 있어요.

  • 함수는 맵 인자 하나를 받아야 함
  • 결과는 (평소처럼) 함수에서 반환
  • 함수가 던진 예외는 실패를 일으키고, 예외 데이터(대략 Throwable->map)가 외부 프로세스에 전달되어 그곳에서 ex-info로 다시 던져짐
  • 출력은 (기본적으로) 캡처되지 않음
  • 어떤 결과나 예외 데이터든 다른 프로세스에서 데이터로 출력하고 다시 읽을 수 있어야 안전

-X 또는 -T 중에 CLI에 특별한 의미를 가진 arg map 키가 몇 개 있어요. 이 키들은 함수가 호출되기 전에 모두 arg map에서 제거돼요.

  • :clojure.exec/invoke:fn으로 이 프로토콜을 사용
  • :clojure.exec/out:capture로 함수 실행 중 stdout을 캡처해 반환
  • :clojure.exec/err:capture로 함수 실행 중 stderr을 캡처해 반환

결과는 다음 키를 가진 출력 봉투(envelope) 맵으로 감싸 CLI stdout으로 반환돼요.

  • :tag — 함수가 결과를 반환했는지 예외를 던졌는지에 따라 :ret 또는 :err
  • :val — 반환값 또는 예외 데이터, prn해서 문자열로
  • :out — 요청했다면 캡처된 stdout 반환
  • :err — 요청했다면 캡처된 stderr 반환
  • :ms — 함수 실행 시간(ms)

이 프로토콜의 소비자 API는 Clojure 1.12.0-alpha2부터 제공돼요.

프로큐어러 (Procurers)

의존성 좌표는 프로큐어러가 해석해요. 프로큐어러는 특정 좌표 타입을 이해하고, 라이브러리의 의존성을 찾고 아티팩트를 다운로드하는 방법을 아는 존재예요. Clojure CLI는 현재 다음 프로큐어러를 지원해요: Maven, Git, local(디렉토리와 jar 모두 포함). 기반 tools.deps 라이브러리는 라이브러리로 쓸 때 프로큐어러 확장을 지원해요.

좌표 속성이 어떤 프로큐어러를 쓸지 결정해요. 일반적으로 대부분의 프로큐어러 속성은 프로큐어러 타입별로 한정되어 있어요(몇 가지 예외). 프로큐어러 독립 좌표 속성은 deps 한정자를 사용해요.

일부 프로큐어러는 같은 한정자를 사용해 deps.edn 설정 맵의 루트에서 설정 속성을 찾기도 해요.

Maven

Maven 프로큐어러는 mvn 한정자를 사용하고, Java 생태계의 표준 저장소 관리자인 Maven 저장소에서 라이브러리 아티팩트를 가져와요. 라이브러리는 .jar 파일로 다운로드되어 Maven 로컬 저장소 캐시(기본 ~/.m2/repository)에 저장돼요. 다른 JVM 기반 도구도 이 캐시를 사용할 수 있어요.

자세한 내용은 deps.edn 참조의 Maven 좌표 타입Maven 프로큐어러 설정을 참고해요.

Maven 인증 저장소

인증 저장소의 Maven deps에는 자격 증명을 전달하기 위해 기존 Maven 인프라를 사용해요.

~/.m2/settings.xml에:

<settings>
  ...
  <servers>
    <server>
      <id>my-auth-repo</id>
      <username>zango</username>
      <password>123</password>
    </server>
    ...
  </servers>
  ...
</settings>

그리고 deps.edn에 서버 id(여기서는 my-auth-repo)와 이름이 일치하는 저장소를 포함해요.

{:deps
 {authenticated/dep {:mvn/version "1.2.3"}}
 :mvn/repos
 {"my-auth-repo" {:url "https://my.auth.com/repo"}}}

그러면 평소처럼 :deps에서 의존성을 참조하기만 하면 돼요.

Maven S3 저장소

mvn 프로큐어러는 AWS S3에 호스팅된 공개·비공개 Maven 저장소 연결도 지원해요. 특히 AWS에 호스팅된 애플리케이션에서 비공개 Maven 저장소에 접근할 때 유용하죠.

s3 저장소 루트를 포함하는 :mvn/repos를 추가해요.

{:deps
 {my/library {:mvn/version "0.1.2"}}
 :mvn/repos
 {"my-private-repo" {:url "s3://my-bucket/maven/releases"}}}

S3 버킷은 생성된 AWS 리전에 한정돼요. s3 transporter는 버킷 위치를 결정하려 시도해요. 그게 안 되면 url에 버킷 리전을 명시적으로 지정할 수 있어요: "s3://my-bucket/maven/releases?region=us-west-2".

인증 저장소의 경우 AWS 자격 증명을 ~/.m2/settings.xml에서 서버별로 설정하거나 AWS 자격 증명 체인(환경 변수 등)에서 앰비언트하게 로드할 수 있어요. deps.edn의 저장소 이름은 settings.xml의 서버 id와 일치해야 해요.

<settings>
  ...
  <servers>
    <server>
      <id>my-private-repo</id>
      <username>AWS_ACCESS_KEY_HERE</username>
      <password>AWS_SECRET_ACCESS_KEY_HERE</password>
    </server>
    ...
  </servers>
  ...
</settings>

AWS S3 자격 증명은 다음 중 한 메커니즘으로 환경에 설정할 수 있어요.

  1. 환경 변수 AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY 설정
  2. AWS 자격 증명 파일 ~/.aws/credentials에 기본 프로파일 생성(구버전 ~/.aws/config도 지원)
  3. AWS 자격 증명 파일에 이름 있는 프로파일을 만들고 환경 변수 AWS_PROFILE로 그 이름 설정
  4. Amazon ECS 컨테이너와 인스턴스 프로파일 자격 증명도 동작해야 하지만, 테스트되지는 않음

자세한 내용은 이 AWS 문서의 조언 대부분이 자격 증명을 찾는 방법을 설명해요. 단, Java 시스템 프로퍼티 옵션은 Clojure CLI에서 동작하지 않아요(tools.deps 라이브러리를 직접 쓰면 동작).

Maven 프록시

인터넷에 프록시로 접근하는 환경에서는 ~/.m2/settings.xml의 기존 Maven 설정으로 프록시 연결을 구성해요.

<settings>
  ...
  <proxies>
    <proxy>
      <id>my-proxy</id>
      <host>proxy.my.org</host>
      <port>3128</port>
      <nonProxyHosts>localhost|*.my.org</nonProxyHosts>
    </proxy>
  </proxies>
  ...
</settings>

더 자세한 내용은 Maven의 Guide to using proxies를 참고해요.

Maven HTTP 헤더

나가는 HTTP 요청에 커스텀 헤더를 추가하려면 ~/.m2/settings.xml의 기존 Maven 설정을 사용해요.

<settings>
  ...
  <servers>
    <server>
      <id>my-token-repo</id>
      <configuration>
        <httpHeaders>
          <property>
            <name>Private-Token</name>
            <value>abc123</value>
          </property>
        </httpHeaders>
      </configuration>
    </server>
    ...
  </servers>
  ...
</settings>

settings.xml의 서버 id는 deps.edn의 저장소 이름과 일치해야 해요.

{:mvn/repos
 {"my-token-repo" {:url "https://my.auth.com/repo"}}}

이 메커니즘은 사용자 이름·비밀번호가 아니라 토큰으로 인증하는 저장소가 사용해요.

Git

git 프로큐어러는 Git 저장소에 호스팅된 소스 기반 lib의 직접 사용을 지원해요. Git lib는 기본적으로 ~/.gitlibs 디렉토리에 다운로드돼요. 의존성으로 포함된 각 sha에 대해 작업 트리가 체크아웃되어 캐시돼요.

자세한 내용은 deps.edn 참조의 Git 좌표 타입을 참고해요.

설정과 디버깅

git 프로큐어러는 커맨드라인 git(과 ssh)을 셸아웃해요. git >= 2.5가 필요해요. 일반적으로 커맨드라인에서 접근이 된다면 Clojure CLI에서도 동작해야 해요. git이 설치되어 있고 기본적으로 git이 path에 있다고 가정돼요. ssh 접근은 시스템 문서를 참고해요(보통 ~/.ssh/id_rsa에 ssh 키를 등록).

git 사용을 제어하는 환경 변수:

  • GITLIBS — gitlibs 저장 디렉토리 경로 (기본 = ~/.gitlibs)
  • GITLIBS_COMMAND — git 접근에 실행할 커맨드 (기본 = git)
  • GITLIBS_DEBUG — 실제 실행되는 git 커맨드와 그 출력 로그를 보려면 true (기본 = false)

Local

local 프로큐어러는 로컬 디렉토리나 jar 파일을 의존성으로 포함해요. 자세한 내용은 deps.edn 참조의 local 좌표 타입을 참고해요.

용어 사전 (Glossary)

라이브러리 (Library) — 단일 디렉토리 루트 아래 관리되는, 어떤 문제를 푸는 Clojure 또는 다른 코드의 모음. 일반적(전용적이진 않은) 용법으로, 대부분의 GitHub 저장소는 단일 라이브러리를 담아요. 각 라이브러리는 고유한 네임스페이스 이름을 가지는데, Maven에서는 group-id/artifact-id로 결정돼요.

아티팩트 (Artifact) — 어떤 시점의 라이브러리 상태를 담아 컨테이너 파일로 릴리스된 라이브러리. 빌드 과정을 거칠 수도 있고, 버전으로 라벨링되고, 의존성을 문서화하는 매니페스트를 담고, 예를 들어 jar로 패키징돼요.

좌표 (Coordinate) — 사용하기 위해 선택된 특정 버전의 라이브러리. 라이브러리를 얻고 사용하기에 충분한 정보가 있어요.

의존성 (Dependency) — 프로젝트/라이브러리 수준에서, 선언하는 라이브러리가 그 기능 중 일부를 제공하기 위해 선언된 라이브러리가 필요하다는 표현. 최소한 라이브러리 이름을 지정해야 하고, 버전이나 기타 속성도 지정할 수 있어요. 실제(기능적) 의존성은 더 세밀해요.

의존성 타입:

  • Maven 아티팩트 (아티팩트 기반)
  • Git 라이브러리 (소스 기반)
  • 로컬 라이브러리 (소스 기반) — 로컬 디렉토리
  • 로컬 아티팩트 (아티팩트 기반) — 로컬 jar 파일

클래스패스 (그리고 루트/경로) — 런타임에 requires/imports 검색의 루트 경로가 될, 순서 있는 로컬 ‘장소‘(파일시스템 디렉토리 및/또는 jar) 목록. Java에 인자로 제공되고 Java가 의미를 제어해요. 우리는 클래스패스의 순서 의존성을 권장하지 않아요 — 네임스페이스나 리소스 파일이 중복된다는 뜻이고(그래서 아마 깨져 있음) 때문이죠.

확장 (Expansion) — 루트 의존성 집합이 주어졌을 때, 전이 의존성 집합의 완전한 폐포(closure).

해석 (Resolution) — 루트 의존성 모음과 추가 수정이 주어졌을 때, 완전히 확장된 의존성 트리를 만들고, 각 라이브러리에 대해 모든 의존자를 만족시킬 단일 버전과 그 소스·아티팩트의 로컬 경로로의 매핑을 만들어내는 것. 각 항목에 그 의존자들도 포함해요. 충돌은 라이브러리들이 서로 다른 메이저 버전에 의존할 때만 생겨요.

버전 (Version) — 해석이 관례에 의해 정해지는 인간용 번호 체계. 흔히 x.y.z. 널리 쓰이는 체계로 “시맨틱 버저닝” aka “semver”가 있는데, 각 레벨의 변화에 의미를 부여해요. 예를 들어 첫 메이저 숫자가 바뀌면 하위 호환되지 않는 변화를 뜻해요.

버전 차이 (Version difference) — 의존성 확장에 같은 라이브러리가 두 개 이상의 “버전”으로 포함되지만(숫자나 sha 등) 서로 상대적 순서가 있을 때 발생. 상대 관계가 성립될 수 있을 때 “나중”/“최신” 버전을 선택해 해석할 수 있어요.

버전 충돌 (Version conflict) — 의존성 확장에 같은 라이브러리가 두 개 이상의 “버전”으로 포함되어 최선의 선택을 자동으로 할 수 없을 때 발생.

  • semver 버전 깨짐 (메이저 버전 변경)
  • 공통 루트나 조상을 포함하지 않는 github sha (예: 다른 브랜치의 두 sha 또는 관련 없는 저장소)
  • 상대 관계를 세울 수 없을 정도로 서로 다른 저장소나 저장소 타입을 가로지르는 버전

Maven 저장소 (Maven Repo) — 라이브러리 아티팩트의 저장소 — 예: Maven Central 또는 Clojars

더 알아보기