Pedestal을 사용해 간단한 웹서버를 만들어 보고 쓸만하다 싶어서 그것으로 백앤드 구성해보려고 했다. 그런데 이런 저런 것들을 붙이려고 보니 생각보다 사용하기 불편했다. 그래서 다른 프레임워크들을 찾다가 Catacumba라는 것을 발견했다. 나온지 얼마 안된 것처럼 보였지만 내가 필요로 하는 기능들은 적당히 들어가 있는 것 같았다. 우선 가벼운 프레임워크이고 기능이 부족하지만 계속 추가되는 것 같고 문서가 쉽게 잘 정리되어 있다. 웹서버 기능을 제대로 할 수 있는지는 아직 잘 모르겠지만 백앤드를 구성하는 마이크로서비스를 만들기에는 부족함이 없어 보였다. 외부로 API를 노출시켜야 하는 서비스는 다른 것을 가져다 써도 되니까 지금 걱정할 필요는 없다. 오늘은 문서를 보면서 간단한 서버를 만들어봤다.


Catacumba

https://funcool.github.io/catacumba/latest


프로젝트 생성

우선 lein을 이용해서 프로젝트를 생성한다. 

lein new app catacumba-app 


다음은 project.clj 파일에 Catacumba를 추가한다. 

1
2
:dependencies [[org.clojure/clojure "1.8.0"]
               [funcool/catacumba "2.2.1"]]
cs


다음으로 서버 실행과 관련된 파일인 core.clj 파일을 살펴보자. 


네임스페이스 구성

1
2
3
4
(ns catacumba-app.core
  (:gen-class)
  (require [catacumba.core :as ct]
           [catacumba.handlers.misc :as misc]))
cs



우선 Catacumba 코어 라이브러리와 handlers.misc 라이브러리를 추가한다. handlers.misc/autoreloader 함수는 routes에서 사용되며 핸들러와 관련된 모든 네임스페이스의 변경을 감지해 릴로드해주는 기능을 한다. 정상적인 동작을 위해서는 반드시 핸들러의 var reference를 등록해야 한다.


Routes 등록

1
2
3
4
(def app
  (ct/routes [[:any (misc/autoreloader)]
              [:all "" #'all]
              [:get "ping" #'ping]]))
cs

 

Catacumba의 라우팅은 백터와 키워드로 구성되는데 모든 루트를 위한 :any, 그리고 :get, :post, :patch, :delete를 루트 디렉티브로 사용할 수 있다. 앞서 설명한 것처럼 (misc/autoreloader)를 사용하여 코드 변경이 있을 때마다 앱을 릴로드하도록 했다. 그리고 각 루트에 대해 #' 매크로를 사용해 var references를 등록했다. 


서버 실행

1
2
3
(defn -main
  [& args]
  (ct/run-server app {:port 8080}))
cs


앱의 메인 엔트리 포인트는 run-server이다. 위에서 등록한 핸들러에 옵션을 추가해 서버를 실행한다. :port 외에도 :host, :debug, :thread 등을 옵션에 추가할 수 있다. 옵션 항목들은 여기에서 확인할 수 있다. 

https://funcool.github.io/catacumba/latest/#launching-the-server


위 코드들을 모두 합친 core.clj 파일은 아래와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
(ns catacumba-app.core
  (:gen-class)
  (require [catacumba.core :as ct]
           [catacumba.handlers.misc :as misc]))
 
(defn all [context]
  "Hello World!!")
 
(defn ping [context]
  "pong")
 
(def app
  (ct/routes [[:any (misc/autoreloader)]
              [:all "" #'all]
              [:get "ping" #'ping]]))
 
(defn -main
  [& args]
  (ct/run-server app {:port 8080}))
cs


서버 실행

서버 실행을 위해 아래 명령을 실행한다. 

lein deps

lein run


테스트

테스트를 위해 cURL을 이용한다. 

$ curl -i "localhost:8080"

Clojure 1.9.0 - served from /about(py2_env) kwiff-mbp-klee:echo-service klee$ curl -i "localhost:8080"

HTTP/1.1 200 OK

content-type: text/plain;charset=UTF-8

content-length: 13

set-cookie: sessionid=AAABaE-nFJG53hgFY5oSqeWkMtfT0Yajcwe4beQSgoz2KQu6hCZ_miYDktpXlUF3; Max-Age=0; Expires=Tue, 15 Jan 2019 03:56:16 GMT; Path=/; HTTPOnly


Hello World!!


$ curl -i "localhost:8080/ping"

HTTP/1.1 200 OK

content-type: text/plain;charset=UTF-8

content-length: 4

set-cookie: sessionid=AAABaE-nd9yOBW5YlZ1RWSBTNkSTU0QU94wG7_VQaBIGJd7q9-6Rb1QMx7GWYFmE; Max-Age=0; Expires=Tue, 15 Jan 2019 03:56:41 GMT; Path=/; HTTPOnly


pong


소스코드

간단한 코드이지만 여기에 전체 소스코드를 올려 놓았다. 

https://github.com/ksleeq21/catacumba-app


Catacumba 문서를 보면 알겠지만 작고 간단한 프레임워크인데도 비동기 핸들러 추가, 클라이언트 요청을 처리할 쓰레드 설정, 개발에 편리한 오토 릴로드 설정과 같은 기본은 잘 갖춰져 있다. 쓰다보면 단점도 발견하게 되겠지만 이 만하면 좀 더 사용해볼 만 하다. 앞으로는 이 Catacumba를 이용해서 특정 로직을 수행하는 백앤드를 만들어 보려고 한다. 몇 개의 마이크로서비스를 설계하고 데이터, 컨트롤, 프로토콜 등을 정의해 직접 구현까지 해볼 계획이다. 지금 시간 있을 때 해봐야지 안그러면 영영 못한다.


Posted by 코딩새싹
,