프런트 엔드 구현

프런트 엔드 개발

프런트 엔드는 jQuery를 사용하여 구현하는 사례가 많습니다. 그도 그럴 것이 순수하게 JavaScript만으로 처리를 구현하려면 각 브라우저의 고유 사양에 대응해야 하므로, 개발자는 브라우저별로 처리를 구현해야 합니다. 반면에 jQuery를 사용하면 jQuery가 브라우저 간의 동작 차이를 흡수하므로, 개발자의 부담이 줄어듭니다.

jQuery의 특징

  • 브라우저에 의존하지 않는 DOM 조작
  • 이벤트와 CSS 조작 등 취급이 간단
  • 이팩트와 애니메이션
  • Ajax와 쉽게 통신
  • 확장성(jQuery 플러그인)

jQuery 간단 사용법

다음과 같은 페이지가 있고 선택된 요소를 JavaScript로 가져온다고 가정해봅시다.

<html>
<head>
	<meta content="text/html" charset="UTF-8">
	<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
</head>
<body>
	<form>
		<label><input type="radio" name"fruit" value="사과" checked>사과</label>
		<label><input type="radio" name"fruit" value="딸기">딸기</label>
		<label><input type="radio" name"fruit" value="귤">귤</label>
	</form>
</body>
</html>

jQuery를 사용하지 않고 순수 JavaScript로만 구현하는 이런 느낌일 것입니다. 먼저 document.getElementsByName으로 라디오 버튼 요소를 모두 가져와서 for 루프로 요소를 하나씩 checked인지 확인합니다. checked인 요소를 발견할 때까지 반복합니다.

var checkedVal;
var radio buttons = document.getElementsByName('fruit');
for (var i = 0; i < radioButtons.length; i++) {
	if (radioButtons[i].checked) {
	checkedVal = radioButtons[i].value;
	break;
	}
}
alert(checkedVal);

반면에 jQuery를 사용하면 다음처럼 단 두 줄만으로도 동일하게 처리할 수 있습니다.

var checkedVal = jQuery('[name="fruit"]:checked').val();
alert(checked);

DOM 요소 가져오기

부모 요소 가져오기

부모 요소를 가져오는 방법 하나를 봐도 parent, parents, closest라는 API를 제공합니다. 각 API의 차이는 다음 표와 같습니다.

  • 부모 요소를 가져오는 API의 차이
API 설명
parent 바로 위 부모 요소만 가져온다(조상 요소까지 거슬러 올라가지 않는다.)
parents 조상 요소까지 거슬러 올라가서 가져온다.
closest 지정한 인수와 일치하는 가장 가까운 조상 요소를 가져온다.
자식 요소 가져오기

자식 요소를 가져오는 방법으로 children, find와 같은 API가 준비되어 있습니다. 각 차이는 다음의 표와 같습니다.

  • 자식 요소를 가져오는 API의 차이
API 설명
children 자식 요소만 가져온다(손자 요소는 가져오지 않는다)
find 자손 요소까지 모두 대상으로 해서 가져온다
형제 요소 가져오기

next나 prev 등 API가 준비되어 있습니다.

  • 형제 요소를 가져오는 API의 차이
API 설명
next 바로 다음에 있는 형제 요소만 가져온다.
nextAll 바로 이후에 있는 모든 형제 요소를 가져온다.
prev 바로 앞에 있는 형제 요소만 가져온다.
prevAll 이전에 나온 모든 형제 요소를 가져온다.

jQuery 오브젝트

jQuery는 실제로 jQuery 오브젝트라고 하는 데이터로 되어 있습니다.

> $("#target") instanceof jQuery
true

DOM 요소를 가져올 때 복수의 요소가 반환되는 경우, 요소 중에서 맨 앞쪽 데이터를 추출하면 그 데이터는 jQuery 오브젝트가 아니므로 주의해야합니다.

> $("li")
{
	<li>Foo</li>,
	<li id="target">Target</li>,
	<li>Bar</li>,
	<li>Baz</li>,
]
> $("li") instanceof jQuery
true
> $("li")[0] instanceof jQuery
false

특정 인덱스의 요소를 가져올 때는 first 나 last, 인덱스 번호를 지정할 수 있습니다.

> $("li:first") instanceof jQuery
true
> $("li").eq(0) instanceof jQuery
true

CoffeeScript

CoffeeScript는 Ruby나 Python에서 영향을 받아 탄생한 JavaScript로 변환 가능한 프로그래밍 언어입니다. 간단히 말해, JavaScript의 신택스 슈가입니다. 컴파일하여 JavaScript로 변환할 수 있고, JavaScript보다 간결하고 코드양도 적습니다.

CoffeeScript의 특징

  • 변수를 선언하는 var가 필요 없다(자동으로 부여)
  • 문장 끝에 ;(세미콜론)이 필요 없다
  • {}는 들여쓰기(인덴트)로 표현한다
  • ()는 모호하지 않을 경우 생략할 수 있다

CoffeeScript 사용

CoffeeScript에서는 다음처럼 배열을 for 루프로 돌리거나 함수 정의(fuction)을 ‘->’로 대신 쓸 수 있습니다.

names = ["kyeonghan", "yoon", "han"]

hello = (name) ->
	alert "Hi, #{name}"
	
for name in names
	hello(name if name.length > 5

위의 내용을 JavaScript로 변환하기

$ coffee -c test.coffee
//Generated by CoffeeScript 1.10.0
(function() {
	var hello, i, len, name, names;
	
	name = ["kyeonghan", "yoon", "han"];
	
	hello = function(name) {
		return alert("Hi, " + name);
	};
	
	for (i = 0, len = names.length; i < len; i++) {
		name = names[i];
		if (name.length > 5) {
			hello(name);
		}
	}
	
}).call(this);
  • JavaScript와 CoffeeScript 연산자 비교
JavaScript CoffeeScript
=== is
!== isnt
! not
&& and
|| or
존재 검사 연산자

다음과 같은 CoffeeScript가 있다고 하자.

alert "ok" if name

JavaScript로 변환하면 다음과 같지만, 문제가 있습니다. 예를 들어, name이 ‘undefined’일 때도 alert가 실행되어 버립니다.

if (name) {
	alert("ok");
}

그렇다면 존재를 검사하는 연산자를 사용하면??

alert "ok" if name?

JavaScript는 다음처럼 변환됩니다.

if (typeof name !== "undefined" && name !== null) {
	alert("ok");
}

이렇게 하면 name이 ‘undefined’일 때는 alert를 실행하지 않습니다.

TypeScipt

TypeScipt는 마이크로소프트가 개발한 프로그래밍 언어입니다. CoffeeScript와 마찬가지로 JavaScript의 신택스 슈가이지만, 변수를 선언할 때 데이터형을 지정할 수 있다는 특징이 있습니다.

TypeScipt 도입

$ sudo npm install -g typescript

TypeScipt 사용

test.ts에 다음 코드를 입력합니다.

var name:string = "yoon";

컴파일해봅시다.

$ tsc test.ts

tsc 커맨드를 실행하면, 컴파일되어 test.js가 생성됩니다.

  • JavaScript, CoffeeScript, TypeScipt의 차이
종류 특징 확장자
JavaScript - .js
CoffeeScript 짧고 간결하게 기술할 수 있다. .coffee
TypeScript 데이터형을 지정할 수 있다 .ts

Grunt

Grunt는 JavaScript로 기술된 테스크를 실행하는 자동화 도구 입니다. 최근 프런트 엔드 성능을 향상하려고 JavaScript와 CSS 파일을 최소화하고 이미지 파일을 최적화하는 일이 늘었습니다. 파일을 수정할 때마다 이런 작업을 일일이 수작업으로 하는 것은 매우 힘이 듭니다. Grunt를 사용하면 이런 작업을 자동화할 수 있습니다.

Grunt 도입

$ sudo npm install -g grunt-cli

Grunt를 사용할 때는 다음 두가지 파일이 필요합니다.

  • package.json
  • Gruntfile.js(또는 Gruntfile.coffee)

package.json의 내용은 다음과 같습니다.

{ 
	"name": "grunt-test",
	"version": "0.0.0",
}

Coffee.Script를 컴파일할 때 몇 가지 필요한 모듈이 있으므로 함께 설치합니다.

$ npm install grunt --save-dev
$ npm install grunt-contrib-watch --save-dev
$ npm install grunt-contrib-coffee --save-dev

Grunt로 처리 자동화

module.exports = (grunt)->

	# 테스크 설정 
	grunt.initConfig
		pkg: grunt.file.readJSON 'package.json'
		watch:
			files: ['src/**/*.coffee']
			tasks: 'coffee'
		coffee:
			compile: files: [
				expand: true
				cwd: 'src/'
				src: ['**/*.coffee']
				dest: 'dest/'
				ext: '.js'
			]
			
		# 모듈 로드 
		grunt.loadNpmTasks 'grunt-contrib-coffee'
		grunt.loadNpmTasks 'grunt-contrib-watch'
		
		# 테스크 등록 
		grunt.registerTask 'default', ['watch']
		return

이제 이 Gruntfile.coffee가 있는 디렉터리에서 grunt 커맨드를 실행합니다.

$ grunt
Running "watch" task
Waiting...

JavaScript 프레임워크 등장

jQeury로 프런트 엔드 개발이 매우 편해졌다는 사실을 알았습니다. 그런데 왜 Backbone.js, AngularJS, Ember.js, Vue.js와 같은 JavaScript 프레임워크가 등장한 걸까? jQuery만으로는 부족했을까? 그 이유는 크게 두가지 입니다.

  • DOM 변경에 약한 jQuery
  • 대규모화된 프런트 엔드 개발

DOM 변경에 약한 jQuery

jQeury는 아주 편리하지만, DOM을 탐색하기에는 아무래도 DOM 구조 변경에 취약합니다.

$("#target").parent().next().find(".defualt").hide();

특정 ID요소에서 부모 요소의 형제 요소를 찾아 그중 class 이름이 default인 자손 요소를 비표시로 하는 처리입니다. jQuery에서는 이처럼 DOM을 탐색하는 처리를 간단히 기술할 수 있어 편리하지만, 그 편리함 때문에 약간만 DOM 구조를 변경해도 바르게 동작하지 않아 버그의 원인이 됩니다.

대규모화된 프런트 엔드 개발

서버사이드 개발에서는 이전부터 MVC(Model-View-Controller)라는 디자인 패턴을 이용하여 비즈니스 로직은 모델에, 디자인은 뷰에 책임을 분산했습니다. 최근 프런트 엔드 개발 규모가 커지자 서버사이드 개발과 마찬가지로 프런트 엔드 개발에서도 MVC 디자인 패턴으로 비즈니스 로직과 디자인을 따로 분리하려는 경향을 보입니다.

AngularJS 특징

AngularJS는 구글에서 만든 풀 스택 JavaScript 프레임워크 입니다. Backbone.js 등은 최소한의 기능만 있기 때문에 부족한 기능은 서드파티 플러그인이나 라이브러리를 조합해서 개발해야 합니다. 하지만 AngularJS에서는 필요한 기능을 기본으로 지원합니다.

AngularJS의 특징

  • HTML을 그대로 템플릿으로 사용
  • 양방향 데이터 바인딩
  • DI 컨테이너

HTML을 그대로 템플릿으로 사용

AngularJS에서는 HTML을 그대로 템플릿으로 사용할 수 있습니다. HTML을 기반으로 커스텀 태그와 커스텀 속성을 지정하여 조건 분기나 반복 등을 제어할 수 있습니다. 겉보기에는 거의 일반 HTML과 다르지 않으므로 도입하기도 쉽습니다.

AngularJS에서는 커스텀 태그와 커스텀 속성을 ‘Directive’라고 합니다. ng-if나 ng-repeat등 굉장히 많은 Directive가 준비되어 있습니다.

양방향 데이터 바인딩

AngularJS의 가장 큰 특징은 양방향 데이터 바인딩입니다. 양방향 바인딩이란 ‘화면에 뭔가 입력했을 때 JavaScript 변수에 값이 반영되는 처리’와 ‘JavaScript’에서 변수 값이 변했을 때 화면에 다시 그리는 처리’를 양방향으로 하는 것 입니다. 이렇게 아주 매끄럽게 연계하는 것이 AngularJS의 강점입니다.

DI 컨테이너

AngularJS의 큰 특징은 ‘DI(Dependency Injection)’이라는 DI패턴을 이용해서 의존관계를 관리하는 매커니즘입니다. AngularJS를 능숙하게 사용하려면, DI 컨테이너를 반드시 이해해야 합니다. 예를 들어, 다음처럼 ‘myApp’이라는 모듈을 정의하고, 그 안에 ‘message’ 속성이 있는 ‘greetService’라는 Service를 정의하겠습니다.

var myApp = angular.module("myApp", []);
myApp.service("greetService", fuction() {
	this.message = "Hello World!"
});

이 Service를 다른 곳에서 호출해서 사용해 봅시다.

var myApp = angular.module("myApp"); // sample_service.js에서 정의한 module을 가져온다
myApp.controller("MyCtrl", ["$scope", "greetService", function($scope, greetService) {
	$scope.greet = greetService.message;
}]);

이 매커니즘 덕분에 기능을 역할별로 모듈화하여 관리할 수 있습니다.

AngularJS 사용

AngularJS는 공식 사이트에서 다운로드 한뒤, script 태그로 불러오면 됩니다.

<script src="libs/angularjs/1.2.29/angular.min.js"></script>

또 다음처럼 구글에 호스팅되는 CDN(Contents Delivery Network)을 사용할 수도 있습니다.

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.29/angular.min.js"></script>

DOM 조작

AngularJS에서는 DOM을 조작하려고 jqlite라는 jQuery 호환 API를 준비하여 두었습니다.

jqlite

Angular.element를 사용하면 jqlite 오브젝트를 가져올 수 있습니다. HTML 안에 있는 임의의 요소를 인수로 전달하면 됩니다.

> angular.element(document.getElementById('wrap'))
$scope.$apply

AngularJS에서는 $scope 속성이 변하면 화면도 자동으로 다시 그립니다. 하지만 AngularJS의 관리 밖에서 이벤트가 발생하면 자동으로 처리하지 않으므로, $scope 오브젝트 내용을 수정해도 화면에 그린 내용은 예전과 같을 때가 있습니다.

다음의 내용은 focus 이벤트가 발생하지만 이 이벤트는 AngularJS의 관리 밖에 있습니다. 이때는 $scope.$apply를 사용해서 명시적으로 화면을 다시 그립니다

$("#target").on("focus", function() {
	$scope.$apply(function() {
		$scope.isFocus = true;
	});
});

컨트롤러 사용

다음 HTML을 템플릿으로 합니다. ng-controller=”MainCtrl”로 지정하여 div 요소 안에서 MainCtrl의 변수와 메소드를 사용할 수 있는 상태로 합니다. ng-repeat는 루프 처릴를 하는Directive입니다.

<!doctype html>
<html ng-app>
	<head>
		<meta content="text/html" charset="UTF-8">
		<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.29/angular.min.js"></script>
		<script src="controller.js"></script>
	</head>
	<body>
		<div ng-controller="MainCtrl">
			 users.
			<ul ng-repeat="user in users">
				<li>()</li>
			</ul>
		</div>
	</body>
</html>
  • MainCtrl은 다음처럼 구현합니다. $scope라는 특수한 오브젝트에 임의의 속성을 지정하고, 그 속성을 HTML 쪽에서 불러낼 수 있습니다.
var MainCtrl = function($scope) {
	$scope.users = [
		{name: "dooli", age: "21"},
		{name: "ttochi", age: "31"},
		{name: "gildong", age: "38"},
	];
}

TODO 리스트 구현

컨트롤러 쪽에서 초기 태스크를 준비하고, 초기 태스크를 ng-repeat로 표시합니다. 체크박스는 ng-model=”task.done”으로 하여 task.done값에 따라 표시를 바꿉니다. 또 ng-class를 사용하여 task.done이 true면 done이라는 이름을 붙이고, CSS에서 표시를 바꿉니다.

<!doctype html>
<html ng-app>
	<head>
		<meta content="text/html" charset="UTF-8">
		<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.29/angular.min.js"></script>
		<script src="todo.js"></script>
		<style>
			.done {
				color: gray;
				text-decoration: line-through;
			}
		</style>
	</head>
	<body>
		<div ng-controller="todoCtrl">
			<ul ng-repeat="task in tasks">
				<li>
					<input type="checkbox" ng-model="task.done">
					<span ng-class="{done: task.done}"></span>
				</li>
			</ul>
		</div>
	</body>
</html>
  • JavaScript쪽은 다음처럼 name과 done 속성이 있는 태스크의 배열로 되어 있습니다.
var todoCtrl = function($scope) {
	$scope.tasks = [
		{name: "task1", done: true},
		{name: "task2", done: false},
		{name: "task3", done: false},
		{name: "task4", done: false},
	];
}

ng-submit으로 폼을 전송하는 동작을 지정합시다.

<!doctype html>
<html ng-app>
	<head>
		<meta content="text/html" charset="UTF-8">
		<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.29/angular.min.js"></script>
		<script src="todo.js"></script>
		<style>
			.done {
				color: gray;
				text-decoration: line-through;
			}
		</style>
	</head>
	<body>
		<div ng-controller="todoCtrl">
			<ul ng-repeat="task in tasks">
				<li>
					<input type="checkbox" ng-model="task.done">
					<span ng-class="{done: task.done}"></span>
				</li>
			</ul>
			
			# <!-- 추가 -->
			<form ng-submit="addNewTask()">
				<input type="text" ng-model="newTaskName">
				<input type="submit" value="Add">
			</form>
		</div>
	</body>
</html>

이제 $scope.tasks 배열에 새로운 요소만 추가하면 화면 표시는 AngularJS가 자동으로 실행하니 아주 간단합니다. 또 마지막에 $scope.newTaskName을 비워서 다음 태스크를 매끄럽게 입력할 수 있게 해야 합니다.

var todoCtrl = function($scope) {
	$scope.tasks = [
		{name: "task1", done: true},
		{name: "task2", done: false},
		{name: "task3", done: false},
		{name: "task4", done: false},
	];
	// 추가
	$scope.addNewTask = function() {
		$scope.tasks.push({name: $scope.newTaskName, done: false});
		#scope.newTaskName="";
	}
}

전체 태스트가 몇 개이고, 그중에서 몇 개를 완료했는지 표시해봅시다.

<!doctype html>
<html ng-app>
	<head>
	...
	</head>
	<body>
		<div ng-controller="todoCtrl">
			<!-- 추가 -->
			<p>
				Done:  / 
			</p>
			
			
			<ul ng-repeat="task in tasks">
				<li>
					<input type="checkbox" ng-model="task.done">
					<span ng-class="{done: task.done}"></span>
				</li>
			</ul>
			
			
			<form ng-submit="addNewTask()">
				<input type="text" ng-model="newTaskName">
				<input type="submit" value="Add">
			</form>
		</div>
	</body>
</html>
  • JavaScript에서는 angular.forEach 구문으로 $scope.tasks를 계속 돌면서 각각의 task.done 값을 보고 완료된 태스크 수를 카운트 합니다.
var todoCtrl = function($scope) {
	$scope.tasks = [
		{name: "task1", done: true},
		{name: "task2", done: false},
		{name: "task3", done: false},
		{name: "task4", done: false},
	];
	// 추가
	$scope.addNewTask = function() {
		$scope.tasks.push({name: $scope.newTaskName, done: false});
		#scope.newTaskName="";
	}
	
	// 추가
	$scope.doneTaskCount = function() {
		var doneTaskCount = 0;
		angular.forEach($scope.tasks, function(task) { 
			doneTaskCount += task.done ? 1 : 0;
		});
		return doneTaskCount;
	}
}
디버깅

한 가지 더 기억해야 할 것이 바로 디버깅 방법입니다. AngularJS는 편리한 디버깅 방법을 제공합니다.

<!doctype html>
<html ng-app>
	<head>
	...
	</head>
	<body>
		<div ng-controller="todoCtrl">
			<!-- 추가 -->
			<p>
				Done:  / 
			</p>
			
			
			<ul ng-repeat="task in tasks">
				<li>
					<input type="checkbox" ng-model="task.done">
					<span ng-class="{done: task.done}"></span>
				</li>
			</ul>
			
			
			<form ng-submit="addNewTask()">
				<input type="text" ng-model="newTaskName">
				<input type="submit" value="Add">
			</form>
			
			<!-- 추가 -->
			<pre></pre>	
				
		</div>
	</body>
</html>

서버 통신

여기서는 Rails를 사용해서 서버 쪽에 간단한 API를 준비합니다. 먼저 새로 Rails 프로젝트를 준비합니다. 여기서는 ‘angular-sample’이름으로 프로젝트를 만들겠습니다.

$ rails new angular-sample --skip-bundle

다음으로 bundle install 커맨드로 필요한 gem을 설치합니다

$ cd angular-sample
$ bundle install --path=vendor/bundle

이번에는 User 정보를 다루는 API를 준비합니다. Users 컨트롤러와 User 모델이 필요합니다.

$ rails g controller users
$ rails g model user name
$ rake db:migrate
$ rails generate controller top index

TOP 페이지는 Top 컨트롤러의 index 액션을 담당하게 합시다. config/routes.rb를 다음처럼 작성합니다.

root 'top#index'
resource :users
  • 뷰는 다음처럼 AngularJS를 사용하도록 설정합니다. 또, ngResource 모듈을 사용하므로 이 모듈을 뷰에서 로드합니다.
<!DOCTYPE html>
<html ng-app="myApp">
	<head>
		<meta content="text/html" charset="UTF-8">
		<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.29/angular.min.js"></script>
		<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.29/angular-resource.min.js></script>
		<script src="angular.js"></script>
	</head>

	<body ng-controller="MainCtrl">
		<input type="text" ng-model="userName" />
		<button ng-click="addUser()">Add</button>
		<ul>
			<li ng-repeat="user in users"></li>
		</ul>
		<pre></pre>
	</body>
</html>

API 쪽 컨트롤러는 다음처럼 작성합니다. RESTful API로 되어 있습니다. index 액션으로 모든 사용자의 정보를 반환하고 show 액션으로 특정 사용자의 정보를 반환합니다. 또, create 액션에서는 주어진 파라미터를 이용하여 사용자를 새로 생성합니다.

class UserController < ApplicationController
	def index
		render json: User.all
	end
	
	def show
		render json: User.find(params[:id])
	end 
	
	def create
		render json: User.create(user_name)
	end
	private 
	
	def user_params
		params.require(:user).permit(:name)
	end
end	
  • 이제 index.html.erb에서 로드한 angular.js에 구체적인 처리를 구현합니다.

      var app = angular.module("myApp", ["ngResource"]);
    
      # Rails의 CSRF Token 대책
      app.config(["$httpProvider", function($httpProvider) {
          csrfToken = angular.element('meta[name=csrf-token]').attr('content')
          $httpProvidr.defaults.headers.post['X-CSRF-Token'] = csrfToken
          $httpProvidr.defaults.headers.put['X-CSRF-Token'] = csrfToken
          $httpProvidr.defaults.headers.patch['X-CSRF-Token'] = csrfToken 
      }]);
    
      var MainCtrl = function($scope, $resource) {
          var User = $resource("/users");
    
          $scope.users = User.query();
    
          $scope.addUser = function() {
              User.save({name: $scope.userName}, function(user) {
                  $scope.users.push(user);
              });
    
              $scope.userName = "";
          };
      }
    

ngResource에서 사용할 수 있는 액션

액션 HTTP 메소드
get GET
save POST
query GET
delete DELETE
remove DELETE



서비스

AngularJS에는 서비스라는 편리한 매커니즘이 있습니다. 서비스는 함수와 오브젝트 등을 AngularJS 애플리케이션 안에서 공유하는 매커니즘 입니다. 싱글톤으로 다루므로 컨틀로러 간 공유에도 이용할 수 있습니다. 다음은 대표적인 서비스 입니다.

  • $location
  • $timeout
  • $cookieStore(ngCookies)

$location

$location은 window.location을 AngularJS로 랩핑한 서비스입니다.

<!doctype html>
<html ng-app="app>
	<head>
		<meta content="text/html" charset="UTF-8">
		<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.29/angular.min.js"></script>
		<script src="location.js"></script>
	</head>
	</body>
		<div ng-controller="LocationCtrl">
			
		</div>
	</body>
</html>

컨트롤러 쪽에서 $location을 넘겨주고 그 값을 $scope가 갖게 하여 뷰쪽에서도 $location을 사용할 수 있습니다.

var app = anular.module('app', []);
app.controller('LocationCtrl', ['$scope', '$location', function($scope, $location) {
	$scope.$location = $location;
}]);

$timeout

$timeout은 window.setTimeout을 AngularJS로 랩핑한 서비스입니다.

AngularJS가 관리하지 않는 setTimeout 등 함수를 사용해서 $scope 값을 변경해도 화면을 다시 그리지 않습니다. 화면을 갱신하려면 $timeout을 사용해야 합니다. 사용법은 setTimeout과 완전히 똑같습니다.

<!doctype html>
<html ng-app="app>
	<head>
		<meta content="text/html" charset="UTF-8">
		<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.29/angular.min.js"></script>
		<script src="timeout.js"></script>
	</head>
	</body>
		<div ng-controller="TimeoutCtrl">
			
		</div>
	</body>
</html>
var app = anular.module('app', []);
app.controller('TimeoutCtrl', ['$scope', '$timeout', function($scope, $timeout) {
	$timeout(function() {
		$scope.message = '3초가 지났어요!'
	}, 3000);
}]);

$cookieStore(ngCookie)

ngCookie 모듈을 사용하면, 쿠키를 간단하게 조작할 수 있습니다.

<!doctype html>
<html ng-app="app>
	<head>
		<meta content="text/html" charset="UTF-8">
		<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.29/angular.min.js"></script>
		<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.29/angular-cookies.min.js"></script>
		<script src="cookies.js"></script>
	</head>
	</body>
		<div ng-controller="CookieCtrl">
			
		</div>
	</body>
</html>
var app = angular.module('app', ['ngCookies']);
app.controller('CookieCtrl', ['$scope', '$cookieStroe', function($scope, $cookieStore) {
	$cookieStore.put("name", "dooli");
	$scope.name = $cookieStore.get("name");
}]);

초기화 처리

$rootScope에 API의 URL을 지정하면 다음처럼 처리한다.

var app = angular.module("app", []);
app.run(function() {
	$rootScope.apiUrl = "http://exmaple.com/users";
});