웹 애플리케이션 프레임웍의 과거,현재 그리고 미래 - 봄날은 간다13. 차례
Prologue
...
Past
WWW
43. 프레임웍
Epilogue
... 2
2
69. Past
WWW
CGI
WAS
Frameworks
1990 2000 2012
6
96. W3C
8
1990 2000 2012
8
122. “위임”
SERVER_PROTOCOL,
132. ...
12
1990 2000 2012
12
133. CGI
printf(%s%c%cn, Content-Type:text/html, 13, 10);
printf(htmlheadtitleMultiplication results
/title/headbody);
printf(h3results/h3);
char *data = getenv(QUERY_STRING);
if(data == NULL) {
printf(pError!/p);
} else if(sscanf(data,m=%ldn=%ld,m,n) != 2) {
printf(pError!/p);
} else {
printf(pThe product of %ld and %ld is
b%ld/b./p,m,n,m*n);
}
printf(/body/html);
13
13
184. ...
15
1990 2000 2012
15
185. WAS
%@ page language=”java”%
html
headtitleMultiplication results/title/head
body
h3Multiplication results/h3
% try {
long m = Long.parseLong(request.getParameter(“m”));
long n = Long.parseLong(request.getParamter(“n”));
%
p
The product of %= m % and %= n % is
b%= (m*n) %/b.
/p
% } catch(Exception e) { %
pError!/p
% } %
/body
/html
16
16
274. You.
Inversion-of-Control
Where
277. 프레임웍
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ServletLifeCycleExample extends HttpServlet {
private int count;
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config); getServletContext().log(init() called); count=0;
}
@Override
protected void service(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
getServletContext().log(service() called); count++;
response.getWriter().write(Incrementing the count: Count = +count);
}
@Override
public void destroy() {
getServletContext().log(destroy() called);
}
}
19
19
287. 2.0
Model-View-Controller
웹
319. ...
22
1990 2000 2012
22
320. MVC
class ProductModel {
long multiplier, multiplicant, product; ... M
}
class CalcService {
long getProduct(long m, long n) { return m * n; } ...
}
jsp:useBean id=”model” class=”ProductBean”/
h3Multiplication results/h3 V
pThe product of jsp:getProperty name=”model” property=”multiplier”/ and
jsp:getProperty name=”model” property=”multiplicand”/ is
bjsp:getProperty name=”model” property=”product”//b./p
long m = Long.parseLong(request.getParameter(“m”));
long n = Long.parseLong(request.getParameter(“n”)); C
ProductModel model = new ProductModel(m, n, calcService.getProduct(m, n));
request.setAttribute(“model”, model);
getServletContext().getRequestDispatcher(“mul.jsp”).forward(request, response);
23
23
341. 손~”
管理理
Convention-over-Configuration,
353. ...
25
1990 2000 2012
25
388. cares?
27
1990 2000 2012
27
401. Future
모바일, 소셜 클라우드
비동기 프레임웍
경량 웹프레임웍
프론트엔드 웹프레임웍
Play! 프레임웍
1990 2000 2012
29
463. ...
36
1990 2000 2012
36
466. 비동기
if (fs.existsSync(/etc/passwd)) {
var data = fs.readFileSync(/etc/passwd);
console.log(data);
}
fs.exists(/etc/passwd, function (exist) {
if (exist) {
fs.readFileSync(/etc/passwd, function (err, data) {
console.log(b); console.log(data);
});
}
}); console.log(a);
(1)
484. 멀티쓰레드
서버
▶
1 || || 2
▶
클라이언트
▶ ▶ Long
486.
Task
▶ ▶
4 3
응답
38
38
495.
서버
|| || ▶
1 3
클라이언트
Long
▶ ▶ I/O
▶ ▶ Task
5
6 4
응답
40
40
504. 멀티쓰레드
서버 Worker
1
1 || || ▶ ▶
|| ||
▶
클라이언트
▶ ▶ 2 2 3
▶ ▶
3 Long
544. ...
44
1990 2000 2012
44
548. Sinatra
$ gem install sinatra
$ cat hello.rb
require 'sinatra'
get '/hello/:name' do |name|
'Hello, #{name}'
end
$ ruby -rubygems hello.rb
45
45
552. Flask
$ pip install Flask
$ cat hello.py
from flask import Flask
app = Flask(__name__)
@app.route(/hello/name, methods=[GET])
def hello(name):
return Hello, %s % name
if __name__ == __main__:
app.run()
$ python hello.py
46
46
556. Express
$ npm intall express
$ cat hello.js
var express = require('express'),
app = express();
app.get('/hello/:name', function (req, res) {
res.send('Hello, ' + req.param('name'));
});
app.listen(3000);
$ node hello
47
47
560. Spray
$ git clone git://github.com/spray/spray-template.git .
$ cat src/main/scala/hello.scala
import cc.spray._
trait HelloService extends Directives {
val helloService = {
path(hello / PathElement) {
name = get {
completeWith {
hello, + name
}
}
}
}
}
$ sbt run
48
48
564. 웹프레임웍
Web-as-a-Platform!!
URL
599. ...
49
1990 2000 2012
49
603. Backbone.js
script type=text/template this.defaults().title}); }
id=item-template },
div class=view ...
input class=toggle });
type=checkbox var TodoView =
%=done?'checked=checked':''%/ Backbone.View.extend({
label%= title %/label template: _.template(
a class=destroy/a $('#item-template').html()),
/div initialize: function() {
input class=edit type=text this.model.on('change',
value=%= title % / this.render, this);
/script this.model.on('destroy',
this.remove, this);
script type=text/javascript },
var Todo = Backbone.Model.extend({ render: function() {
defaults: function() { this.$el.html(this.template(
return { this.model.toJSON()));
title: empty todo..., this.$el.toggleClass('done',
order: Todos.nextOrder(), this.model.get('done'));
done: false return this;
}; },
}, ...
initialize: function() { });
if (!this.get(title)) { /script
this.set({title:
출처: http://todomvc.com 50
50
607. Knockout.js
select data-bind=options:tickets,optionsCaption:'Choose...',
optionsText:'name',value:chosenTicket/select
button data-bind=enable:chosenTicket,click:resetTicketClear/button
p data-bind=with:chosenTicket
You have chosen b data-bind=text:name/b
($span data-bind=text:price/span)
/p
script type=text/javascript
function TicketsViewModel() {
this.tickets = [
{ name: Economy, price: 199.95 },
{ name: Business, price: 449.22 },
{ name: First Class, price: 1199.99 }
];
this.chosenTicket = ko.observable();
this.resetTicket = function() { this.chosenTicket(null) }
}
ko.applyBindings(new TicketsViewModel(),
document.getElementById(liveExample));
/script
51
51
613. JS
Ext.define('User', {
extend: ‘Ext.data.Model’,
fields: [
{name: ‘name’, type: ‘string’},
{name: ‘age’, type: ‘int’},
{name: ‘pic’, type: ‘string’}
]
});
var myStore = Ext.create(‘Ext.data.Store’, {
model: ‘User’,
proxy: {
type: ‘ajax’,
url : ‘/users.json’,
reader: { type: ‘json’, root: ‘users’ }
},
autoLoad: true
});
Ext.create(‘Ext.DataView’, {
fullscreen: true,
store: myStore,
itemTpl: ‘img src=”{pic}” /h2{name}/h2p{age} years old/p’
});
52
52
650. 처리
53
1990 2000 2012
53
655. 구조
app → Application sources
! assets → Compiled asset sources
! stylesheets → Typically LESS CSS sources
! javascripts → Typically CoffeeScript sources
! controllers → Application controllers
! models → Application business layer
! views → Templates
conf → Configurations files
! application.conf → Main configuration file
! routes → Routes definition
public → Public assets
! stylesheets → CSS files
! javascripts → Javascript files
! images → Image files
project → sbt configuration files
! build.properties → Marker for sbt project
! Build.scala → Application build script
! plugins.sbt → sbt plugins
lib → Unmanaged libraries dependencies
logs → Standard logs folder
target → Generated stuff
test → source folder for unit or functional tests
54
54
659. Routes
GET / controllers.Projects.index()
# Authentication
GET /login controllers.Application.login()
POST /login controllers.Application.authenticate()
GET /logout controllers.Application.logout()
# Projects
POST /projects controllers.Projects.add()
POST /projects/groups controllers.Projects.addGroup()
DELETE /projects/groups controllers.Projects.deleteGroup(group: String)
PUT /projects/groups controllers.Projects.renameGroup(group: String)
DELETE /projects/:project controllers.Projects.delete(project: Long)
PUT /projects/:project controllers.Projects.rename(project: Long)
POST /projects/:project/team controllers.Projects.addUser(project: Long)
DELETE /projects/:project/team controllers.Projects.removeUser(project:Long)
...
# Map static resources from the /public folder to the /public path
GET /assets/*file controllers.Assets.at(path=/public, file)
55
55
663. Java
package controllers;
import play.*;
import play.mvc.*;
public class Application extends Controller {
public static Result hello(String name) {
return ok(views.html.index.render(Hello + name));
}
public static Result upload() {
FilePart filePart =
request().body().asMultipartFormData().getFile(file);
if (filePart != null) {
// ... filePart.getFilename()/getContentType()/getFile() ...
return ok(h1file uploaded/h1).as(text/html);
} else { return BadRequest(file upload error!) }
}
public static Result download() {
return ok(new java.io.File(/tmp/fileToServe.pdf));
}
}
56
56
667. Scala
package controllers
import play.api._
import play.api.mvc._
object Application extends Controller {
def hello(name:String) = Action {
Ok(views.html.hello(Hello + name))
}
def upload = Action {
request.body.file(file).map { filePart =
// ... filePart.filename/contentType/ref ...
Ok(h1file uploaded/h1).as(HTML)
}.getOrElse {
BadRequest(file upload error!)
}
}
def download = Action {
Ok.sendFile(new java.io.File(/tmp/fileToServe.pdf))
}
}
57
57
672. Template
@(title: String)(content: Html)
html
head
title@title/title
link rel=stylesheet href=@routes.Assets.at(stylesheets/main.css)
script src=@routes.Assets.at(javascripts/jquery.js)/script
/head
body
header
a href=@routes.Application.index@title/a
/header
section
@content
/section
/body
/html
@(name: String, repeat: Int, color: String)
@main(Here is the result:) {
ul style=color: @if(color != null) { @color } else { inherited }
@for(i - 1 to repeat) {
liHello @name!/li
}
/ul
p class=buttons
a href=@routes.Application.indexBack to the form/a
/p
}
58
58
676. Akka
def hello = Action {
Async {
val myActor =
Akka.system.actorOf(Props[MyActor], name = myactor)
(myActor ? hello).mapTo[String].asPromise.map {
result = Ok(Greetings, + result)
}
}
}
def upload = Action {
Async {
Akka.future {
longTask()
}.map {
result = Ok(Got + result)
}
}
}
59
59