웹 어플리케이션 보안 2016년 2학기 6. Angular
6. Angular Chap 11. Starting Angular Chap 12. Angular Routing Chap 13. Animating Angular Applications
Node와 Angular의 비교 Node Angular Back-end (서버측) 개발에 활용. RESTful API, MongoDB를 활용한 CRUD Angular Front-end (클라이언트측) 개발의 최전선 핵심 기술 Superheroic JavaScript MVC Framework 웹앱을 위한 확장 HTML https://angularjs.org/
Angular 2.0 open https://angular.io/
Angular framework의 장점 Framework를 사용하지 않는 JavaScript 개발의 문제점 순수 자바스크립트, jQuery 등은 프로그래밍이 복잡하고 코드가 길다. 사용자 입력 변수를 처리하는데 많은 노력 소모 실제 데이터가 무엇인지 코드 해석이 어려움 MVC framework의 유용성, 활용 증가 Model : true source of data View : just display data, logic free Controller : manipulation of data Angular MVC 모델에 따른 front-end 개발 방법론 제공 Back-end의 개발 방법론과 동일
Angular의 중요 개념 1. Data-binding (데이터 결합) 모델과 뷰 사이에 실제 데이터를 자동 반영. 사용자의 별도 노력 이 필요하지 않음 Single true source of data “The compilation step produces a live view. Any changes to the view are immediately reflected in the model, and any changes in the model are propagated to the view. The model is the single-source-of-truth for the application state, greatly simplifying the programming model for the developer. You can think of the view as simply an instant projection of your model.”
Angular의 중요 개념 2. Dependency Injection (의존성 삽입, 유지, 전달) 1. Controller: 데이터를 다루는 일 2. Service(model): API와 연동하는 일 3. Directive: 뷰(view)를 다루는 일 등등 각각의 모듈들의 의존성이 메인 프로그램에 그대로 전달됨 passing of a dependency to a dependent object (a client) that would use it. 모듈러 프로그래밍 방식을 적용 가능
Angular의 중요 개념 3. Directives (지시자) 어떤 HTML의 요소가 Angular의 어떤 변수(또는 함수)에 어떻게 연동되는지를 나타냄 Angular가 DOM(document object model) 요소를 변경할 수 있 도록 하기 위해 사용됨
첫번째 Angular 예제 파일 구조 App.js : Angular 앱의 생성, 메인 모듈 생성 (콘트롤러) Index.html : Angular 앱의 적용 (뷰) 콘트롤러와 뷰의 역할을 나누어 다른 파일로 작성 하나의 파일에 모든 기능을 넣는 것을 회피 어플리케이션이 커질수록 분산된 파일관리가 효율적
첫번째 Angular 예제 Angular 앱의 생성 angular.module( )을 이용한 // app.js // name our angular app angular.module('firstApp', []) .controller('mainController', function() { // bind this to vm (view-model) var vm = this; // define variables and objects on this // this lets them be available to our views // define a basic variable vm.message = 'Hey there! Come and see how good I look!'; // define a list of items vm.computers = [ { name: 'Macbook Pro', color: 'Silver', nerdness: 7 }, { name: 'Yoga 2 Pro', color: 'Gray', nerdness: 6 }, { name: 'Chromebook', color: 'Black', nerdness: 5 } ]; }); angular.module( )을 이용한 Angular 메인모듈 생성 (firstApp) Controller 선언 (mainController) 현재 페이지의 객체를 vm이라는 변수로 뷰모델과 바인딩 변수 생성 (message) 리스트 변수 생성 (computers)
첫번째 Angular 예제 Angular 앱의 적용 (index.html) Bootstrap CSS를 CDN에서 불러오기 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>My First Angular Application!</title> <!-- CSS --> <!-- load bootstrap and our stylesheet --> <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css"> <style> body { padding-top:50px; } </style> <!-- JS --> <!-- load angular and our custom application --> <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular.min.js"></script> <script src="js/app.js"></script> </head> Bootstrap CSS를 CDN에서 불러오기 디바이스의 화면크기에 맞추어 스타일 자동 변경 화면이 작은 모바일 디바이스에 적합한 페이지 작성 Angular.js를 CDN에서 불러오기 앞에서 생성한 Angular app을 불러오기 * CDN - Content Delivery Network 여러곳의 IDC 또는 ISP에 동일한 컨텐츠를 올려놓고, 접속자가 사용하는 인터넷전용회선의 종류에 따라 가장 가까운 곳에서 컨텐츠를 불러들일 수 있도록 지원하는 서비스
첫번째 Angular 예제 ng-app: angular app을 지정하는 지시자 ng-controller: 컨트롤러를 지정하는 지시자 컨트롤러를 main이라는 이름으로 사용 생성한 앱을 body에 적용 <!-- declare our angular application and angular controller --> <body class="container" ng-app="firstApp" ng-controller="mainController as main"> <div class="jumbotron"> <!-- display the message --> <h2>This is my message:</h2> {{ main.message }} <!-- display the list using ng-repeat --> <h2>This is my list:</h2> <table class="table table-bordered"> <thead> <tr> <td>Name</td> <td>Color</td> <td>Nerd Level</td> </tr> </thead> <tbody> <tr ng-repeat="computer in main.computers"> <td>{{ computer.name }}</td> <td>{{ computer.color }}</td> <td>{{ computer.nerdness }}</td> </tbody> </table> </div> </body> </html> {{ }}는 컨트롤러에서 정의된 변수를 view에 보여줌 ng-repeat는 리스트 변수의 값들을 모두 보여줌 자바스크립트의 foreach 구문과 동일한 역할
첫번째 Angular 예제 결과 웹브라우저로 index.html 파일을 실행 클라이언트 프로그래밍으로 서버는 아직 필요 없음
Data-binding 추가 사용자 입력과 뷰의 데이터를 결합하는 사례 <!-- form to update the message variable using ng-model --> <div class="form-group"> <label>Message</label> <input type="text" class="form-control" ng-model="main.message"> </div> <div class="jumbotron"> <!-- display the message --> <h2>This is my message:</h2> {{ main.message }} 사용자 입력 양식 사용자 입력을 받아 main.message로 전달 ng-model 지시자는 사용자 입력과 앱의 변수를 결합 사용자 입력이 뷰에 즉시 반영됨 클릭하여 코드 수행 테스트 http://codepen.io/sevilayha/full/DhLqk/
사용자 입력 폼 다루기 사용자의 폼 입력 다루기: 해야 할 일 사용자 입력값을 리스트 변수에 데이터로 추가하기 Add 버튼을 누를 때 데이터 추가를 실행 해야 할 일 1. 폼을 다루고 리스트에 추가하는 작업을 Angular 함수로 추가 2. HTML 폼에서 Angular와의 연결작업을 지시, 함수를 실행
사용자 입력 폼 다루기 App.js에 addComputer 함수 추가 // information that comes from our form vm.computerData = {}; vm.addComputer = function() { // add a computer to the list vm.computers.push({ name: vm.computerData.name, color: vm.computerData.color, nerdness: vm.computerData.nerdness }); // after our computer has been added, clear the form }; 사용자가 입력한 vm.computerData 값들을 vm.computers 리스트로 푸시
사용자 입력 폼 다루기 Index.html에 사용자입력 폼 추가 <!-- form to add computer to the list --> <form class="form-inline" ng-submit="main.addComputer()"> <input type="text" class="form-control" placeholder="Macbook" ng-model="main.computerData.name"> <input type="text" class="form-control" placeholder="Silver" ng-model="main.computerData.color"> <input type="number" class="form-control" placeholder="8" ng-model="main.computerData.nerdness"> <button type="submit" class="btn btn-success">Add</button> </form> 사용자가 입력하는 세개의 값을 main.computerData의 name, color, nerdness 변수로 받아들여 addComputer( ) 함수로 전달 Add 버튼을 누를 경우 addComputer( ) 함수를 실행 addComputer( ) 함수에서는 이 값들을 vm.computers 리스트로 푸시 뷰의 테이블에 즉시 반영됨 (data-binding)
사용자 입력 폼 다루기 결과 클릭하여 코드 수행 테스트 http://codepen.io/sevilayha/full/DhLqk/
사용자 입력 폼 다루기 Model ng-model View {{ }}, ng-view Controller ng-controller
두번째 예제 – Angular 라우팅 3개의 페이지를 갖는 single page application (SPA)을 제작해보자. Home About Contact
Single Page Application 이란? Single-Page Applications (SPAs) are Web apps that load a single HTML page and dynamically update that page as the user interacts with the app. SPAs use AJAX and HTML5 to create fluid and responsive Web apps, without constant page reloads. 별도의 페이지를 새로 읽어오는 방식이 아니라 페이지 레이아웃은 그대로 사용하고 필요한 업데이트 데이터만 ajax로 읽어옴
두번째 예제 – Angular 라우팅 Refresh가 필요 없는 single page application으로 동작 Phone app과 비슷한 느낌의 빠름과 편리성 사례: gmail, facebook, twitter 등 ngRoute 모듈의 기능 활용 이것을 구현하기 위해서는 서버가 필요함 Node, express를 이용하여 구현한 서버를 활용 가능 Node와 Angular를 함께 사용하는 서비스의 첫번째 사례
라우팅을 제공하는 node server Node, express를 사용하는 서버 생성 파일 구조 백엔드와 프론트엔드의 코드를 분리 백엔드: server.js 프론트엔드: public 폴더 서버 구축 - 새 폴더 생성 (md angular) - 폴더로 이동 (cd angular) - npm init - npm install express --save
Server.js 서버 프로그램 Index.html 파일을 제공하는 기능 서버 실행 nodemon server.js // get the things we need var express = require('express'); var app = express(); var path = require('path'); // set the public folder to serve public assets app.use(express.static(__dirname + '/public')); // set up our one route to the index.html file app.get('*', function(req, res) { res.sendFile(path.join(__dirname + '/public/views/index.html')); }); // start the server on port 8080 (http://localhost:8080) app.listen(8080); console.log('Magic happens on port 8080.'); Index.html 파일을 제공하는 기능 서버 실행 nodemon server.js 간단한 index.html 페이지 작성 브라우저로 확인 http://localhost:8080
샘플 어플리케이션 설계 3개의 페이지를 갖는 간단한 SPA 사이트 Home, About, Contact 페이지 Refresh가 필요 없는 SPA 각각의 페이지는 전체 레이아웃은 같고 컨텐츠만 다름 Public 폴더의 파일 구조
Index.html 생성 Bootstrap과 Font Awesome을 이용한 스타일 활용 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>My Routing App!</title> <!-- set the base path for angular routing --> <base href="/"> <!-- CSS --> <!-- load bootstrap and fontawesome via CDN --> <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css"> <link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.0/css/font-awesome.css"> <style> body { padding-top:50px; } </style> <!-- JS --> <!-- load angular and angular-route via CDN --> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular.min.js"></script> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular-route.js"></script> <script src="js/app.routes.js"></script> <script src="js/app.js"></script> </head> Bootstrap과 Font Awesome을 이용한 스타일 활용 Angular와 angular-route를 활용 우리가 생성할 angular 앱을 포함 - app.js, app.routes.js
Index.html 생성 페이지에 angular app과 controller를 적용 3개의 메뉴 생성 메뉴별 루트 지정 <body class="container" ng-app="routerApp" ng-controller="mainController as main"> <!-- HEADER AND NAVBAR --> <header> <nav class="navbar navbar-default"> <div class="navbar-header"> <a class="navbar-brand" href="/">Angular Routing Example</a> </div> <ul class="nav navbar-nav navbar-right"> <li><a href="/"><i class="fa fa-home"></i> Home</a></li> <li><a href="/about"><i class="fa fa-shield"></i> About</a></li> <li><a href="/contact"><i class="fa fa-comment"></i> Contact</a></li> </ul> </nav> </header> <!-- MAIN CONTENT AND INJECTED VIEWS --> <main> <!-- angular templating will go here --> <!-- this is where content will be injected --> <div ng-view></div> </main> </body> </html> 페이지에 angular app과 controller를 적용 3개의 메뉴 생성 메뉴별 루트 지정 ng-view를 메인 섹션에 설정 Ajax로 읽어오는 데이터를 이곳에 삽입 나머지 레이아웃은 그대로 사용
기본 페이지 Localhost:8080 Bootstrap을 이용한 자동 리사이징 - PC, 모바일, 태블릿 등 디바이스 화면의 크기에 맞추어 적절한 페이지 디자인으로 자동 변경
Angular의 모듈과 컨트롤러 생성 public/js/app.js routerApp을 정의 페이지별 컨트롤러 등록 angular.module('routerApp', [ ]) // create the controller and inject Angular's // this will be the controller for the ENTIRE site .controller('mainController', function() { var vm = this; // create a bigMessage variable to display in our view vm.bigMessage = 'A smooth sea never made a skilled sailor.'; }) // home page specific controller .controller('homeController', function() { vm.message = 'This is the home page!'; // about page controller .controller('aboutController', function() { vm.message = 'Look! I am an about page.'; // contact page controller .controller('contactController', function() { vm.message = 'Contact us! JK. This is just a demo.'; }); routerApp을 정의 페이지별 컨트롤러 등록 mainController 페이지별 컨트롤러 등록 homeController 페이지별 컨트롤러 등록 aboutController 페이지별 컨트롤러 등록 contactController
Angular 어플리케이션의 적용 Index.html의 body에 앱과 메인컨트롤러 등록 <main> 섹션에 bigMessage 표시 <body class="container" ng-app="routerApp" ng-controller="mainController as main"> <main> <div class="jumbotron"> <h1>{{ main.bigMessage }}</h1> </div> <!-- angular templating will go here --> <!-- this is where content will be injected --> </main>
Main Layout에 페이지 삽입하기 ng-view는 메인 레이아웃에 현재 루트((/home, /about, /contact)의 템플릿을 가져와 삽입하도록 하는 지시자 Angular route (ngRoute) 는 현재 URL에 맞는 view 파일을 가져 와 ng-view 섹션에 삽입함 <main> 섹션에 다음과 같이 ng-view 영역을 생성 <main> <!-- angular templating will go here --> <!-- this is where content will be injected --> <div ng-view></div> </main>
루트 설정 $routeProvider 서비스 $locationProvider 서비스 .when() 을 이용한 루트 설정 route, template file, controller를 연결 $locationProvider 서비스 $location 서비스는 URL을 파싱하여 어플리케이션에 전달 AngularJS에서는 기본적으로 해쉬태그 #을 이용하여 라우팅 http://example.com/#/about AngularJS에서 기본 설정되는 해쉬태그 #을 사용하지 않도록 서 비스 설정 필요. 이를 위해서는 $locationProvider.html5Mode(true) HTML5 모드를 true로 설정, HTML5 History API를 사용 가능 <head> 영역에 <base href="/"> 설정 – 이미 적용
루트 설정 public/js/app.routes.js templateUrl의 파일을 읽어와서 ng-view 영역에 삽입 // inject ngRoute for all our routing needs angular.module('routerRoutes', ['ngRoute']) // configure our routes .config(function($routeProvider, $locationProvider) { $routeProvider // route for the home page .when('/', { templateUrl : 'views/pages/home.html', controller : 'homeController', controllerAs: 'home' }) // route for the about page .when('/about', { templateUrl : 'views/pages/about.html', controller : 'aboutController', controllerAs: 'about' // route for the contact page .when('/contact', { templateUrl : 'views/pages/contact.html', controller : 'contactController', controllerAs: 'contact' }); $locationProvider.html5Mode(true); templateUrl의 파일을 읽어와서 ng-view 영역에 삽입 HTML5 모드를 true로 설정, HTML5 History API를 사용 가능
루트 설정 메인 앱에 루트 삽입 public/js/app.js angular.module('routerApp', [‘routerRoutes’]) public/js/app.routes.js angular.module('routerRoutes', ['ngRoute'])
Html 페이지 등록 About.html Contact.html Home.html <div class="jumbotron text-center"> <h1>About Page</h1> <p>{{ about.message }}</p> </div> 컨트롤러에서 정의한 메시지를 읽어와서 보여줌 <div class="jumbotron text-center"> <h1>Contact Page</h1> <p>{{ contact.message }}</p> </div> <div class="jumbotron text-center"> <h1>Home Page</h1> <p>{{ home.message }}</p> </div> .when('/', { templateUrl : 'views/pages/home.html', controller : 'homeController', controllerAs: 'home' }) Html 파일의 기본형식을 갖추지 않고 <div> </div> 영역만 있는 페이지
SPA 완성 페이지 리프레쉬 없이 즉시 열림
전체 구조 리뷰 index.html app.js app.route.js pages ng-app=“routerApp” 모듈, 컨트롤러를 적용 모듈, 컨트롤러 생성 루트 정의 ng-app=“routerApp” routerApp, [routerRoutes] routerRoutes, [ngRoute] home.html about.html contact.html mainController homeController aboutController contactController .when('/', { templateUrl : 'views/pages/home.html', controller : 'homeController', controllerAs: 'home' ng-controller=“mainController” .when('/about', { templateUrl : 'views/pages/about.html', controller : 'aboutController', controllerAs: 'about' ng-view .when('/contact', { templateUrl : 'views/pages/contact.html', controller : 'contactController', controllerAs: 'contact'
또다른 라우팅 기술 UI router UI router의 새로운 기능 http://angular-ui.github.io/ 어플리케이션의 상태(state)에 따라 라우팅 – 로그인 여부에 따라 다른 라우팅 제공 결합된 상태(Nested states)에 따른 라우팅 https://scotch.io/tutorials/angular-routing-using-ui-router
Angular 애니메이션 필요성 사용하는 기술 앞에서 만든 Angular routing 예제에 애니메이션을 적용 해 보자 Angular SPA는 모바일 어플리케이션과 비슷한 느낌을 제공 ngAnimate 모듈을 이용하여 애니메이션을 제공할 수도 있음 애니메이션을 이용하여 일반적인 모바일앱과 동일한 경험을 제 공하고자 함 사용하는 기술 ngAnimate: 페이지 애니메이션 생성 CSS animation: 페이지 애니메이션 실행 앞에서 만든 Angular routing 예제에 애니메이션을 적용 해 보자
Angular 애니메이션 ngAnimate 모듈의 원리 애니메이션 적용 가능한 Angular 지시자들 페이지가 처음 로드될때와 나갈때 Angular 지시자에 CSS 클래스 를 추가하거나 삭제함으로써 애니메이션 효과를 발생시킴 .ng-enter: 페이지가 로드될때 사용되는 CSS 클래스 .ng-leave: 페이지를 나갈때 사용되는 CSS 클래스 애니메이션 적용 가능한 Angular 지시자들 ngView, ngRepeat, ngInclude, ngIf, ngSwitch, ngShow, ngHide, ngClass 여기에서는 ngView 에 적용하는 사례를 보임
사용할 수 있는 애니메이션의 종류 http://daneden.github.io/animate.css/ 다양한 종류의 애니메이션
애니메이션 적용하기 ngAnimate 모듈을 적용하는 3단계 1. Link to the angular-animate.js file (angular-animate.js 파일을 CDN에서 읽어오기) 2. Inject the ngAnimate module into our main Angular module (ngAnimate 모듈을 메인 Angular 모듈에 삽입) 3. Add the animate.css stylesheet to have prebuilt CSS animations (스타일시트에 애니메이션 정의)
애니메이션 적용하기 1. Index.html 수정 angular-animate.js, animate.min.css 파일을 CDN에서 읽어오기 <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/animate.css/3.1.1/animate.min.css"> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular-animate.js"></script>
애니메이션 적용하기 2. Angular 모듈에 ngAnimate 모듈 삽입 3. CSS 애니메이션 삽입 public/css/style.css 파일 생성 Index.html에 CSS 설정 ng-view를 위한 이름 등록 ng-view 영역을 content-view라는 id를 가진 영역 안에 넣음 angular.module('routerApp', ['routerRoutes', 'ngAnimate']) <link rel="stylesheet" href="css/style.css">
애니메이션 적용하기 public/css/style.css 수정 # - ID 정의 . - class 정의 #content-views 아이디 등록 .ng-enter 클래스 설정 zoomInDown 애니메이션 설정 .ng-leave 클래스 설정 zoomOutDown 애니메이션 설정 # - ID 정의 . - class 정의
애니메이션 적용하기 Index.html에 css 파일 적용 <head> <meta charset="utf-8"> <title>My Routing App!</title> <!-- set the base path for angular routing --> <base href="/"> <!-- CSS --> <!-- load bootstrap and fontawesome via CDN --> <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css"> <link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.0/css/font-awesome.css"> <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/animate.css/3.1.1/animate.min.css"> <link rel="stylesheet" href="css/style.css"> <!-- JS --> <!-- load angular and angular-route via CDN --> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular.min.js"></script> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular-route.js"></script> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular-animate.js"></script> <script src="js/app.routes.js"></script> <script src="js/app.js"></script> </head>
사이트 테스트 애니메이션 적용 확인 * style.css에 다른 애니메이션을 적용하고 테스트 해보자.
요약 Angular는 front-end 개발에 널리 사용되는 MVC 기반 프레임워크 다뤄 본 예제 Data-binding, Dependency injection, Directives 이용 다뤄 본 예제 1. Data-binding 예제 2. 라우팅을 이용한 SPA 3. Angular animation