java/spring과 node.js의 공존 시즌2

54
Java/Spring과 Node.js의 공존 시 즌2 (부제: Java/Spring 전성시대에 Node.js가 살아남는 법 ) J2V8을 활용한 자바에 빌붙 Dongsu Jang <iolothebard at gmail dot com>

Upload: -

Post on 08-Jan-2017

2.467 views

Category:

Software


12 download

TRANSCRIPT

Java/Spring과�Node.js의�공존�시즌2�(부제:�Java/Spring�전성시대에�Node.js가�살아남는�법)�

J2V8을�활용한�자바에�빌붙기

Dongsu�Jang�<iolothebard�at�gmail�dot�com>

발표자료

http://slideshare.net/iolo

제주사는/마이너지향/입코딩전문/독거중년/개발자

이 분이

바로... 만렙 음유시

그러나,

현실은... 독거중년

아무도�궁금해�하지�않는…�

iolo-the-bard

TOC• BEGIN�

• AS-IS�

• Nashorn�

• ScriptTemplateView�

• Node.js�

• TO-BE�

• J2V8�

• VS�

• CODE�

• END

BEGINJUST�FOR�FUN

개발자여,�불가능한�꿈을�꾸어라

• Just�For�Fun�

• Open�Source�

• MSA�

• Polyglot�

• IE8�없는�세상…

그러나,�리얼리스트가�되라

• 현실은�자바�천국…�

• 스프링�전성�시대…�

• 봄날은�생각보다�오래�가더라…�

• Write�Once,�Ops�Forever!�

• IE8만�없어지면�될�줄�알았지?

그래도…�npm에�좋은거�많다던데…

J2V8의�역습�J2V8�STRIKES�BACK

Java/Spring과�Node.js의�공존�시즌2

AS-ISAS�GOOD�AS�IT�GETS

Spring�Velocity�DEPRECATED에�대처하는�우리의�자세

• Thymeleaf?�

• 다시�JSP?�

• 그냥�Velocity?!�

• 참고:�https://jira.spring.io/browse/SPR-13235

React�Isomorphic�Rendering에�대처하는�우리의�자세

• React?�

• Isomorphic?�

• 먹는거임?�

• 대세�or�Hype!

빌붙기의�기술

• Rhino�

• Nashorn�

• Node.js�

• J2V8

Rhino

• built-in�since�Java6�

• Oldies�but�Goodies�

• Slooooow�but�Elegant�

• 참고:�https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Rhino

Nashorn

• built-in�since�Java8�

• Fast�&�Easy�

• try�`jrunscript`�

• JSR-223�Scripting�API�

• 참고:�http://openjdk.java.net/projects/nashorn/

Hello�World�with�Nashorn

function greeting(name) { return "hello," + name + "!"; }

ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn"); engine.eval(new FileReader("hello.js")); Invocable invocable = (Invocable)engine; Object result = invocable.invokeFunction( "greeting", "World"); System.out.println(result);

React�Isomorphic�Rendering��with�Nashorn

tomcatapache webapp�(war)

MySQL

Nashorn

mod_jkAJPHTTP

JVM

glue�script

ReactDOMServer.renderToString()

자바�기반�템플릿�엔진

React�Isomorphic�Rendering��with�Nashorn

function renderToString(type, props) { return ReactDOMServer.renderToString(type, props); }

<div id="main">${reactHtml}</div> <script src="bundle.js"></script>

$.getJSON('/apis/v1/comments', function (data) { ReactDOM.render(<CommentList comments={ data }/>, document.getElementById('main')); });

React�Isomorphic�Rendering��with�Nashorn

@RequestMapping("/comment_list") String getCommentList(Model model) { ScriptEngine engine = new ScriptEngineManager() .getEngineByName("nashorn"); engine.eval(new FileReader("polyfill.js")); engine.eval(new FileReader("react.js")); engine.eval(new FileReader("react-dom-server.js")); engine.eval(new FileReader("render.js")); Invocable invocable = (Invocable)engine; String reactHtml = (String)invocable.invokeFunction( "renderToString", "CommentList", demoService.getComments()); model.addAttribute("reactHtml", reactHtml); return "comment_list"; }

ScriptTemplateView

• since�Spring�4.2�

• Easy!!�

• JSR-223�Scripting�API�

• Nashorn,�Rhino,�JRuby,�Jython,�…�

• Template�Engines�

• Hadlebars,�Mustache,�ejs,�Jade�and�erb,�Jinja2,�…

ScriptTemplateView

tomcatapache webapp�(war)

MySQL

Script�Template�

View

mod_jkAJPHTTP

JVM

glue�script

render(template,�model,�url)

스크립트�언어�기반�템플릿�엔진

ScriptTemplateView�with�ejs/Nashorn

@RequestMapping(“/comment_list”) public String server(Model model) { model.addAttribute(“comments”, demoService.getComments()); return "comment_list"; }

<ul> <% comments.forEach(function (comment) { %> <li> <h5><%= comment.content %></h5> <p><%= comment.author %></p> </li> <% }); %> </ul>

ScriptTemplateView�with�ejs/Nashorn

var _compiledTemplates = {}; function render(template, model, url) { var compiledTemplate = templates[url]; if(!_compiledTemplates[url]) { _compiledTemplates[url] = compiledTemplate = ejs.compile(template); } return compiledTemplate(toJsonObject(model));} function toJsonObject(javaObj) { var jsonObj = {}; for (var k in javaObj) { if(javaObj[k] instanceof Java.type("java.lang.Iterable")) { jsonObj[k] = Java.from(javaObj[k]); } else { jsonObj[k] = javaObj[k]; } } return jsonObj; }

ScriptTemplateView�with�ejs/Nashorn

@Configuration public class EjsConfig { @Bean public ScriptTemplateConfigurer scriptTemplateConfigurer() { ScriptTemplateConfigurer bean = new ScriptTemplateConfigurer(); bean.setEngineName("nashorn"); bean.setScripts( "/server-scripts/nashorn-polyfill.js", "/META-INF/resources/webjars/ejs/2.4.1/ejs-v2.4.1/ejs.min.js", "/server-scripts/nashorn-ejs-render.js" ); bean.setRenderFunction("render"); bean.setSharedEngine(true); return bean; } @Bean public ViewResolver scriptTemplateViewResolver() { ScriptTemplateViewResolver bean = new ScriptTemplateViewResolver(); bean.setPrefix("classpath:/templates/ejs/"); bean.setSuffix(".ejs"); return bean; } }

Node.js

• Polyglot,�MSA�or�Hype?�

• Fast�&�Easy�

• but�Another�World�

• npm에�좋은거�많다던데…�

• 참고:�https://nodejs.org

React�Isomorphic�Rendering��with�Node.js

tomcatapache webapp�(war)

MySQL

express

mod_jkAJPHTTP

JVM

app.js

ReactDOMServer.renderToString()

자바�기반�템플릿�엔진

HTTPNode.js

HTTP

React�Isomorphic�Rendering�with�Node.js

var ReactDOMServer = require(‘react-dom/server’); var CommentList = require(‘comment_list’); app.get(‘/comment_list’, function (req, res, next) { db.getCommentList(function (err, data) { ReactDOMServer.renderToString(<CommentList comments={data}/>); res.send(reactHtml); }; });

@RequestMapping("/comment_list") String getCommentList(Model model) { String reactHtml = restTemplate.getForObject( "http://localhost:3000/comment_list", String.class); model.addAttribute("reactHtml", reactHtml); return "comment_list"; }

<div id="main">${reactHtml}</div> <script src="bundle.js"></script>

TO-BESTAY�HUNGRY�STAY�FOOLISH

J2V8• Open�Source�Java�bindings�

for�V8�

• Licensed�under�the�EPL�

• Faaaaast�Fresh!�

• Run�on�Java6�

• not�only�V8�but�also�NodeJS�

• Linux,�Windows,�Mac�OS�X,�Android�ARM,�Android�x86�

• 참고:�https://github.com/eclipsesource/J2V8

J2V8�-�TODO

• Marshalling�

• JNI�performance�bottleneck�

• Memory�Management�&�GC�

• Exception�Handling�

• Debugger�Integration�

• JSR-223�Scripting�Engine�

• Best�Practice�&�Antipatterns

Rhino�vs�Nashorn�vs�V8

출처: https://ariya.io/2014/03/nashorn-the-new-rhino-on-the-block

Hello�World�with�V8/J2V8

V8 v8 = V8.createV8Runtime(); v8.executeScript(FileUtils.readFileToString("hello.js")); V8Array args = new V8Array(v8).push("World"); String result = v8.executeStringFunction("greeting", args); System.out.println(result); args.release(); v8.release();

function greeting(name) { return "Hello," + name + "!"; }

Hello�World�with�NodeJS/J2V8

NodeJS nodeJS = NodeJS.createNodeJS(); V8Object hello = nodeJS.require("./hello"); V8Array args = new V8Array(hello.getRuntime()).push("World"); String result = hello.executeJSFunction("greeting", args); while (nodeJS.isRunning()) { nodeJS.handleMessage(); } System.out.println(result); args.release(); hello.release(); nodeJS.release();

function greeting(name) { return "Hello," + name + "!"; }

Putting�it�all�togethter�with�J2V8

tomcatapache webapp�(war)

MySQL

J2V8

mod_jkAJPHTTP

JVM

server�&�shared�scripts

ReactDOMServer.renderToString()

자바스크립트�기반�템플릿�엔진

JNI

npm

Putting�it�all�togethter�with�J2V8

채널�고정!

VSI�WANT�TO�BELIEVE

소스코드

https://github.com/iolo/spring-template-bench

ab�on�my�machine

• ab -n 100 -c 4

• MacBook�Pro�(Retina,�15-inch,�Mid�2014)�

• OS�X�El�Capitan�10.11.6�

• 2.5�GHz�Intel�Core�i7,�16GB�1600�MHz�DDR3,�500GB�Apple�SSD

THE�TRUTH�IS�OUT�THERE

0

75

150

225

300

Velocity Freemarker Thymeleaf JSP ScriptTemplateView ejs handlebars J2V8TemplateView ejs

Server�Only React�Nashorn J2V8 Custom�J2V8

THE�TRUTH�IS�OUT�THERE

Server OnlyReact Custom

Nashorn J2V8 J2V8

Velocity 248.15 24.91 83.98 -

Freemarker 216.40 24.44 82.59 -

Thymeleaf 138.60 25.21 89.73 -

JSP 117.05 24.88 93.10 -

Script TemplateView

ejs 84.40 30.10 86.39 -

handlebars 26.59 38.56 95.62 -

J2V8 TemplateView

ejs 102.65 25.37 207.70 280.90

CODESHOW�ME�THE�CODE

소스코드

https://github.com/iolo/jscon-springboard-demo 또�게시판!�

ㅋㅋㅋ

디렉토리�구조• src/main/java/�

• src/main/react/�

• src/main/resources/static�

• src/main/resources/templates�

• pom.xml�

• package.json�

• webpack.config.js�

• target/classes/static

안봐도비디오~

J2V8�in�Action

• pom.xml�-�Maven�Dependencies�for�J2V8�

• J2V8TemplateView/ViewResolver/…�for�Spring�WebMVC�

• ex.�ejs,�handlebars,�mustache,�jade,�…�

• require()ing�NPM�modules�

• ex.�require("marked")�

• webpack.config.js�-�client�and�server�at�once�

• React�Isomorphic�Rendering�-�ReactDOMServer.renderToString()�

• Async.�React-Router�Isomorphic�Rendering�-�ReactRouter.match()

Time�Over

ENDHO�EYO�HE�HUM

­�Anonymous

“Do�not�reinvent�the�wheel,�but�make�it�perfect!”�

­�Anonymous

“Reinvent�the�wheel,�knowing�when�and�how.”�

­�Douglas�Crockford�

“The�good�thing�about�reinventing�the�wheel�is�that�you�can�get�a�

round�one.”�

– Linus Torvalds

“Just�for�Fun�;)”�

References• Spring�Framework:�http://projects.spring.io/spring-framework/�

• Node.js:�https://nodejs.org�

• React:�https://facebook.github.io/react/�

• React-Router:�https://github.com/reactjs/react-router�

• ScriptTemplate:�https://docs.spring.io/spring/docs/current/spring-framework-reference/html/view.html#view-script�

• J2V8:�https://github.com/eclipsesource/J2V8�

• Rhino:�https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Rhino�

• Nashorn:�http://openjdk.java.net/projects/nashorn/�

• JSR-223:�https://jcp.org/en/jsr/detail?id=223�

• Isomorphic�templating�with�Spring�Boot,�Nashorn�and�React:�https://speakerdeck.com/sdeleuze/isomorphic-templating-with-spring-boot-nashorn-and-react�

• Spring�mvc�서버로�Hybrid�Rendering�전략�질문:�https://slipp.net/questions/370�

• Spring�Project�JIRA�

• Support�JavaScript�Templating:�https://jira.spring.io/browse/SPR-12266�

• Server-side�JavaScript�improvements:�https://jira.spring.io/browse/SPR-13508�

• Remove�Velocity�support:�https://jira.spring.io/browse/SPR-13795�

• …

EVAL()의�귀환�RETURN�OF�THE�EVAL()Java/Spring과�Node.js의�공존�시즌3

Q&AMAY�THE�**SOURCE**�BE�WITH�YOU

ThanksTHAT’S�ALL�FOLKS