Clojure 라이브러리(Libs) 사용하기
Clojure 라이브러리(Libs) 사용하기
Clojure는 코드를 불러오고(loading) 의존성을 추적하는 기능을 lib(라이브러리)이라는 장치로 제공해요. lib는 클래스패스(classpath) 안에 있는 Java 리소스에 담긴, 이름이 붙은 Clojure 소스 코드 단위예요. 보통 lib 하나가 Clojure 네임스페이스(namespace) 하나를 이루는 정의의 완전한 집합을 제공하죠.
출처: Clojure 공식문서
본문
lib 이름 짓는 규칙 (Lib Conventions)
Clojure는 lib의 이름과 구조에 대한 규약을 정해두고 있어요. 여기서 핵심 세 가지를 짚어볼게요.
- lib 이름은 심볼(symbol) 이고, 보통 마침표(.)로 구분된 두 부분 이상으로 만들어요.
- lib가 담긴 컨테이너는 Java 리소스인데, 그 클래스패스 기준 경로는 lib 이름에서 유도돼요.
- 경로는 문자열(string)이에요.
- lib 이름의 마침표(.)는 경로에서 슬래시(/)로 바뀌어요.
- lib 이름의 하이픈(-)은 경로에서 언더스코어(_)로 바뀌어요.
- 경로는
.class,.clj,.cljc로 끝날 수 있어요. 어떤 우선순위로 로딩되는지는 아래 lib 로딩 순서를 보면 돼요.
- lib는
ns폼(form) 으로 시작하는데, 이 폼이 두 가지를 해요.- 자기 이름과 같은 네임스페이스를 만들고,
- Java 클래스, Clojure 핵심 기능, 다른 lib에 대한 의존성을 선언해요.
Clojure는 ns 호출이 예외 없이 끝나면 선언된 의존성이 모두 충족되고, 그 기능들이 사용 가능하다는 걸 보장해요. 그래서 ns 폼이 성공했다면 의존성은 믿고 써도 되는 거죠.
예시 lib (Example Lib)
간단한 lib 하나를 볼게요.
(ns com.my-company.clojure.examples.my-utils
(:import java.util.Date)
(:use [clojure.string :only (join)])
(:require [clojure.java.io :as jio]))
ns폼이 네임스페이스 이름을 정하고 의존성을 선언해요. 이름을 기준으로 이 lib는 보통com/my_company/clojure/examples/my_utils.clj경로에 정의돼요. 여기서 마침표가 슬래시로, 하이퀸이 언더스코어로 바뀐 걸 확인할 수 있어요.:import절은 이 lib가java.util.Date를 쓴다고 선언하고, 그 클래스를 이름만으로(정규화 없이) 쓸 수 있게 해줘요.:use절은clojure.stringlib에 의존을 선언하는데,join함수만 가져와요. 그래서 이 lib 코드에서join을 이름만으로 쓸 수 있어요.:require절은clojure.java.iolib에 의존을 선언하고, 그 멤버들을 짧은 네임스페이스 별칭jio로 사용할 수 있게 해줘요.
접두사 목록 (Prefix Lists)
lib 하나가 이름 앞부분(접두사)을 공유하는 여러 lib에 의존하는 경우가 흔해요. 이런 경우 require나 use 호출에서(그리고 ns 폼의 :require, :use 절에서도) 공통 접두사를 한 번만 적고, 그 뒤에 나머지 이름들을 모아 접두사 목록(prefix list) 으로 쓸 수 있어요. 아래 두 폼은 완전히 같은 의미예요.
(require 'clojure.contrib.def 'clojure.contrib.except 'clojure.contrib.sql)
(require '(clojure.contrib def except sql))
관련 함수 (Related functions)
- 네임스페이스 만들기:
ns - lib가 로딩되었는지 확인하기:
require,use - 로딩된 lib 나열하기:
loaded-libs
lib 로딩 순서 (Lib load order)
lib는 컴파일된 형태(.class) 또는 소스 형태(.clj, .cljc) 로 존재할 수 있어요. 어떤 경우엔 이중 하나만, 또 어떤 경우엔 전부가 클래스패스에 존재하기도 하죠. 그러면 어디서 로딩할까요? 다음 규칙을 따라요.
.class파일이 항상 소스 파일보다 우선이에요. 단, 소스 파일의 타임스탬프가.class파일보다 새롭다면 소스 파일이 우선이 돼요..clj(플랫폼 특정 파일)는 항상.cljc(플랫폼 공통)보다 우선이에요.
두 번째 규칙 덕분에 라이브러리 저자는 플랫폼 간에 공통으로 쓸 수 있는 휴대용 정의와, 그 위에서 호스트 플랫폼을 활용하도록 덮어쓰는 플랫폼 전용 lib를 함께 배포할 수 있어요.