16. Bootstrap 개요
•CSS 초기화 기본 스타일
•12열 격자 시스템 : 고정 / 유동 레이아웃
•반응형 디자인
•코딩이 필요없는 UI 컴포넌트
•코딩이 필요한 UI 컴포넌트
•웹 기반 커스터마이징 도구
•Super-powered by Twitter
17. 부트스트랩 적용하기
!DOCTYPE html
meta name=”viewport” content=”
width=device-width,initial-scale=1.0” /
link rel=”stylesheet”
href=”bootstrap.css” /
link rel=”styleheet”
href=”bootstrap-responsive.min.ss” /
!--[if lt IE 9]
script src=”html5shiv.js”/script
![endif]--
script src=”jquery.min.js”/script
script src=”bootstrap.min.js”/script
18. CSS Reset 기본 스타일
•브라우저의 기본 스타일 차이 최소화
•Nomalize.css by Nicolas Gallagher
•http://necolas.github.com/
normalize.css/
•(더 나쁘지 않은) 기본 스타일
•HTML5 필수: ?DOCTYPE html
•IE8 이전 버전: html5shiv 등의 polyfill 필요
19. 12열 격자 시스템
고정 레이아웃
•전체 너비: 940px 고정
•.container
•.row
•.span1 ~ 12 / .offset1 ~ 12
•열의 너비 + 간격
•60px + 20px 고정
•@gridColumnWidth, @gridGutterWidth
•중첩된 열의 span 합계 = 부모 열의 span
20. 고정 레이아웃
3 예제 12 9
9
9
http://tomato.iolo.kr:3000/bootstrap/layout-fixed.html
34. 커스터마이징
• 웹 기반 커스터마이징 도구
• http://twitter.github.com/bootstrap/customize.html
• 사용할 컴포넌트 jQuery 플러그인 선택
• 글꼴, 색, 메트릭 설정
• 최적화된 빌드 다운로드
• 더 복잡한 커스터마이징을 하려면:
• 소스 코드: https://github.com/twitter/bootstrap
• LESS: http://lesscss.org
• jQuery jQuery UI
46. Backbone.Model
예제
var Item = Backbone.Model.extend({
urlRoot: '/todos'
});
var item = new Item({
title: 'Backbone 예제 만들기'
});
// HTTP POST 요청 -- 'sync' 이벤트 발생
item.save();
// cf. 동기 처리
item.save(null, {wait:true});
// cf. 콜백 처리
item.save(null, {
success: function (model) { },
error: function (model) { ... }
});
47. Backbone.Model
예제
var item = new Item({ id: 1 });
// HTTP GET 요청 -- 'sync' 이벤트 발생
item.fetch();
// 'change' 'change:title' 이벤트 발생
item.set({title:'Backbone 발표자료/예제 만들기'});
// HTTP PUT 요청 -- 'sync' 이벤트 발생
item.save();
// HTTP DELETE 요청 -- 'sync' 이벤트 발생
item.destroy();
// cf. 이벤트 처리
item.on('change', function(model) { ... });
item.on('sync', function (model) { ... });
48. Backbone.Collection
•Model의 집합 + DAO
•목록 변경에 따른 이벤트 발생
•풍부한 순회 함수
with Underscore.js
•저장소와 동기화
with Backbone.sync
•기본 동기화 방식은 RESTful
HTTP(with jQuery.ajax)
50. Backbone.Collection
예제
var Items = Backbone.Collection.extend({
model: Item,
url: '/todos'
});
var items = new Items();
// HTTP 요청없이 초기화 -- 'reset' 이벤트 발생
// 서버 사이드 템플릿에서 사용:
// ex. items.reset(%= @items.to_json %);
items.reset([
{id:123, title: 'first'},
{id:456, title: 'second'},
{id:789, title: 'third'}]
);
// HTTP GET 요청 -- 'reset' 이벤트 발생
items.fetch();
var item = items.get(123); // by id
var item = items.at(9); // by index
51. Backbone.Collection
예제
// HTTP POST 요청 -- 'add' 이벤트 발생
var item = items.create({title: 'Bootstrap 예제 만들기'});
// HTTP POST 요청 -- 'add' 이벤트 발생
items.add({title: 'AngulaJS 예제 만들기'});
// HTTP POST, PUT, DELETE 요청
// -- 'add', 'remove', 'change'등의 해당하는 이벤트 발생
items.update(item);
items.update([ item1, model2, model3 ]);
// HTT DELETE 요청 -- 'remove' 이벤트 발생
items.remove(item); // by model
items.remove(123); // by id
items.remove([123, 456, 789]); // by id
items.remove([item1, item2, item3]); // by model
72. 모듈
• 모듈(module)은 컨트롤러(controller), 서비스(service), 지시
자(directive), 필터(filter) 등의 컨테이너/패키지/빌더팩토리
• HTML 페이지는 하나의 모듈(앱 모듈)과 결함
• ng-app 지시자, angular.bootstrap() API, 의존성 주입
• 웹앱의 모듈 구성(권장)
• 서비스 모듈
• 지시자 모듈
• 필터 모듈
• 앱 모듈: 초기화 코드 등
73. 모듈
API
• angular.module(name, requires[, configFn])
• .config(configFn)
• .run(initializerFn))
• .constant(name, obj)
• .value(name, value)
• .controller(name, constructor)
• .service(name, constructor)
• .directive(name, directoryFactory)
• .filter(name, filterFactory)
• .factory(name, providerFn)
• .provider(name, providerType)
• config(), run()을 제외한 함수는 다른 제공자 API를 호출하는 편의 함수
74. 모듈
예제
angular.module('services',[ 'controllers' ])
// 모듈 설정 -- 제공자만 주입 가능
.config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/items', {
templateUrl: 'partials/items.html', controller: 'itemListCtrl'
});
...
}])
// 모듈 초기화
.run(['$rootScope', function ($rootScope) {
$rootScope.on('error', function (err) { ... });
...
}]);
// 서비스 정의
.factory('apiService', [ '$http', function ($http) {
return {
loadItems: function(callback) { ... callback(items); },
saveItem: function(item) { ... },
deleteItem: function(item) { ... },
};
}]);
75. 의존성 주입
• Dependency Injection(DI)는 코드 간의 의존성을 해결하기 위
한 소프트웨어 디자인 패턴
• http://en.wikipedia.org/wiki/Dependency_injection
• http://martinfowler.com/articles/injection.html
• angular.injector API
• annotate(injectingFunc)
• get(name)
• instantiate(constructorFunc, locals)
• invoke(func, self, locals)
76. 의존성 주입
예제
// 의존성 자동 주입
angular.module('app', [ 'services' ])
.run([
'$rootScope',
'apiService',
function (root, api) {
api.loadItems(function (items) {
root.items = items;
});
}
]);
// 의존성 수동 해결(!)
var injector = angular.injector(['services', 'ng']);
var $rootScope = injector.get('$rootScope'); // from 'ng' 모듈
var apiService = injector.get('apiService'); // from 'services' 모듈
apiService.loadItems(function (items) {
$rootScope.items = items;
});
77. Scope
• 모델 or 모델의 컨테이너
• 표현식(expression)의 실행 문맥(execution context)
• 계층 구조
• 자식 Scope는 부모 Scope의 속성을 상속(mixin)
• 컨트롤러와 일부 지시자들은 자식 Scope를 생성
• 최상위 Scope: $rootScope
• Scope 이벤트는 상위 Scope로 전파: $emit()
• Scope 이벤트는 하위 Scope로 전파: $broadcast()
• Scope는 DOM 노드와 결합: angular.element(aDomElement).scope()
• 모델 변화를 감시: $watch()
• AngularJS 외부에서 발생한 모델 변화를 내부에 전달: $apply()
80. Scope
예제
// 다른 모듈에서 $rootScope에서 발생한 이벤트 감시
angular.module('errorLogger', [])
.run(['$rootScope', function ($rootScope) {
$rootScope.on('httpError', function(event, error) {
console.error('http error: ', error);
});
}]);
// 다른 모듈에서 상위 Scope($rootScope)에서 상속한 속성 감시
angular.module('controllers', [])
.controller('itemEditCtrl',
['$rootScope', '$scope', function ($rootScope, $scope) {
$rootScope.$watch('pendingHttpRequests', function(old, new)) {
$scope.submitDisabled = (new 3);
});
}]);
// 뷰 템플릿에서 상위 Scope($rootScope)에서 상속한 속성 참조
div ng-show=pendingHttpRequestsloading.../div
81. 컨트롤러
• 컨트롤러는 하나의 Scope와 결합
• ng-controller 지시자, $route 서비스 또는 scope.$new() API
• 컨트롤러의 역할
• Scope 초기화
• Scope에 행위(behavior; 이벤트 핸들러) 추가
• 컨트롤러에서 하면 안되는 것들(권장)
• DOM 조작 -- 지시자 사용
• 입력 포매팅 -- Form Control 지시자 사용
• 출력 필터링 -- 필터 사용
• 다른 컨트롤러 접근 -- 서비스 사용
• 다른 컴포넌트의 생성 및 라이프 사이클 관리
82. 컨트롤러
예제
// 쉬운 방법
// -- 파라메터의 이름을 통해서 의존성 자동 주입
function ItemListCtrl($scope, $location, apiService) {
apiService.loadItems(function (items) {
$scope.items = items;
});
$scope.editItem = function (item) {
$location.path('/items/' + item.id + '/edit');
};
$scope.deleteItem = function (item) {
apiService.deleteItem(item);
};
}
// 어노테이션을 이용한 명시적 의존성 주입
// -- 자바스크립트 난잡화(UglyfyJS같은) 적용할 경우에는 필수
ItemListCtrl.$inject = ['$scope', '$location', 'apiService'];
83. 컨트롤러
예제
// 좀 더 복잡하지만 뽀대나는 방법
angular.module('controllers', [ ])
.controller('itemListCtrl', [
'$scope',
'$location',
'apiService',
function($scope, $location, apiService) {
apiService.loadItems(function (items) {
$scope.items = items;
});
$scope.editItem = function (item) {
$location.path('/items/' + item.id + '/edit');
};
$scope.deleteItem = function (item) {
apiService.deleteItem(item);
};
}
]);
84. 뷰 템플릿
• 결합된 Scope 및 상위 Scope들의 속성을 포함한 자바스크립트와 유사한 표현식
• {{ 표현식 }}
• 예) {{ title }}, {{ item.length }}, {{ 1 + 2 }},
{{ 'HelloWorld'.substring(5) }}
• 필터
• {{ 속성 | 필터 }}
• 예: {{ title | uppercase }}
• {{ 속성 | 필터:옵션 }}
• 예: {{ created | date:'yyyy-MM-dd HH:mm:ss Z' }}
• {{ 속성 | 필터1 | 필터2 | 필터3 }}
• 예: li ng-repeat=item in items |
filter:searchText | orderBy:created
86. 뷰 템플릿
예제
html ng-app=app
...
body ng-controller=mainCtrl
header
div ng-include='common-header.html'/div
div ng-show=currentUser
pWelcome, {{currentUser.userame}}!/p
button ng-click=logout()Logout/login
/div
div ng-hide=currentUser ng-controller=loginCtrl
input type=text ng-model=username /
input type=password ng-model=password /
button ng-click=login()Login/login
a href=#/signupSign Up!/a
/div
/header
...
87. 뷰 템플릿
예제
div ng-controller=itemListCtrl
pThere're {{items.length}} items/p
ul
li ng-repeat=item in items
p{{title}}/p
pposted at {{created | date:'medium'}}/p
a href=#/item/{{id}}/editEdit/a
button ng-click=delete(item)Delete/button
/li
/ul
/div
div ng-controller=itemAddCtrl
form ng-submit=addItem()
input type=text ng-model=newItem.title /
button type=submitAdd/button
/form
/div
...
88. AngularJS의 MVC
$rootScope ItemListCtrl Scope ng-repeat Scope
items id
delete() title
html ng-app function ItemListCtrl($scope) {
$scope.items = [
div ng-controller=ItemListCtrl
{id:1, title:'first'},
ul
{id:2, title:'second'},
li ng-repeat=item in items
{id:3, title:'third'}
{{item.title}} ];
button ng-click=delete(item)
Delete/button $scope.delete=function(item) {
delete $scope.items[item.id];
/li
};
/ul
}
/div
89. 라우팅
• 앱 모듈의 설정 단계에서, $routeProvider의 API를 통해 설정
• $routeProvider.when(path, route)
• path: 라우팅 경로. URL 해시(#)
• 경로 내에 :name 형식의 파라메터가 포함되면 $routeParams 서비스를
통해 전달.
• route: 라우팅 설정
• templateUrl: 템플릿 경로. ng-view 지시자가 사용.
• template: 템플릿 문자열.
• controller: 컨트롤러(서비스 ID 또는 생성자). $route, $routeParams
서비스를 주입할 수 있음.
• redirectTo: 리디텍트 경로(또는 경로를 리턴하는 함수)
• $routeProvider.otherwise(path): 기본 라우팅 경로
101. 클래식 웹앱
with Express
•Express on Nodejs
•Server-side rendering
with “jade” template
engine.
•Nothing Specials!
http://tomato.iolo.kr:3000/express
102. 단일 페이지 웹앱
with Backbone.js
•Backbone.js
•Client-side rendering
with Underscore.js
•RESTful API Sever with
Express on Node.js
http://tomato.iolo.kr:3000/backbone/
103. 단일 페이지 웹앱
with AngularJS
•AngularJS + Twitter
Bootstrap
•Client-side rendering
with AngularJS
•RESTful API Sever with
Express on Node.js
http://tomato.iolo.kr:3000/angular/
104. Epilogue
이미지 출처: http://barry-overstreet.com/you-are-your-future/
105. 프론트엔드 웹앱 이슈(1)
검색 엔진 최적화(SEO)
• Seach Engine Cloaking
• IP 주소나 User-Agent에 따라 봇을 위한 별도의 페이지 제공
• http://en.wikipedia.org/wiki/Cloaking
• http://support.google.com/webmasters/bin/
answer.py?hl=enanswer=66355
• AJAX Crawling - Hashbang(#!)
• https://developers.google.com/webmasters/ajax-
crawling/
• #!key=value -- ?_escaped_fragment_=key=value
106. 프론트엔드 웹앱 이슈(2)
접근성(Accessibility)
•동적으로 바뀌는 DOM 노드는 스크린 리더에게 넘사벽?
•Accessible Rich Internet Application(ARIA)
•http://en.wikipedia.org/wiki/WAI-ARIA
•최신 HTML5, CSS3가 지원되지 않는 브라우져? 자바스크
립트가 지원되지 않는 브라우져?
•Progressive Enhancement: http://
en.wikipedia.org/wiki/Progressive_enhancement
•Unobtrusive Javascript: http://en.wikipedia.org/
wiki/Unobtrusive_JavaScript
107. 프론트엔드 웹앱 이슈(3)
히스토리
•이전 / 다음 버튼 북마크
•화면의 각 단계마다 고유한 URL 해시(#) 부여
•window.location.hash 속성
•window.onhashchange 이벤트
•HTML5 브라우저 히스토리 API
•window.history.pushState()/popState()
•window.onpopstate 이벤트
108. 프론트엔드 웹앱
주요 프레임웍 비교
프레임웍 모듈-뷰 바인딩 UI 컴포넌트 HTML/CSS 친화도 확장성
Backbone.js X X O O
SprouteCore O O X X
Sammy.js X X O O
Spine.js X X O O
Cappuccino O O X X
Knockout.js O X O O
JavascriptMVC X O O O
Google Web Tookit X O X X
Google Closure X O X X
Ember.js O O O O
AngularJS O X O O
Batman.js O X O O
출처: http://codebrief.com/2012/01/the-top-10-javascript-mvc-frameworks-reviewed/