SlideShare a Scribd company logo
1 of 35
+
한장현
han41858@gmail.com
han41858.tistory.com
1
• 전 삼성SDS 선임
• TV플랫폼 JavaScript 어플리케이션 구현
• 리테일 솔루션 서버 & 프론트엔드 구현
• 프리랜서 개발자
• han41858.tistory.com 블로그 운영
• Angular 2 번역서 집필중
• GDG Korea Web Tech 운영진
한장현 (Janghyun Han)
2
3
ngular
1.6.0-rc.2 safety-insurance
4
• 마술 같은 2-way binding
• HTML 표준을 기반으로 기능 확장
• 체계적인 컴포넌트 구성, Web Component로 가는 길
• Front-end 전체를 커버하는 프레임워크
• Google 에서 관리, 개선
• 풍부한 사용자 삽질 경험
Angular를 쓰는 이유
5
Class, inheritance
import/export
Arrow function
Promise
ECMAScript 2015
6
• 간단해지는 코드, syntax sugar
• 클래스, 상속, 모듈 구성 ⇒ 아키텍처 진화
• 브라우저들 지원 계속
• 결국엔 표준, transpiler는 거쳐갈 뿐
ES6를 쓰는 이유
7
8
ES6ES5
script src
<script src="bundle.js"></script>
"devDependencies": {
"angular": "^1.5.8",
"babel-cli": "^6.18.0",
"babel-loader": "^6.2.7",
"babel-preset-es2015": "^6.18.0",
"webpack": "^1.13.3"
}
<script src="angular.js"></script>
<script src="index.js"></script>
"devDependencies": {
"angular": "^1.5.8"
}
9
index.js
ES6ES5
(function () {
var ngApp = angular.module('angular1es5', []);
})();
import angular from 'angular';
(() => {
const ngApp = angular.module('angular1es6', []);
})();
10
Webpack
// this is ES5
var webpack = require('webpack');
module.exports = {
entry : [
'./index.js'
],
output : {
filename : 'build/bundle.js',
sourceMapFilename: '[name].map'
},
module : {
loaders : [
{
test : /.js$/,
loader : 'babel?presets[]=es2015
exclude : /node_modules/
},
{
test : /.pug$/,
loader : 'pug-loader',
exclude : /node_modules/
}
]
},
plugins : [
// new webpack.optimize.UglifyJsPlugin({minimize: true})
]
};
webpack.config.js
"devDependencies": {
"angular": "^1.5.8",
"angular-route": "^1.5.8",
"babel-cli": "^6.18.0",
"babel-loader": "^6.2.7",
"babel-preset-es2015": "^6.18.0",
"file-loader": "^0.9.0",
"pug": "^2.0.0-beta6",
"pug-loader": "^2.3.0",
"webpack": "^1.13.3",
"webpack-dev-server": "^1.16.2"
}
package.json
11
export default class HomeCtrl {
constructor () {
console.log('HomeCtrl.constructor()');
}
}
/view/homeCtrl.js
p this is home
/view/home.pug
import angular from 'angular';
import ngRoute from 'angular-route';
import HomeCtrl from './view/homeCtrl';
const main = () => {
console.log('main()');
const ngApp = angular.module('angular1es6', ['ngRoute']);
ngApp.config(($routeProvider, $locationProvider) => {
console.log('this is angular config');
$routeProvider
.when('/', {
template : require('./view/home.pug'),
controller : 'HomeCtrl',
controllerAs : 'Ctrl'
})
.otherwise({
redirectTo : '/'
});
// need to angular.js routing
$locationProvider.html5Mode({
enabled : true,
requireBase : false
});
});
ngApp.controller('HomeCtrl', HomeCtrl);
};
main();
index.js + ngRoute
12
webpack-dev-server
13
ngApp.directive('CustomDirective', () => new CustomDirective);
ngApp.filter('groupBy', GroupBy);
ngApp.service('CustomSvc', CustomSvc);
ngApp.controller('CustomCtrl', CustomCtrl);
Angular Components
ngApp.directive('CustomDirective', CustomDirective);
ngApp.filter('groupBy', GroupBy);
ngApp.service('CustomSvc', CustomSvc);
ngApp.controller('CustomCtrl', CustomCtrl);
function
Class
new Class
14
Filter
ES6ES5
ngApp.filter('uppercase', uppercase);
function uppercase () {
return function (item) {
return item.toUpperCase();
};
}
<script src="uppercase.filter.js"></script>
const uppercase = () => {
return (input) => {
return input.toUpperCase();
};
};
export default uppercase;
import uppercase from './uppercase.filter';
ngApp.filter('uppercase', uppercase);
15
.ctrlRoot
p this is home ctrl
p {{ Ctrl.title }}
button(ng-click="Ctrl.select()") Select
export default class HomeCtrl {
constructor () {
console.log('HomeCtrl.constructor()');
this.title = 'this is title';
}
select () {
console.log('HomeCtrl.select()');
}
}
$routeProvider
.when('/', {
template : require('./view/home.pug'),
controller : 'HomeCtrl',
controllerAs : 'Ctrl'
})
ngApp.controller('HomeCtrl', HomeCtrl);
function HomeCtrl ($scope) {
console.log('home controller');
$scope.title = 'this is title';
$scope.select = function () {
console.log('HomeCtrl.select()');
}
}
Controller
ES6ES5
.ctrlRoot
p this is home ctrl
p {{ title }}
button(ng-click="select()") Select
16
Service
ES6ES5
ngApp.service('myService', myService);
<script src="./view/myService.js"></script>
function myService () {
this.testFnc = function () {
console.log('myService.testFnc()');
};
return this;
}
export default class MyService {
constructor () {
console.log('MyService');
}
testFnc () {
console.log('MyService.testFnc()');
}
}
ngApp.service('MyService', MyService);
export default class HomeCtrl {
constructor (MyService) {
this.MyService = MyService;
}
select () {
this.MyService.testFnc();
}
}
static 있어야 할 것 같지만 없어야 함
17
ngApp.directive('myDirective', () => new MyDirective);
export default class MyDirective {
constructor () {
console.log('MyDirective.constructor()');
this.restrict = 'E';
this.template = '<p>message : {{ this.msg }}</p>';
this.scope = {
msg : '@'
};
}
link (scope) {
console.log(scope.msg);
}
}
ngApp.directive('myDirective', myDirective);
function myDirective () {
return {
restrict : 'E',
template : '<p>message : {{ msg }}</p>',
scope : {
msg : '@'
},
controller : function ($scope) {
console.log('myDirective.controller()');
console.log($scope.msg);
}
}
}
<script src="myDirective.js"></script>
Directive
ES6ES5
directive 등록할 때 () => new18
Directive vs. Component
19
Directive vs. Component
const customInput = {
bindings : {
model : '='
},
template : '<input ng-model="$ctrl.model"></input>',
controller : function () {
this.$onInit = () => {
}
}
};
export default customInput;
ngApp.component('customInput', customInput);ngApp.directive('customInput', () => new customInput);
export default class customInput {
constructor () {
this.restrict = 'E';
this.scope = {
model : '='
};
this.template = '<input ng-model="model"></input>';
}
controller () {
}
}
20
static delete (param) {
const self = this;
return util.objValidate(param, {
userID : Constants.TYPE.EMAIL
}, Constants.ERROR.USER_CTRL.NO_PARAMETER, log, 'delete()')
.then(param => self.isExists(param))
.then(param => {
// delete records
return recordCtrl.deleteAll({
userID : param.userID
})
.then(() => {
log('remove records ok');
// param 자체를 다시 돌려주기 위해 Promise 필요
return Promise.resolve(param);
});
})
.then(param => {
// delete cards
return cardCtrl.deleteAll({
userID : param.userID
})
.then(() => {
log('remove cards ok');
return Promise.resolve(param);
});
})
.then(param => {
// delete assets
return assetCtrl.deleteAll({
userID : param.userID
})
.then(() => {
log('remove assets ok');
return Promise.resolve(param);
});
})
.then(param => {
// delete user
return User.remove({
userID : param.userID
})
.then(() => {
return Promise.resolve(param);
}, error => {
log(error);
return Promise.reject(new ERROR(Constants.ERROR.MONGOOSE.REMOVE_FAILED, log, 'delete()'));
});
})
.then(param => {
log(`delete ok : ${param.userID}`);
return Promise.resolve(true);
});
}
Promise
21
ngApp.config(($routeProvider, $locationProvider) => {
// include styles
require('./view/home.styl');
$routeProvider
.when('/', {
template : require('./view/home.pug'),
controller : 'HomeCtrl',
controllerAs : 'Ctrl'
})
.otherwise({
redirectTo : '/'
});
});
배포 : webpack
import가 아니므로 require 22
Angular 1 + ES6 + BDD
= Hell
23
describe('homeCtrl.test', () => {
it('module import', () => {
expect(true).to.be.true;
});
});
λ karma start
(node:7564) DeprecationWarning: Using Buffer without `new` will soon stop working. Use `new
Buffer()`, or preferably `Buffer.from()`, `Buffer.allocUnsafe()` or `Buffer.alloc()` instead.
18 11 2016 02:53:45.852:INFO [framework.browserify]: bundle built
18 11 2016 02:53:45.941:INFO [karma]: Karma v1.3.0 server started at http://localhost:9876/
18 11 2016 02:53:45.941:INFO [launcher]: Launching browser Chrome with unlimited concurrency
18 11 2016 02:53:45.952:INFO [launcher]: Starting browser Chrome
18 11 2016 02:53:47.283:INFO [Chrome 54.0.2840 (Windows 10 0.0.0)]: Connected on socket
/#AjAqCwTlrwmVmV_sAAAA with id 16857313
Chrome 54.0.2840 (Windows 10 0.0.0): Executed 1 of 1 SUCCESS (0.005 secs / 0.001 secs)
BDD 시작
24
λ karma start
(node:12196) DeprecationWarning: Using Buffer without `new` will soon stop working. Use `new Buffer()`, or preferably
`Buffer.from()`, `Buffer.allocUnsafe()` or `Buffer.alloc()` instead.
18 11 2016 02:19:10.237:INFO [framework.browserify]: bundle built
18 11 2016 02:19:10.343:INFO [karma]: Karma v1.3.0 server started at http://localhost:9876/
18 11 2016 02:19:10.343:INFO [launcher]: Launching browser Chrome with unlimited concurrency
18 11 2016 02:19:10.353:INFO [launcher]: Starting browser Chrome
18 11 2016 02:19:11.676:INFO [Chrome 54.0.2840 (Windows 10 0.0.0)]: Connected on socket /#sBpP4RL0XFZAwPtxAAAA with id 52822107
Chrome 54.0.2840 (Windows 10 0.0.0) ERROR
Uncaught SyntaxError: Unexpected token import
at test/homeCtrl.test.js:1
import HomeCtrl from '../view/homeCtrl';
describe('homeCtrl.test', () => {
it('module import', () => {
console.log(HomeCtrl);
expect(true).to.be.true;
expect(HomeCtrl).to.be.ok;
});
});
λ karma start
(node:11580) DeprecationWarning: Using Buffer without `new` will soon stop working. Use `new Buffer()`, or preferably
`Buffer.from()`, `Buffer.allocUnsafe()` or `Buffer.alloc()` instead.
18 11 2016 02:31:24.248:INFO [framework.browserify]: bundle built
18 11 2016 02:31:24.339:INFO [karma]: Karma v1.3.0 server started at http://localhost:9876/
18 11 2016 02:31:24.339:INFO [launcher]: Launching browser Chrome with unlimited concurrency
18 11 2016 02:31:24.349:INFO [launcher]: Starting browser Chrome
18 11 2016 02:31:25.657:INFO [Chrome 54.0.2840 (Windows 10 0.0.0)]: Connected on socket /#pvpyGrXqq2TZPTgmAAAA with id 30236974
LOG: class HomeCtrl { ... }
Chrome 54.0.2840 (Windows 10 0.0.0): Executed 1 of 1 SUCCESS (0.007 secs / 0.002 secs)
babel : node6
λ karma start
(node:13196) DeprecationWarning: Using Buffer without `new` will soon stop working. Use `new Buffer()`, or preferably
`Buffer.from()`, `Buffer.allocUnsafe()` or `Buffer.alloc()` instead.
18 11 2016 02:58:38.638:INFO [framework.browserify]: bundle built
18 11 2016 02:58:38.728:INFO [karma]: Karma v1.3.0 server started at http://localhost:9876/
18 11 2016 02:58:38.729:INFO [launcher]: Launching browser PhantomJS with unlimited concurrency
18 11 2016 02:58:38.738:INFO [launcher]: Starting browser PhantomJS
18 11 2016 02:58:40.301:INFO [PhantomJS 2.1.1 (Windows 8 0.0.0)]: Connected on socket /#JeRwavdozVZCC8HJAAAA with id 75347319
LOG: function HomeCtrl(MyService) { ... }
PhantomJS 2.1.1 (Windows 8 0.0.0): Executed 1 of 1 SUCCESS (0.008 secs / 0.001 secs)
babel : es2015
ES6가 돌지 않는다…
+
25
var $httpBackend;
beforeEach(function () {
module('angular1es5');
inject(function (_$httpBackend_) {
$httpBackend = _$httpBackend_;
});
});
module 선언, injection 불가
ES6ES5
const $injector, $httpBackend;
beforeEach(() => {
$injector = angular.injector(['angular1es6']);
$httpBackend = $injector.get('$httpBackend');
});
Object is not a constructor (evaluating 'module('angular1es6')')
r:/temp/test/homeCtrl.test.js:15:9 <-
R:/temp/3871fde1c6cf6c302eeae7add18a3b02.browserify:22:9
26
let ngApp = angular.module('angular1es6', ['ngMock']);
ngMock vs. ngMockE2E
The ngMock module provides support to inject
and mock Angular services into unit tests. In
addition, ngMock also extends various core ng
services such that they can be inspected and
controlled in a synchronous manner within test
code.
The ngMockE2E is an angular module which
contains mocks suitable for end-to-end testing.
Currently there is only one mock present in this
module - the e2e $httpBackend mock.
ngMock ngMockE2E
Fake HTTP backend implementation suitable for end-to-
end testing or backend-less development of applications
that use the $http service.
Fake HTTP backend implementation suitable for unit
testing applications that use the $http service.
.when()
.expect()
.flush()
.verifyNoOutstandingExpectation()
.verifyNoOutstandingRequest()
.resetExpectations()
.when()
ngMockE2E에는 $location 없음 27
Promise + http.flush()
Chrome 54.0.2840 (Windows 10 0.0.0) homeCtrl.test http test ok FAILED
Error: No pending request to flush !
at Function.$httpBackend.flush (node_modules/angular-mocks/angular-mocks.js:1799:34)
at r:/temp/test/homeCtrl.test.js:36:17
promise 함수로 부르면 동작 안함
flush() 타이밍 달라짐
flush는 Util에서 수행
const $injector = angular.injector(['angular1es6']);
const $httpBackend = $injector.get('$httpBackend');
const $http = $injector.get('$http');
beforeEach(() => {
$httpBackend.expectGET('/test')
.respond(['this', 'is', 'GET', 'test', 'data']);
});
it('ok', () => {
return new Promise(resolve => {
$http.get('/test').then(result => {
console.log('get().then()');
console.log(result);
console.log(result.data);
resolve(true);
});
$httpBackend.flush();
});
});
동작하는 코드
static post (uri, param, config) {
// use new promise for flush()
return new Promise((resolve, reject) => {
this.http.post(uri, param, config)
.then(result => {
resolve(result);
}, error => {
console.error(error);
reject(false);
});
if (this.httpBackend && this.httpBackend.flush) {
this.httpBackend.flush();
}
});
}
it('ok', () => {
return new Promise(resolve => {
Promise.resolve()
.then(() => {
$http.get('/test').then(result => {
console.log('get().then()');
console.log(result);
console.log(result.data);
resolve(true);
});
});
$httpBackend.flush();
});
});
28
const $httpBackend = $injector.get('$httpBackend');
const $http = $injector.get('$http');
ClientUtil.http = $http;
ClientUtil.httpBackend = $httpBackend;
여러 test 파일 동시 실행
const $injector = angular.injector(['angular1es6']);
const $httpBackend = $injector.get('$httpBackend');
const $http = $injector.get('$http');
Chrome 54.0.2840 (Windows 10 0.0.0) SignInCtrl test logic submit() with ajax error response
response error test FAILED
AssertionError: expected [Error: Unexpected request: POST /api/user/signIn
No more request expected] to be an instance of ERROR
Chrome 54.0.2840 (Windows 10 0.0.0) SignUpCtrl test logic submit() error response response
error test FAILED
AssertionError: expected [Error: [$rootScope:inprog] $digest already in progress
const ngApp = angular.module(appName, ['ngMock']);
var $injector = angular.injector(['MoneyBook']);
const $httpBackend = $injector.get('$httpBackend');
const $http = $injector.get('$http');
ClientUtil.http = $http;
ClientUtil.httpBackend = $httpBackend;
29
생성자 안에서 Promise
export default class HomeCtrl {
constructor () {
console.log('HomeCtrl.constructor()');
Promise.resolve(() => {
// do something
});
}
}
describe('constructor()', () => {
it('ok', () => {
// expect what...?
});
});
export default class HomeCtrl {
constructor () {
console.log('HomeCtrl.constructor()');
this.somethingPromise();
}
somethingPromise(){
return Promise.resolve()
.then() => {
// do something
});
}
}
30
Promise + $scope.$apply()
export default class HomeCtrl {
constructor () {
console.log('HomeCtrl.constructor()');
this.count = 0;
}
select () {
console.log('HomeCtrl.select()');
return Promise.resolve()
.then(() => {
this.count++;
});
}
}
export default class HomeCtrl {
constructor ($scope) {
console.log('HomeCtrl.constructor()');
this.$scope = $scope;
this.count = 0;
}
select () {
console.log('HomeCtrl.select()');
return Promise.resolve()
.then(() => {
this.count++;
this.$scope.$apply();
});
}
}
31
+ =
32
33
https://github.com/han41858/angular1-es6
boilerplate
Q & A
34
감사합니다.
han41858@gmail.com
han41858.tistory.com
35

More Related Content

What's hot

Workshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScriptWorkshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScriptVisual Engineering
 
FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6Dmitry Soshnikov
 
Django + Vue, JavaScript de 3ª generación para modernizar Django
Django + Vue, JavaScript de 3ª generación para modernizar DjangoDjango + Vue, JavaScript de 3ª generación para modernizar Django
Django + Vue, JavaScript de 3ª generación para modernizar DjangoJavier Abadía
 
Node.js API 서버 성능 개선기
Node.js API 서버 성능 개선기Node.js API 서버 성능 개선기
Node.js API 서버 성능 개선기JeongHun Byeon
 
An Introduction To Testing In AngularJS Applications
An Introduction To Testing In AngularJS Applications An Introduction To Testing In AngularJS Applications
An Introduction To Testing In AngularJS Applications Rohan Chandane
 
RDSDataSource: Мастер-класс по Dip
RDSDataSource: Мастер-класс по DipRDSDataSource: Мастер-класс по Dip
RDSDataSource: Мастер-класс по DipRAMBLER&Co
 
Workshop 3: JavaScript build tools
Workshop 3: JavaScript build toolsWorkshop 3: JavaScript build tools
Workshop 3: JavaScript build toolsVisual Engineering
 
Scalable Angular 2 Application Architecture
Scalable Angular 2 Application ArchitectureScalable Angular 2 Application Architecture
Scalable Angular 2 Application ArchitectureFDConf
 
Workshop 5: JavaScript testing
Workshop 5: JavaScript testingWorkshop 5: JavaScript testing
Workshop 5: JavaScript testingVisual Engineering
 
Redux. From twitter hype to production
Redux. From twitter hype to productionRedux. From twitter hype to production
Redux. From twitter hype to productionFDConf
 
How to build to do app using vue composition api and vuex 4 with typescript
How to build to do app using vue composition api and vuex 4 with typescriptHow to build to do app using vue composition api and vuex 4 with typescript
How to build to do app using vue composition api and vuex 4 with typescriptKaty Slemon
 
Javascript Promises/Q Library
Javascript Promises/Q LibraryJavascript Promises/Q Library
Javascript Promises/Q Libraryasync_io
 
Understanding Asynchronous JavaScript
Understanding Asynchronous JavaScriptUnderstanding Asynchronous JavaScript
Understanding Asynchronous JavaScriptjnewmanux
 
"Migrate large gwt applications - Lessons Learned" By Harald Pehl
"Migrate large gwt applications - Lessons Learned" By Harald Pehl"Migrate large gwt applications - Lessons Learned" By Harald Pehl
"Migrate large gwt applications - Lessons Learned" By Harald PehlGWTcon
 
Jersey framework
Jersey frameworkJersey framework
Jersey frameworkknight1128
 
Zukunftssichere Anwendungen mit AngularJS 1.x entwickeln (GDG DevFest Karlsru...
Zukunftssichere Anwendungen mit AngularJS 1.x entwickeln (GDG DevFest Karlsru...Zukunftssichere Anwendungen mit AngularJS 1.x entwickeln (GDG DevFest Karlsru...
Zukunftssichere Anwendungen mit AngularJS 1.x entwickeln (GDG DevFest Karlsru...Christian Janz
 

What's hot (20)

Workshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScriptWorkshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScript
 
FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6
 
Django + Vue, JavaScript de 3ª generación para modernizar Django
Django + Vue, JavaScript de 3ª generación para modernizar DjangoDjango + Vue, JavaScript de 3ª generación para modernizar Django
Django + Vue, JavaScript de 3ª generación para modernizar Django
 
Node.js API 서버 성능 개선기
Node.js API 서버 성능 개선기Node.js API 서버 성능 개선기
Node.js API 서버 성능 개선기
 
An Introduction To Testing In AngularJS Applications
An Introduction To Testing In AngularJS Applications An Introduction To Testing In AngularJS Applications
An Introduction To Testing In AngularJS Applications
 
RDSDataSource: Мастер-класс по Dip
RDSDataSource: Мастер-класс по DipRDSDataSource: Мастер-класс по Dip
RDSDataSource: Мастер-класс по Dip
 
Workshop 3: JavaScript build tools
Workshop 3: JavaScript build toolsWorkshop 3: JavaScript build tools
Workshop 3: JavaScript build tools
 
Scalable Angular 2 Application Architecture
Scalable Angular 2 Application ArchitectureScalable Angular 2 Application Architecture
Scalable Angular 2 Application Architecture
 
Workshop 5: JavaScript testing
Workshop 5: JavaScript testingWorkshop 5: JavaScript testing
Workshop 5: JavaScript testing
 
Redux. From twitter hype to production
Redux. From twitter hype to productionRedux. From twitter hype to production
Redux. From twitter hype to production
 
Workshop 10: ECMAScript 6
Workshop 10: ECMAScript 6Workshop 10: ECMAScript 6
Workshop 10: ECMAScript 6
 
How to build to do app using vue composition api and vuex 4 with typescript
How to build to do app using vue composition api and vuex 4 with typescriptHow to build to do app using vue composition api and vuex 4 with typescript
How to build to do app using vue composition api and vuex 4 with typescript
 
Javascript Promises/Q Library
Javascript Promises/Q LibraryJavascript Promises/Q Library
Javascript Promises/Q Library
 
OneRing @ OSCamp 2010
OneRing @ OSCamp 2010OneRing @ OSCamp 2010
OneRing @ OSCamp 2010
 
Understanding Asynchronous JavaScript
Understanding Asynchronous JavaScriptUnderstanding Asynchronous JavaScript
Understanding Asynchronous JavaScript
 
Express node js
Express node jsExpress node js
Express node js
 
Zenly - Reverse geocoding
Zenly - Reverse geocodingZenly - Reverse geocoding
Zenly - Reverse geocoding
 
"Migrate large gwt applications - Lessons Learned" By Harald Pehl
"Migrate large gwt applications - Lessons Learned" By Harald Pehl"Migrate large gwt applications - Lessons Learned" By Harald Pehl
"Migrate large gwt applications - Lessons Learned" By Harald Pehl
 
Jersey framework
Jersey frameworkJersey framework
Jersey framework
 
Zukunftssichere Anwendungen mit AngularJS 1.x entwickeln (GDG DevFest Karlsru...
Zukunftssichere Anwendungen mit AngularJS 1.x entwickeln (GDG DevFest Karlsru...Zukunftssichere Anwendungen mit AngularJS 1.x entwickeln (GDG DevFest Karlsru...
Zukunftssichere Anwendungen mit AngularJS 1.x entwickeln (GDG DevFest Karlsru...
 

Viewers also liked

기술용어 선호도 조사 결과
기술용어 선호도 조사 결과기술용어 선호도 조사 결과
기술용어 선호도 조사 결과장현 한
 
Angular 2 어디까지 왔을까
Angular 2 어디까지 왔을까Angular 2 어디까지 왔을까
Angular 2 어디까지 왔을까장현 한
 
Angularjs 도입 선택 가이드
Angularjs 도입 선택 가이드Angularjs 도입 선택 가이드
Angularjs 도입 선택 가이드NAVER D2
 
Angular2를 위한 컴포넌트 분석과 개발
Angular2를 위한 컴포넌트 분석과 개발Angular2를 위한 컴포넌트 분석과 개발
Angular2를 위한 컴포넌트 분석과 개발Jin wook
 
Angular2를 활용한 컴포넌트 중심의 개발
Angular2를 활용한 컴포넌트 중심의 개발Angular2를 활용한 컴포넌트 중심의 개발
Angular2를 활용한 컴포넌트 중심의 개발Jin wook
 
Lazy angular w/ webpack
Lazy angular w/ webpackLazy angular w/ webpack
Lazy angular w/ webpackRich Snapp
 
RequireJS를 이용한 모듈관리.
RequireJS를 이용한 모듈관리.RequireJS를 이용한 모듈관리.
RequireJS를 이용한 모듈관리.Hyung Eun Jin
 
Bootstrap 살펴보기
Bootstrap 살펴보기Bootstrap 살펴보기
Bootstrap 살펴보기영배 현
 
『풀스택 개발자를 위한 MEAN 스택 입문』 - 미리보기
『풀스택 개발자를 위한 MEAN 스택 입문』 - 미리보기『풀스택 개발자를 위한 MEAN 스택 입문』 - 미리보기
『풀스택 개발자를 위한 MEAN 스택 입문』 - 미리보기복연 이
 
Mean 스택을 사용한 IoT 개발
Mean 스택을 사용한 IoT 개발Mean 스택을 사용한 IoT 개발
Mean 스택을 사용한 IoT 개발Jay Park
 
주니어 개발자의 개인프로젝트 개발기
주니어 개발자의 개인프로젝트 개발기주니어 개발자의 개인프로젝트 개발기
주니어 개발자의 개인프로젝트 개발기sung yong jung
 
Angular2 가기전 Type script소개
 Angular2 가기전 Type script소개 Angular2 가기전 Type script소개
Angular2 가기전 Type script소개Dong Jun Kwon
 
JavaScript 프레임워크 살펴보기
JavaScript 프레임워크 살펴보기JavaScript 프레임워크 살펴보기
JavaScript 프레임워크 살펴보기항희 이
 
Angular2를 위한 타입스크립트
Angular2를 위한 타입스크립트Angular2를 위한 타입스크립트
Angular2를 위한 타입스크립트Jin wook
 
FullStack 개발자 만들기 과정 소개 (Android + MEAN Stack + Redis 다루기)
FullStack 개발자 만들기 과정 소개  (Android + MEAN Stack + Redis 다루기) FullStack 개발자 만들기 과정 소개  (Android + MEAN Stack + Redis 다루기)
FullStack 개발자 만들기 과정 소개 (Android + MEAN Stack + Redis 다루기) YoungSu Son
 
JavaScript MEAN 스택
JavaScript MEAN 스택JavaScript MEAN 스택
JavaScript MEAN 스택Tai Hoon KIM
 
웹-프론트엔드 프레임워크를 고르기 위한 팁
웹-프론트엔드 프레임워크를 고르기 위한 팁웹-프론트엔드 프레임워크를 고르기 위한 팁
웹-프론트엔드 프레임워크를 고르기 위한 팁WebFrameworks
 
혼자서 프로젝트 수행하기
혼자서 프로젝트 수행하기혼자서 프로젝트 수행하기
혼자서 프로젝트 수행하기JeongHun Byeon
 
Front-End 개발의 괜찮은 선택 ES6 & React
Front-End 개발의 괜찮은 선택  ES6 & ReactFront-End 개발의 괜찮은 선택  ES6 & React
Front-End 개발의 괜찮은 선택 ES6 & React지수 윤
 
응답하라 반응형웹 - 3. bootstrap
응답하라 반응형웹 - 3. bootstrap응답하라 반응형웹 - 3. bootstrap
응답하라 반응형웹 - 3. bootstrapredribbon1307
 

Viewers also liked (20)

기술용어 선호도 조사 결과
기술용어 선호도 조사 결과기술용어 선호도 조사 결과
기술용어 선호도 조사 결과
 
Angular 2 어디까지 왔을까
Angular 2 어디까지 왔을까Angular 2 어디까지 왔을까
Angular 2 어디까지 왔을까
 
Angularjs 도입 선택 가이드
Angularjs 도입 선택 가이드Angularjs 도입 선택 가이드
Angularjs 도입 선택 가이드
 
Angular2를 위한 컴포넌트 분석과 개발
Angular2를 위한 컴포넌트 분석과 개발Angular2를 위한 컴포넌트 분석과 개발
Angular2를 위한 컴포넌트 분석과 개발
 
Angular2를 활용한 컴포넌트 중심의 개발
Angular2를 활용한 컴포넌트 중심의 개발Angular2를 활용한 컴포넌트 중심의 개발
Angular2를 활용한 컴포넌트 중심의 개발
 
Lazy angular w/ webpack
Lazy angular w/ webpackLazy angular w/ webpack
Lazy angular w/ webpack
 
RequireJS를 이용한 모듈관리.
RequireJS를 이용한 모듈관리.RequireJS를 이용한 모듈관리.
RequireJS를 이용한 모듈관리.
 
Bootstrap 살펴보기
Bootstrap 살펴보기Bootstrap 살펴보기
Bootstrap 살펴보기
 
『풀스택 개발자를 위한 MEAN 스택 입문』 - 미리보기
『풀스택 개발자를 위한 MEAN 스택 입문』 - 미리보기『풀스택 개발자를 위한 MEAN 스택 입문』 - 미리보기
『풀스택 개발자를 위한 MEAN 스택 입문』 - 미리보기
 
Mean 스택을 사용한 IoT 개발
Mean 스택을 사용한 IoT 개발Mean 스택을 사용한 IoT 개발
Mean 스택을 사용한 IoT 개발
 
주니어 개발자의 개인프로젝트 개발기
주니어 개발자의 개인프로젝트 개발기주니어 개발자의 개인프로젝트 개발기
주니어 개발자의 개인프로젝트 개발기
 
Angular2 가기전 Type script소개
 Angular2 가기전 Type script소개 Angular2 가기전 Type script소개
Angular2 가기전 Type script소개
 
JavaScript 프레임워크 살펴보기
JavaScript 프레임워크 살펴보기JavaScript 프레임워크 살펴보기
JavaScript 프레임워크 살펴보기
 
Angular2를 위한 타입스크립트
Angular2를 위한 타입스크립트Angular2를 위한 타입스크립트
Angular2를 위한 타입스크립트
 
FullStack 개발자 만들기 과정 소개 (Android + MEAN Stack + Redis 다루기)
FullStack 개발자 만들기 과정 소개  (Android + MEAN Stack + Redis 다루기) FullStack 개발자 만들기 과정 소개  (Android + MEAN Stack + Redis 다루기)
FullStack 개발자 만들기 과정 소개 (Android + MEAN Stack + Redis 다루기)
 
JavaScript MEAN 스택
JavaScript MEAN 스택JavaScript MEAN 스택
JavaScript MEAN 스택
 
웹-프론트엔드 프레임워크를 고르기 위한 팁
웹-프론트엔드 프레임워크를 고르기 위한 팁웹-프론트엔드 프레임워크를 고르기 위한 팁
웹-프론트엔드 프레임워크를 고르기 위한 팁
 
혼자서 프로젝트 수행하기
혼자서 프로젝트 수행하기혼자서 프로젝트 수행하기
혼자서 프로젝트 수행하기
 
Front-End 개발의 괜찮은 선택 ES6 & React
Front-End 개발의 괜찮은 선택  ES6 & ReactFront-End 개발의 괜찮은 선택  ES6 & React
Front-End 개발의 괜찮은 선택 ES6 & React
 
응답하라 반응형웹 - 3. bootstrap
응답하라 반응형웹 - 3. bootstrap응답하라 반응형웹 - 3. bootstrap
응답하라 반응형웹 - 3. bootstrap
 

Similar to Angular 1 + es6

Solving anything in VCL
Solving anything in VCLSolving anything in VCL
Solving anything in VCLFastly
 
using Mithril.js + postgREST to build and consume API's
using Mithril.js + postgREST to build and consume API'susing Mithril.js + postgREST to build and consume API's
using Mithril.js + postgREST to build and consume API'sAntônio Roberto Silva
 
Building and deploying React applications
Building and deploying React applicationsBuilding and deploying React applications
Building and deploying React applicationsAstrails
 
Live deployment, ci, drupal
Live deployment, ci, drupalLive deployment, ci, drupal
Live deployment, ci, drupalAndrii Podanenko
 
Ch ch-changes cake php2
Ch ch-changes cake php2Ch ch-changes cake php2
Ch ch-changes cake php2markstory
 
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)Igor Bronovskyy
 
(DEV204) Building High-Performance Native Cloud Apps In C++
(DEV204) Building High-Performance Native Cloud Apps In C++(DEV204) Building High-Performance Native Cloud Apps In C++
(DEV204) Building High-Performance Native Cloud Apps In C++Amazon Web Services
 
10 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 2020
10 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 202010 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 2020
10 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 2020Matt Raible
 
Future of Web Apps: Google Gears
Future of Web Apps: Google GearsFuture of Web Apps: Google Gears
Future of Web Apps: Google Gearsdion
 
Future Decoded - Node.js per sviluppatori .NET
Future Decoded - Node.js per sviluppatori .NETFuture Decoded - Node.js per sviluppatori .NET
Future Decoded - Node.js per sviluppatori .NETGianluca Carucci
 
Angular JS deep dive
Angular JS deep diveAngular JS deep dive
Angular JS deep diveAxilis
 
MinbilDinbil Django Speed Tricks
MinbilDinbil Django Speed TricksMinbilDinbil Django Speed Tricks
MinbilDinbil Django Speed TricksLorenzo Setale
 
Bonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsBonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsFrancois Zaninotto
 
Real World Lessons on the Pain Points of Node.JS Application
Real World Lessons on the Pain Points of Node.JS ApplicationReal World Lessons on the Pain Points of Node.JS Application
Real World Lessons on the Pain Points of Node.JS ApplicationBen Hall
 
Running Vue Storefront in production (PWA Magento webshop)
Running Vue Storefront in production (PWA Magento webshop)Running Vue Storefront in production (PWA Magento webshop)
Running Vue Storefront in production (PWA Magento webshop)Vendic Magento, PWA & Marketing
 
Patterns Are Good For Managers
Patterns Are Good For ManagersPatterns Are Good For Managers
Patterns Are Good For ManagersAgileThought
 
Symfony2 - from the trenches
Symfony2 - from the trenchesSymfony2 - from the trenches
Symfony2 - from the trenchesLukas Smith
 
Protractor framework – how to make stable e2e tests for Angular applications
Protractor framework – how to make stable e2e tests for Angular applicationsProtractor framework – how to make stable e2e tests for Angular applications
Protractor framework – how to make stable e2e tests for Angular applicationsLudmila Nesvitiy
 

Similar to Angular 1 + es6 (20)

Solving anything in VCL
Solving anything in VCLSolving anything in VCL
Solving anything in VCL
 
using Mithril.js + postgREST to build and consume API's
using Mithril.js + postgREST to build and consume API'susing Mithril.js + postgREST to build and consume API's
using Mithril.js + postgREST to build and consume API's
 
Building and deploying React applications
Building and deploying React applicationsBuilding and deploying React applications
Building and deploying React applications
 
Live deployment, ci, drupal
Live deployment, ci, drupalLive deployment, ci, drupal
Live deployment, ci, drupal
 
Ch ch-changes cake php2
Ch ch-changes cake php2Ch ch-changes cake php2
Ch ch-changes cake php2
 
Capistrano
CapistranoCapistrano
Capistrano
 
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
 
(DEV204) Building High-Performance Native Cloud Apps In C++
(DEV204) Building High-Performance Native Cloud Apps In C++(DEV204) Building High-Performance Native Cloud Apps In C++
(DEV204) Building High-Performance Native Cloud Apps In C++
 
10 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 2020
10 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 202010 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 2020
10 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 2020
 
Future of Web Apps: Google Gears
Future of Web Apps: Google GearsFuture of Web Apps: Google Gears
Future of Web Apps: Google Gears
 
Introduction to angular js
Introduction to angular jsIntroduction to angular js
Introduction to angular js
 
Future Decoded - Node.js per sviluppatori .NET
Future Decoded - Node.js per sviluppatori .NETFuture Decoded - Node.js per sviluppatori .NET
Future Decoded - Node.js per sviluppatori .NET
 
Angular JS deep dive
Angular JS deep diveAngular JS deep dive
Angular JS deep dive
 
MinbilDinbil Django Speed Tricks
MinbilDinbil Django Speed TricksMinbilDinbil Django Speed Tricks
MinbilDinbil Django Speed Tricks
 
Bonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsBonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node js
 
Real World Lessons on the Pain Points of Node.JS Application
Real World Lessons on the Pain Points of Node.JS ApplicationReal World Lessons on the Pain Points of Node.JS Application
Real World Lessons on the Pain Points of Node.JS Application
 
Running Vue Storefront in production (PWA Magento webshop)
Running Vue Storefront in production (PWA Magento webshop)Running Vue Storefront in production (PWA Magento webshop)
Running Vue Storefront in production (PWA Magento webshop)
 
Patterns Are Good For Managers
Patterns Are Good For ManagersPatterns Are Good For Managers
Patterns Are Good For Managers
 
Symfony2 - from the trenches
Symfony2 - from the trenchesSymfony2 - from the trenches
Symfony2 - from the trenches
 
Protractor framework – how to make stable e2e tests for Angular applications
Protractor framework – how to make stable e2e tests for Angular applicationsProtractor framework – how to make stable e2e tests for Angular applications
Protractor framework – how to make stable e2e tests for Angular applications
 

Recently uploaded

Clustering techniques data mining book ....
Clustering techniques data mining book ....Clustering techniques data mining book ....
Clustering techniques data mining book ....ShaimaaMohamedGalal
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...OnePlan Solutions
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software DevelopersVinodh Ram
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionSolGuruz
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...panagenda
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️anilsa9823
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerThousandEyes
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsJhone kinadey
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsAndolasoft Inc
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxbodapatigopi8531
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about usDynamic Netsoft
 
Active Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfActive Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfCionsystems
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxComplianceQuest1
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 

Recently uploaded (20)

Clustering techniques data mining book ....
Clustering techniques data mining book ....Clustering techniques data mining book ....
Clustering techniques data mining book ....
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
 
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS LiveVip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software Developers
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.js
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptx
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about us
 
Active Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfActive Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdf
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 

Angular 1 + es6

  • 2. • 전 삼성SDS 선임 • TV플랫폼 JavaScript 어플리케이션 구현 • 리테일 솔루션 서버 & 프론트엔드 구현 • 프리랜서 개발자 • han41858.tistory.com 블로그 운영 • Angular 2 번역서 집필중 • GDG Korea Web Tech 운영진 한장현 (Janghyun Han) 2
  • 3. 3
  • 5. • 마술 같은 2-way binding • HTML 표준을 기반으로 기능 확장 • 체계적인 컴포넌트 구성, Web Component로 가는 길 • Front-end 전체를 커버하는 프레임워크 • Google 에서 관리, 개선 • 풍부한 사용자 삽질 경험 Angular를 쓰는 이유 5
  • 7. • 간단해지는 코드, syntax sugar • 클래스, 상속, 모듈 구성 ⇒ 아키텍처 진화 • 브라우저들 지원 계속 • 결국엔 표준, transpiler는 거쳐갈 뿐 ES6를 쓰는 이유 7
  • 8. 8
  • 9. ES6ES5 script src <script src="bundle.js"></script> "devDependencies": { "angular": "^1.5.8", "babel-cli": "^6.18.0", "babel-loader": "^6.2.7", "babel-preset-es2015": "^6.18.0", "webpack": "^1.13.3" } <script src="angular.js"></script> <script src="index.js"></script> "devDependencies": { "angular": "^1.5.8" } 9
  • 10. index.js ES6ES5 (function () { var ngApp = angular.module('angular1es5', []); })(); import angular from 'angular'; (() => { const ngApp = angular.module('angular1es6', []); })(); 10
  • 11. Webpack // this is ES5 var webpack = require('webpack'); module.exports = { entry : [ './index.js' ], output : { filename : 'build/bundle.js', sourceMapFilename: '[name].map' }, module : { loaders : [ { test : /.js$/, loader : 'babel?presets[]=es2015 exclude : /node_modules/ }, { test : /.pug$/, loader : 'pug-loader', exclude : /node_modules/ } ] }, plugins : [ // new webpack.optimize.UglifyJsPlugin({minimize: true}) ] }; webpack.config.js "devDependencies": { "angular": "^1.5.8", "angular-route": "^1.5.8", "babel-cli": "^6.18.0", "babel-loader": "^6.2.7", "babel-preset-es2015": "^6.18.0", "file-loader": "^0.9.0", "pug": "^2.0.0-beta6", "pug-loader": "^2.3.0", "webpack": "^1.13.3", "webpack-dev-server": "^1.16.2" } package.json 11
  • 12. export default class HomeCtrl { constructor () { console.log('HomeCtrl.constructor()'); } } /view/homeCtrl.js p this is home /view/home.pug import angular from 'angular'; import ngRoute from 'angular-route'; import HomeCtrl from './view/homeCtrl'; const main = () => { console.log('main()'); const ngApp = angular.module('angular1es6', ['ngRoute']); ngApp.config(($routeProvider, $locationProvider) => { console.log('this is angular config'); $routeProvider .when('/', { template : require('./view/home.pug'), controller : 'HomeCtrl', controllerAs : 'Ctrl' }) .otherwise({ redirectTo : '/' }); // need to angular.js routing $locationProvider.html5Mode({ enabled : true, requireBase : false }); }); ngApp.controller('HomeCtrl', HomeCtrl); }; main(); index.js + ngRoute 12
  • 14. ngApp.directive('CustomDirective', () => new CustomDirective); ngApp.filter('groupBy', GroupBy); ngApp.service('CustomSvc', CustomSvc); ngApp.controller('CustomCtrl', CustomCtrl); Angular Components ngApp.directive('CustomDirective', CustomDirective); ngApp.filter('groupBy', GroupBy); ngApp.service('CustomSvc', CustomSvc); ngApp.controller('CustomCtrl', CustomCtrl); function Class new Class 14
  • 15. Filter ES6ES5 ngApp.filter('uppercase', uppercase); function uppercase () { return function (item) { return item.toUpperCase(); }; } <script src="uppercase.filter.js"></script> const uppercase = () => { return (input) => { return input.toUpperCase(); }; }; export default uppercase; import uppercase from './uppercase.filter'; ngApp.filter('uppercase', uppercase); 15
  • 16. .ctrlRoot p this is home ctrl p {{ Ctrl.title }} button(ng-click="Ctrl.select()") Select export default class HomeCtrl { constructor () { console.log('HomeCtrl.constructor()'); this.title = 'this is title'; } select () { console.log('HomeCtrl.select()'); } } $routeProvider .when('/', { template : require('./view/home.pug'), controller : 'HomeCtrl', controllerAs : 'Ctrl' }) ngApp.controller('HomeCtrl', HomeCtrl); function HomeCtrl ($scope) { console.log('home controller'); $scope.title = 'this is title'; $scope.select = function () { console.log('HomeCtrl.select()'); } } Controller ES6ES5 .ctrlRoot p this is home ctrl p {{ title }} button(ng-click="select()") Select 16
  • 17. Service ES6ES5 ngApp.service('myService', myService); <script src="./view/myService.js"></script> function myService () { this.testFnc = function () { console.log('myService.testFnc()'); }; return this; } export default class MyService { constructor () { console.log('MyService'); } testFnc () { console.log('MyService.testFnc()'); } } ngApp.service('MyService', MyService); export default class HomeCtrl { constructor (MyService) { this.MyService = MyService; } select () { this.MyService.testFnc(); } } static 있어야 할 것 같지만 없어야 함 17
  • 18. ngApp.directive('myDirective', () => new MyDirective); export default class MyDirective { constructor () { console.log('MyDirective.constructor()'); this.restrict = 'E'; this.template = '<p>message : {{ this.msg }}</p>'; this.scope = { msg : '@' }; } link (scope) { console.log(scope.msg); } } ngApp.directive('myDirective', myDirective); function myDirective () { return { restrict : 'E', template : '<p>message : {{ msg }}</p>', scope : { msg : '@' }, controller : function ($scope) { console.log('myDirective.controller()'); console.log($scope.msg); } } } <script src="myDirective.js"></script> Directive ES6ES5 directive 등록할 때 () => new18
  • 20. Directive vs. Component const customInput = { bindings : { model : '=' }, template : '<input ng-model="$ctrl.model"></input>', controller : function () { this.$onInit = () => { } } }; export default customInput; ngApp.component('customInput', customInput);ngApp.directive('customInput', () => new customInput); export default class customInput { constructor () { this.restrict = 'E'; this.scope = { model : '=' }; this.template = '<input ng-model="model"></input>'; } controller () { } } 20
  • 21. static delete (param) { const self = this; return util.objValidate(param, { userID : Constants.TYPE.EMAIL }, Constants.ERROR.USER_CTRL.NO_PARAMETER, log, 'delete()') .then(param => self.isExists(param)) .then(param => { // delete records return recordCtrl.deleteAll({ userID : param.userID }) .then(() => { log('remove records ok'); // param 자체를 다시 돌려주기 위해 Promise 필요 return Promise.resolve(param); }); }) .then(param => { // delete cards return cardCtrl.deleteAll({ userID : param.userID }) .then(() => { log('remove cards ok'); return Promise.resolve(param); }); }) .then(param => { // delete assets return assetCtrl.deleteAll({ userID : param.userID }) .then(() => { log('remove assets ok'); return Promise.resolve(param); }); }) .then(param => { // delete user return User.remove({ userID : param.userID }) .then(() => { return Promise.resolve(param); }, error => { log(error); return Promise.reject(new ERROR(Constants.ERROR.MONGOOSE.REMOVE_FAILED, log, 'delete()')); }); }) .then(param => { log(`delete ok : ${param.userID}`); return Promise.resolve(true); }); } Promise 21
  • 22. ngApp.config(($routeProvider, $locationProvider) => { // include styles require('./view/home.styl'); $routeProvider .when('/', { template : require('./view/home.pug'), controller : 'HomeCtrl', controllerAs : 'Ctrl' }) .otherwise({ redirectTo : '/' }); }); 배포 : webpack import가 아니므로 require 22
  • 23. Angular 1 + ES6 + BDD = Hell 23
  • 24. describe('homeCtrl.test', () => { it('module import', () => { expect(true).to.be.true; }); }); λ karma start (node:7564) DeprecationWarning: Using Buffer without `new` will soon stop working. Use `new Buffer()`, or preferably `Buffer.from()`, `Buffer.allocUnsafe()` or `Buffer.alloc()` instead. 18 11 2016 02:53:45.852:INFO [framework.browserify]: bundle built 18 11 2016 02:53:45.941:INFO [karma]: Karma v1.3.0 server started at http://localhost:9876/ 18 11 2016 02:53:45.941:INFO [launcher]: Launching browser Chrome with unlimited concurrency 18 11 2016 02:53:45.952:INFO [launcher]: Starting browser Chrome 18 11 2016 02:53:47.283:INFO [Chrome 54.0.2840 (Windows 10 0.0.0)]: Connected on socket /#AjAqCwTlrwmVmV_sAAAA with id 16857313 Chrome 54.0.2840 (Windows 10 0.0.0): Executed 1 of 1 SUCCESS (0.005 secs / 0.001 secs) BDD 시작 24
  • 25. λ karma start (node:12196) DeprecationWarning: Using Buffer without `new` will soon stop working. Use `new Buffer()`, or preferably `Buffer.from()`, `Buffer.allocUnsafe()` or `Buffer.alloc()` instead. 18 11 2016 02:19:10.237:INFO [framework.browserify]: bundle built 18 11 2016 02:19:10.343:INFO [karma]: Karma v1.3.0 server started at http://localhost:9876/ 18 11 2016 02:19:10.343:INFO [launcher]: Launching browser Chrome with unlimited concurrency 18 11 2016 02:19:10.353:INFO [launcher]: Starting browser Chrome 18 11 2016 02:19:11.676:INFO [Chrome 54.0.2840 (Windows 10 0.0.0)]: Connected on socket /#sBpP4RL0XFZAwPtxAAAA with id 52822107 Chrome 54.0.2840 (Windows 10 0.0.0) ERROR Uncaught SyntaxError: Unexpected token import at test/homeCtrl.test.js:1 import HomeCtrl from '../view/homeCtrl'; describe('homeCtrl.test', () => { it('module import', () => { console.log(HomeCtrl); expect(true).to.be.true; expect(HomeCtrl).to.be.ok; }); }); λ karma start (node:11580) DeprecationWarning: Using Buffer without `new` will soon stop working. Use `new Buffer()`, or preferably `Buffer.from()`, `Buffer.allocUnsafe()` or `Buffer.alloc()` instead. 18 11 2016 02:31:24.248:INFO [framework.browserify]: bundle built 18 11 2016 02:31:24.339:INFO [karma]: Karma v1.3.0 server started at http://localhost:9876/ 18 11 2016 02:31:24.339:INFO [launcher]: Launching browser Chrome with unlimited concurrency 18 11 2016 02:31:24.349:INFO [launcher]: Starting browser Chrome 18 11 2016 02:31:25.657:INFO [Chrome 54.0.2840 (Windows 10 0.0.0)]: Connected on socket /#pvpyGrXqq2TZPTgmAAAA with id 30236974 LOG: class HomeCtrl { ... } Chrome 54.0.2840 (Windows 10 0.0.0): Executed 1 of 1 SUCCESS (0.007 secs / 0.002 secs) babel : node6 λ karma start (node:13196) DeprecationWarning: Using Buffer without `new` will soon stop working. Use `new Buffer()`, or preferably `Buffer.from()`, `Buffer.allocUnsafe()` or `Buffer.alloc()` instead. 18 11 2016 02:58:38.638:INFO [framework.browserify]: bundle built 18 11 2016 02:58:38.728:INFO [karma]: Karma v1.3.0 server started at http://localhost:9876/ 18 11 2016 02:58:38.729:INFO [launcher]: Launching browser PhantomJS with unlimited concurrency 18 11 2016 02:58:38.738:INFO [launcher]: Starting browser PhantomJS 18 11 2016 02:58:40.301:INFO [PhantomJS 2.1.1 (Windows 8 0.0.0)]: Connected on socket /#JeRwavdozVZCC8HJAAAA with id 75347319 LOG: function HomeCtrl(MyService) { ... } PhantomJS 2.1.1 (Windows 8 0.0.0): Executed 1 of 1 SUCCESS (0.008 secs / 0.001 secs) babel : es2015 ES6가 돌지 않는다… + 25
  • 26. var $httpBackend; beforeEach(function () { module('angular1es5'); inject(function (_$httpBackend_) { $httpBackend = _$httpBackend_; }); }); module 선언, injection 불가 ES6ES5 const $injector, $httpBackend; beforeEach(() => { $injector = angular.injector(['angular1es6']); $httpBackend = $injector.get('$httpBackend'); }); Object is not a constructor (evaluating 'module('angular1es6')') r:/temp/test/homeCtrl.test.js:15:9 <- R:/temp/3871fde1c6cf6c302eeae7add18a3b02.browserify:22:9 26 let ngApp = angular.module('angular1es6', ['ngMock']);
  • 27. ngMock vs. ngMockE2E The ngMock module provides support to inject and mock Angular services into unit tests. In addition, ngMock also extends various core ng services such that they can be inspected and controlled in a synchronous manner within test code. The ngMockE2E is an angular module which contains mocks suitable for end-to-end testing. Currently there is only one mock present in this module - the e2e $httpBackend mock. ngMock ngMockE2E Fake HTTP backend implementation suitable for end-to- end testing or backend-less development of applications that use the $http service. Fake HTTP backend implementation suitable for unit testing applications that use the $http service. .when() .expect() .flush() .verifyNoOutstandingExpectation() .verifyNoOutstandingRequest() .resetExpectations() .when() ngMockE2E에는 $location 없음 27
  • 28. Promise + http.flush() Chrome 54.0.2840 (Windows 10 0.0.0) homeCtrl.test http test ok FAILED Error: No pending request to flush ! at Function.$httpBackend.flush (node_modules/angular-mocks/angular-mocks.js:1799:34) at r:/temp/test/homeCtrl.test.js:36:17 promise 함수로 부르면 동작 안함 flush() 타이밍 달라짐 flush는 Util에서 수행 const $injector = angular.injector(['angular1es6']); const $httpBackend = $injector.get('$httpBackend'); const $http = $injector.get('$http'); beforeEach(() => { $httpBackend.expectGET('/test') .respond(['this', 'is', 'GET', 'test', 'data']); }); it('ok', () => { return new Promise(resolve => { $http.get('/test').then(result => { console.log('get().then()'); console.log(result); console.log(result.data); resolve(true); }); $httpBackend.flush(); }); }); 동작하는 코드 static post (uri, param, config) { // use new promise for flush() return new Promise((resolve, reject) => { this.http.post(uri, param, config) .then(result => { resolve(result); }, error => { console.error(error); reject(false); }); if (this.httpBackend && this.httpBackend.flush) { this.httpBackend.flush(); } }); } it('ok', () => { return new Promise(resolve => { Promise.resolve() .then(() => { $http.get('/test').then(result => { console.log('get().then()'); console.log(result); console.log(result.data); resolve(true); }); }); $httpBackend.flush(); }); }); 28 const $httpBackend = $injector.get('$httpBackend'); const $http = $injector.get('$http'); ClientUtil.http = $http; ClientUtil.httpBackend = $httpBackend;
  • 29. 여러 test 파일 동시 실행 const $injector = angular.injector(['angular1es6']); const $httpBackend = $injector.get('$httpBackend'); const $http = $injector.get('$http'); Chrome 54.0.2840 (Windows 10 0.0.0) SignInCtrl test logic submit() with ajax error response response error test FAILED AssertionError: expected [Error: Unexpected request: POST /api/user/signIn No more request expected] to be an instance of ERROR Chrome 54.0.2840 (Windows 10 0.0.0) SignUpCtrl test logic submit() error response response error test FAILED AssertionError: expected [Error: [$rootScope:inprog] $digest already in progress const ngApp = angular.module(appName, ['ngMock']); var $injector = angular.injector(['MoneyBook']); const $httpBackend = $injector.get('$httpBackend'); const $http = $injector.get('$http'); ClientUtil.http = $http; ClientUtil.httpBackend = $httpBackend; 29
  • 30. 생성자 안에서 Promise export default class HomeCtrl { constructor () { console.log('HomeCtrl.constructor()'); Promise.resolve(() => { // do something }); } } describe('constructor()', () => { it('ok', () => { // expect what...? }); }); export default class HomeCtrl { constructor () { console.log('HomeCtrl.constructor()'); this.somethingPromise(); } somethingPromise(){ return Promise.resolve() .then() => { // do something }); } } 30
  • 31. Promise + $scope.$apply() export default class HomeCtrl { constructor () { console.log('HomeCtrl.constructor()'); this.count = 0; } select () { console.log('HomeCtrl.select()'); return Promise.resolve() .then(() => { this.count++; }); } } export default class HomeCtrl { constructor ($scope) { console.log('HomeCtrl.constructor()'); this.$scope = $scope; this.count = 0; } select () { console.log('HomeCtrl.select()'); return Promise.resolve() .then(() => { this.count++; this.$scope.$apply(); }); } } 31

Editor's Notes

  1. 오늘 언급할 라이브러리들
  2. https://github.com/angular/angular.js/blob/master/CHANGELOG.md 1.6.0-rc.2 safety-insurance (2016-11-24)
  3. 지속적인 성능 개선, 버그 수정 two-way binding is magic 체계적인 앱 프론트엔드 구성 사용자 삽질 경험 풍부, 웬만한 문제는 해결 가능 Angular 2는 아직..
  4. http://www.ecma-international.org/ecma-262/6.0/ ECMAScript 2015 2015-6 발표 2016-6-20 개정 ECMAScript 2016, ES7 2016-6 Exponentiation operator ** Array.prototype.includes
  5. transpiler들의 지원 babel babelify browserify traceur
  6. ES6에서 angular.js 포함 없음 webpack 쓸거니까
  7. webpack bundling을 위해 html이 아니라 js에서 추가 import 들… 코드에서 직접 쓰지는 않더라도 의존성을 위해 추가해야 함(script src 대신) ex) import ngRoute 없으면 angular module injection failed html script 나열이 아니라서 webpack dependency를 찾아가는 것이 편하기도 함
  8. webpack을 쓰니까 pug 를 require로 사용 controllerAs 없으면 스코프 접근 불가
  9. 모두 class로 export filter, directive 등록에는 new 필요, 없으면 에러 service, controller 등록에는 안 필요
  10. controller 대체, controllerAs 사용하지 않으면 접근 불가 $scope 대신 this 사용, private function 불가
  11. angular.service 와 ES6 class static은 연관되지만… static 있으면 안돌아감. 없어야 prototype chain으로 연결됨 ngApp.service() 필요 없음, babel 때문에
  12. 생성자의 재발견 상속이면 super() 필요 ES5 directive의 return보다 보기 편함 controller 대체 $scope 대신 this 사용, private function 불가
  13. after Angular 1.5
  14. componen는 directiv와 사용방법이 다름 component 쓸때는 객체를 반환 directive는 클래스를 반환, new 선언 componen에서는 element, attr 등 접근 어려움 component는 Element만 사용 가능, 어차피 directive 필요 .directive()는 쓰자
  15. 어차피 표준, 가독성 엄청 향상 catch로 끝내지 않도록 주의, 콘솔이 안 이쁘잖아.. callback hell, pyramid of doom
  16. template, style 로드 간편 서버와 공통 로직 그대로 사용(ex. validation)
  17. BDD 작성 시작 헬 시작 참고 자료 찾기 어려움
  18. Chrome에서는 돈다. PhantomJS에서는 돌지 않음
  19. 브라우저에서 ES6지원하지 않으면 karma 돌지 않음… ES6니까 node6, es2015 babel preset 필요 Chrome에서도 import는 안됨 import 없이 arrow function은 동작함 webpack → karma : bundling, 오류 찾기 힘들다 karma-browerify → karma-babelify → karma : O
  20. import 구문이 아니라서 찾을 수 없음 browserify, babelify를 거치니까.. karma.conf.js에 angular 추가, 수동 injector 사용
  21. http 이후 $location 테스트하면서 문제 발생 같은 파일이지만 angular.module dependency 선언에서 ngMock과 ngMockE2E로 갈림 동시에 사용 불가, ngMockE2E에는 $location이 없음 ngMock : fake response for unit test ngMockE2E : fake response for end-to-end test
  22. promise 쓰니까 http.flush() 타이밍 맞지 않음 유틸 객체에 프로퍼티로 지정
  23. 한 번에 돌리면 에러 http injection 문제, 전역에서 한 번만 지정
  24. 생성자 안에서 Promise 쓰는 경우 결과 확인 불가 함수 분리. Promise 완료를 기다릴 수 없음
  25. Promise 안에서 클래스 프로퍼티 값을 바꾼 경우 한 cycle 늦게 view에 적용됨 $scope.$apply() 호출 필요
  26. 할 만 하다 어차피 ES6는 표준 가독성이 향상되는 코드가 많음
  27. Angular usage in Google (etc : https://builtwith.angularjs.org/) Double Click For Advertiser YouTube for PS3 Google Cloud Developers Console Google Cast