2015년 10월 6일 화요일

Handlebarjs로 생성하는 HTML을 서버에서 생성하기

underscorehandlebarjs로 생성하는 HTML조각을 서버에서 생성해야 하는 경우가 생겼다. 현재 서버에서 정형화된 데이터를 JSON으로 받아서 javascript에서 underscore로 자료구조를 변경한 뒤에, handlebarjs로 템플릿을 씌워서 jquery로 DOM에 붙이는 작업이 있는데, 이를 클라이언트에서 변경하지 못하도록 서버에서 생성해야 하는 것이다. 결국에는 서버에서 모든 HTML을 생성하여 PDF로 바로 생성하는데 그 목적이 있다.

1.
javascript 엔진을 java에서 구현한 게 있으니 그걸 사용해서 해보자. java 1.7까지는 rhino가 있고, 1.8부터는 nashorn이 있다. 현재 프로젝트가 1.7을 사용 중이어서 rhino에 underscore와 handlebajs를 load해서 실행시키는 것 까지는 성공했다.

        Context cx = Context.enter();
        Global global = new Global(cx);
        cx.evaluateString(global, "print('Hello World!')", "helloWorld.js", 1, null);
        cx.evaluateString(global, "print('Hello World!')", null, 1, null);
        cx.evaluateString(global, "function a() { print('this is a') }", null, 1, null);
        cx.evaluateString(global, "a();a();", null, 1, null);
        cx.evaluateString(global, "load('underscore.js')", null, 1, null);
        cx.evaluateString(global, "load('handlebars-v4.0.1.js')", null, 1, null);
        cx.evaluateString(global, "print(_.now())", null, 1, null);
        cx.evaluateString(global, "print(Handlebars.Utils.isFunction(_.now))", null, 1, null);
        Context.exit();

2.
그런데 jquery를 안된다. rhino 내부에 window 객체가 없어서 에러가 난다. 구글링을 해봐도 전부 2008년도 즈음의 웹페이지들만 검색이 되고, 대부분 안된다는 내용이다.

3.
1번에서 사용한 javascript context에 java의 VO객체 유형의 데이터를 넣고 underscore로 데이터를 조작한 다음, 바로 handlebarjs에 넣어서 템플릿을 만들고 그걸 java로 다시 받아와서 이어 붙이는 형태를 해볼까 생각해봤다.

4.
그러던 와중에 handlebarjs의 java 버전이 있는 것을 찾아 냈다. 블로그는 여기. 예제를 따라하니 금방된다.

Handlebars handlebars = new Handlebars();
Template template = handlebars.compileInline("Hello {{this}}!");
System.out.println(template.apply("Handlebars.java"));
template = handlebars.compile("mytemplate");
System.out.println(template.apply("Handlebars.java"));

5.
jsp에 <script> 태그로 선언한 템플릿을 hbs 파일로 나누거나, 하나의 파일을 읽어서 나누거나 해서 서버에서 충분히 HTML코드를 만들 수 있게 되었따.

6.
underscore로 정형화된 데이터를 재구성하는 것은 DB조회시부터 원하는 모양으로 조회하도록 변경할 예정

7.
템플릿을 미리 컴파일해놓고 쓸 수 있게 최적화하는 것도 이번에 고려할 예정