- Learn about Wiki
- Lectures
- Study
- Tips
프로젝트의 관리는 project.clj와 profiles.clj 2 개의 파일을 사용한다.
자세한 설명 : 라이닝언 프로파일
정의: 프로파일이란 하나의 프로젝트를 빌드, 릴리즈, 테스트, 개발 등, 프로젝트를 여러가지 단계 및 측면에서 필요한 설정을 선언적 방식으로 할 수 있도록 하는 프로젝트 관리 방법.
프로파일에는 defproject(project.clj 파일에서 정의되는)에서 사용하는 모든 키-값을 사용할 수 있다. 프로파일에 정의된 키-값은 project 맵에 병합(merge)된다.
다음 4가지 방식으로 프로파일을 만들 수 있다.
키로 정의하기
defproject에 :profiles 키에 맵으로 값을 할당한다.
(defproject myproject "0.5.0-SNAPSHOT" :description "A project for doing things." :dependencies [[org.clojure/clojure "1.4.0"]] :profiles {:dev {:resource-paths ["dummy-data"] :dependencies [[expectations "1.4.41"]]}})
프로젝트가 만들어지지 않은 아무 디렉토리에서 lein show-profiles 명령을 실행하면 기본적으로 존재하는 프로파일을 볼 수 있다.
> lein show-profiles base debug default leiningen/default leiningen/test offline uberjar update user
기 정의된 프로파일로 다른 프로파일을 만들 수 있다. 이때는 프로파일 값으로 맵이 아니라 백터를 쓰고 구성하고 싶은 프로파일 명을 원소로 넣는다.
{:shared {:port 9229, :protocol "https"} :qa [:shared {:servers ["qa.mycorp.com"]}] :stage [:shared {:servers ["stage.mycorp.com"]}] :production [:shared {:servers ["prod1.mycorp.com", "prod1.mycorp.com"]}]}
(defproject guestbook "0.1.0-SNAPSHOT" ... :profiles {:uberjar {:omit-source true :env {:production true} :aot :all :source-paths ["env/prod/clj"] :resource-paths ["env/prod/resources"]} :dev [:project/dev :profiles/dev] ; (1) :test [:project/test :profiles/test] ; (2) :project/dev {:dependencies [[prone "1.0.1"] [ring/ring-mock "0.3.0"] [ring/ring-devel "1.4.0"] [pjstadig/humane-test-output "0.7.1"] [mvxcvi/puget "1.0.0"]] :source-paths ["env/dev/clj" "test/clj"] :resource-paths ["env/dev/resources"] :repl-options {:init-ns user} :injections [(require 'pjstadig.humane-test-output) (pjstadig.humane-test-output/activate!)] ;;when :nrepl-port is set the application starts the nREPL server on load :env {:dev true :port 3000 :nrepl-port 7000}} :project/test {:env {:test true :port 3001 :nrepl-port 7001}} :profiles/dev {} :profiles/test {}})
lein show-profiles로 project/test 프로파일이 어떻게 설정되는지 볼 수 있다.
> lein show-profiles project/test {:env {:test true, :port 3001, :nrepl-port 7001}, :jvm-opts nil, :eval-in nil}
개발시에는 에러가 발생하면 에러 메시지가 자세하게 나오게 하는 것이 좋지만, 배포시에는 제한된 메시지만 뿌리게 하고 싶다. 하지만 개발시와 배포시의 실행을 코드상으로 구별하는 것은 또 다른 버그를 만들 수 있다. 이것도 프로파일을 사용하면 원하는 소스만을 해당 개발과 배포시에 구분해서 사용할 수 있다.
:source-paths는 defproject의 키로서 프로젝트에서 실제 사용할 소스의 위치를 정의한다. 이 키가 루미너스에서는 root와 :uberjar, 그리고 :project/dev 에서 다음과 같이 설정되어 있다.
개발시에는 env/dev에 있는, 배포시에는 env/prod 폴더에 있는, guestbook.config 이름공간을 사용한다.
env/dev/guestbook/config.clj
(ns guestbook.config (:require [selmer.parser :as parser] [clojure.tools.logging :as log] [guestbook.dev-middleware :refer [wrap-dev]])) (def defaults {:init (fn [] (parser/cache-off!) (log/info "\n-=[guestbook started successfully using the development profile]=-")) :middleware wrap-dev})
env/prod/guestbook/config.clj
(ns guestbook.config (:require [clojure.tools.logging :as log])) (def defaults {:init (fn [] (log/info "\n-=[guestbook started successfully]=-")) :middleware identity})
보통 웹 어플리케이션에서는 MVC 패턴을 사용하지만 루미너스에서는 뷰와 컨트롤러 사이의 구분이 엄격하지 않다. 오히려 관련된 코드는 같은 이름공간에 존재한다.
하지만 클로저 웹 스택은 아주 유연하기 때문에 MVC 패턴 방식으로 구성할 수도 있다.
최초의 어플리케이션 구동과 서버 구동하는 코드들이 정의되어 있다.
루미너스는 핸들러의 routing을 다음과 같이 분리되어 있다.
일반적으로는 다음과 같이 시작한다.
(defroutes app-routes (GET "/" [] (resource-response "index.html" {:root "public"})) (GET "/widgets" [] (response [{:name "Widget 1"} {:name "Widget 2"}])) (route/resources "/") (route/not-found "Page not found"))
init과 destroy 함수는 서버 시작과 종료시에 실행할 코드 정의한다.(이 2 함수는 handler가 아닌 core 이름공간으로 갈 필요가 있어 보인다)
컴포넌트 라이브러리로는 스튜 지에라의 Component가 아닌 mount 사용하고 있다.
커스텀 미들웨어를 정의한다.
환경 변수로 DB 설정한다.
HTTP 응답을 위한 HTML 만들기.
*app-context*는 요청의 :servlet-context나 혹은 환경변수의 :app-context로 동적으로 설정되면서 wrap-context 미들웨어에 적용된다.