내가 원페이지 앱도 별로 안좋아하고 또 HTML에 동작을 집어넣는 접근을 안좋아하기 때문에 그동안 안보고 있다가 최근 주변의 설득에 넘어가서 최근 Angular.js를 열심히 만져보고 있다. 보통 이러한 새로운 걸 만져보면 간단한 Hello World성 글을 올리는 편이지만 Angular.js는 초기 러닝커브가 좀 있는 편이라 이해를 하는데 시간이 꽤 걸렸고 개념을 제대로 이해하지 못한가는데 튜토리얼성 글을 어설프레 올리는게 위험해 보여서 굳이 올리고 있지 않았다.(그러다가 갑자기 Angular.js 팁같은 걸 올리는것도 좀 생뚱맞고...)
그러다가 Angular Tips 블로그에서 Why Does Angular.js Rock?라는 글을 보고 Angular.js를 소개하는 글로 괜찮고 예제도 잘 구성이 되어 있어서 굳이 내가 설명하는 것보다 낫겠다고 생각했다. 해당 블로그를 운영하는 Jesus Rodriguez한테 번역해도 된다는 허락도 받았기에 해당 글을 번역해서 올린다. Angular Tips 블로그는 Octopress로 되어 있어서 글마다 Angular.js 예제를 글 가운데 삽입하기가 괜찮았지만 내 블로그는 그런 구조가 아니므로 JSfiddle을 사용했다. 해보고 나니 예제마다 전체 소스를 볼 수 있어서 처음 Angular를 보는 사람에게는 소스를 보기 좀더 괜찮을 꺼라고 생각한다.
Angular.js는 왜 좋은가?(Why Does Angular.js Rock?)
Angular.js는 구글이 만든 MV*(Model - View - Whatever) 자바스크립트 프레임워크로 원페이지 어플리케이션에서 뛰어나면서 전통적인 웹 어플리케이션에 약간의 "마법"을 부린 것처럼 동작하는 것도 가능하다.
새로운 프로젝트에 Angular.js를 사용해야 하는 이유에 대해서 하루 종일 글을 쓸수도 있지만 직접 동작하는 것을 보는 것이 더 좋겠다고 생각했다.
데이터바인딩과 스코프(scope)
Angular.js에서 가장 처음 궁금해 하는 부분은 "데이터 바인딩의 지원여부"이다.
Angular.js의 데이터 바인딩 예제를 보자.
<!-- index.html -->
<body ng-app>
<span>Insert your name:</span>
<input type="text" ng-model="user.name" />
<h3>Echo: {{user.name}}</h3>
</body>
이 예제코드에서 설명해야 할 부분이 좀 있기는 하지만 설명하기 전에 먼저 Angular.js 코드에 좀 익숙해 져야 한다.
이 예제에서 보듯이 input
에 입력한 내용이 바로 출력된다. 동작방식을 설명하자면 ng-model
디렉티브로 input
이 양방향 바인딩(two-way binding) 된 것이다.(디렉티브에 대해서는 뒤에서 설명한다.)
그러면 user.name
는 어디에 저장되는지가 궁금할텐데 user.name
은 $scope
에 저장되어 있다. input
에 입력할 때마다 스코프의 user.name
객체가 갱신되고 Angular.js의 {{ ... }} 인터폴레이션으로 모델을 출력할 수 있다. 그래서 HTML에서 user.name
의 값을 볼 수 있는 것이다. input
에 입력할 때 user.name
이 스코프에 저장되고 인터폴레이션으로 HTML에서 그 값을 보게 된다.
어려운 내용은 아니지만 여기서 언급한 $scope
는 무엇인가가 궁금할 것이다. $scope
는 기본적으로 컨트롤러와 템플릿을 연결하고 모델을 보광해서 양방향 바인딩을 할 수 있게 하는 객체다. 이 개념은 다음과 같이 표현할 수 있다.
즉, 템플릿에서 $scope
에 user.name
을 설정하면 컨트롤러에서도 user.name
에 접근할 수 있다. 약간 더 복잡한 예제를 보자.
// app.js
var app = angular.module('app', []);
app.controller('MainCtrl', function($scope) {
$scope.message = 'World';
});
<!-- index.html -->
<body ng-app="app" ng-controller="MainCtrl">
Hello, {{ message }}
</body>
가장 먼저 해야할 작업은 Angular 어플리케이션을 정의하는 것이다. Angular 어플리케이션을 정의하려면 이름과 의존성에 대한 배열을 받는(1번 줄) Angular 모듈을 생성하면 된다. 이어서 app
에 컨트롤러를 생성해야 하는데 app module
에서 controller
메서드를 호출해서 생성할 수 있는데 이 메서드에 이름과 함수를 전달한다. controller
메서드에 전달하는 함수는 양방향 데이터 바인딩에 사용할 $scope
(자세한 내용은 뒤에서 설명한다)를 파라미터로 받고 이 함수내에서 $scope
에 message
문자열을 추가한다.
뷰 파일에서 body
태그에 무언가 추가된 것을 볼 수 있는데 이를 directive
라고 한다. 디렉티브는 HTML에 새로운 기능을 알려 주는 역할을 하는데 이 예제에서는 다음의 두 가지 디렉티브를 사용했다.
ng-app
은 Angular에게 body 요소가 Anuglar 어플리케이션에 포함되어 있다고 알려준다. 즉, body 요소내의 모든 것을 Angular 어플리케이션이 관리하도록 한다. 일반적으로는html
태그에 사용하고 파라미터는 어플리케이션의 이름으로 모듈에서 사용한 이름과 일치해야 한다.ng-controller
: 이 디렉티브를 사용하면 해당 요소의 스코프를 컨트롤러에 할당할다. 이 예제에서는MainCtrl
이다.
그리고 템플릿에서 message
를 사용했다. 이를 그림으로 표현하면 다음과 같다.
아마 이때쯤 $scope
에 함수를 바인딩할 수 있는지 궁금할 수 있는데 당연히 가능하다.
// app.js
var app = angular.module('app', []);
app.controller('MainCtrl', function($scope) {
$scope.greet = function() {
$scope.message = "Hello, " + $scope.user.name;
}
});
<!-- index.html -->
<body ng-app="app" ng-controller="MainCtrl">
What's your name?:
<input type="text" ng-model="user.name" />
<button ng-click="greet()">Click here!</button>
<h3>{{ message }}</h3>
</body>
컨트롤러를 보면 $scope
에 함수를 연결하는 방법을 알 수 있다. $scope
에 연결한 함수에서 인풋에 입력된 값인 $scope.user.name
의 문자열을 이어붙혀서 $scope
에 message
로 추가한다.
그리고 HTML에서 버튼을 생성하고 ng-click
디렉티브를 사용했다. 간단히 얘기하자면 ng-click
디렉티브는 해당 요소를 클릭할 수 있게 만들어서 클릴할 때마다 할당한 함수를 실행하는데 이 예제에서는 greet()
를 실행한다.
디렉티브(Directives)
디렉티브는 무엇인가? 디렉티브는 HTML에게 새로운 동작을 알려주는 방법이다. HTML은 아주 강력하기는 하지만 때로는 좀 더 강력했으면 할 때가 있다. 정말 그런지 직접 보자.
<!-- jquery_index.html -->
<body>
<div id="chart"></div>
</body>
이 코드는 어떤 동작을 할까? 아무런 힌트도 없고 id
가 있기는 하지만 이 id
가 어떤 역할을 할 지 누가 알겠는가? 어떤 동작을 하는지 알려면 HTML 파일에 나오는 30개의 자바스크립트 파일중에 하나를 봐야 한다.
// charts.js
$('#chart').pieChart({ ... });
이 부분을 찾아내면 위의 HTML이 파이차트를 담는 곳이라는 것을 알 수 있다. 여기서 문제점은 페이지에 사용한 모든 자바스크립트 파일을 보지 않으면 페이지가 무엇을 하는지 정확히 알 수 없다는 것이다.
이제 Angular 어플리케이션의 코드를 보자.
<!-- angular_index.html-->
<body>
<pie-chart width="400" height="400" data="data"></pie-chart>
</body>
훨씬 더 명확하지 않은가? 파이차트를 추가한다는 간다한 사실뿐만 아니라 크기가 어느정도 이고 어떤 데이터가 할당되었는지를 알 수 있다. 이 예제에 대해서 궁금하다면 재미삼아 만들어 본 pie-chart
예제에서 확인해 볼 수 있다.
내장 디렉티브
이미 ng-app
, ng-controller
, ng-click
, ng-model
를 봤지만(Angular는 ng
접두사를 사용한다.) Angular에는 다수의 내장 디렉티브가 존재한다. 이 내장 디렉티브를 살펴보자.
페이지에 어떤 프로퍼티가 true일 때만 보여줄 부분이 있다고 해보자.
<button ng-click="show = !show">Show</button>
<div ng-show="show">
I am only visible when show is true.
</div>
ng-show
는 표현식이 true
일때만(예제에서는 바인딩한 값) 해당 요소를 보여준다. 이 예제에서 ng-click
을 사용한 방법을 주의깊게 보길 바란다. 이 예제에서는 컨트롤러에 함수를 생성할 필요가 없으므로(컨트롤러 자체도 필요없다!) 디렉티브의 인자를 표현식으로 작성해서 show
의 값을 토글했다. show
는 undefined
로 시작되고 첫 클릭시 true
가 된다. ng-show
의 반대인 ng-hide
도 있다.
좀 더 재밌는 예제를 보자. 객체에 배열이 있고 이 배열의 목록을 출력하고자 하면 어떻게 하겠는가?
// app.js
var app = angular.module('app', []);
app.controller('MainCtrl', function($scope) {
$scope.developers = [
{
name: "Jesus", country: "Spain"
},
{
name: "Dave", country: "Canada"
},
{
name: "Wesley", country: "USA"
},
{
name: "Krzysztof", country: "Poland"
}
];
});
<!-- index.html -->
<body ng-app="app" ng-controller="MainCtrl">
<ul>
<li ng-repeat="person in developers">
{{person.name}} from {{person.country}}
</li>
</ul>
</body>
컨트롤러에 객체의 리스트를 정의한 것외에는 별로 특별한 내용은 없다. 이어서 HTML에서 ng-repeat
디렉티브를 사용했다. ng-repeat
는 컬렉션의 아이템마다 새로운 템플릿을 생성할 것이다. 예제에서는 4개의 아이템이 있으므로 ng-repeat
가 이 코드 부분을 4번 생성할 것이다.
<li ng-repeat="person in developers">
{{person.name}} from {{person.country}}
</li>
ng-repeat
에서 각 복사본은 자신만의 스코프를 가진다. 그래서 템플릿에서는 컨트롤러가 스코프의 역할을 하지 않고 이 예제에서는 person
이 스코프가 된다. 다시 말하자면 여기서는 부모 컨트롤러에 대한 접근을 하지 않는다.(실제로는 부모 컨트롤러에 접근하는 방법이 있기는 하다.) 이를 그림으로 표현하면 다음과 같다.
자신만의 디렉티브를 만들 수 있는가?
당연히 가능하다! 거의 모든 것을 만들 수 있는데 모달 다이얼로그, 어코디언, 페이지네이터, 차트, 검색폼 등에 대한 디렉티브를 만들 수 있다. 예시로 든 것처럼 항상 보여지는 것이어야 하는 것은 아니고 보이지 않는 부분에 대한 디렉티브를 만들 수도 있다. 앞에서 사용했던 greet 예제로 돌아가 보자.
<!-- form.html -->
<body ng-app="app" ng-controller="MainCtrl">
What's your name?:
<input type="text" ng-model="user.name" />
<button ng-click="greet()">Click here!</button>
<h3>{{ message }}</h3>
</body>
이 코드는 잘 동작하기는 하지만 페이지를 로딩했을 때 인풋에 포커싱을 주고 싶다면 어떻게 해야 하는가? jQuery를 사용해서 인풋에 focus()
메서드를 호출해야 하는가? 당연히 아니다. 우리는 디렉티브에서 HTML이 최대한 자기서술적이 되기를 원하기 때문에 focus
디렉티브를 생성할 것이다.
// focus.js
app.directive('focus', function() {
return {
link: function(scope, element, attrs) {
element[0].focus();
}
};
});
그래서 app
객체의 directive
함수를 호출한다. directive
는 컨트롤러처럼 디렉티브의 이름과 함수를 받는다. 디렉티브는 Angular.js에서 가장 복잡하지만 (이 글을 쇼케이스같은 글이므로) 간단히만 설명할 것이다.(추후에 이 주제로 글을 따로 올리겠다.) 디렉티브는 객체를 반환해야 하고 이 반환 객체에 몇가지 속성을 정의할 수 있지만 이 예제에서는 속성을 사용하지 않았다. 디렉티브는 link
함수를 반환할 수 있는데 이 link
함수 안에 템플릿 로직의 대부분을 작성하고 여기서 DOM 리스너를 등록하거나 DOM을 갱신하는 등의 작업을 할 수 있다.
이 link
함수는 3개의 파라미터를 받는다.(실제로는 4개지만 이는 약간 고급에 해당한다.) 3개의 파라미터는 scope
와 디렉티브를 사용한 element
와 element
의 속성인 attr
이다. 여기서 HTML 요소에 click
이벤트나 mouseenter
이벤트를 바인드할 수 있다.
이 예제에서는 첫번째 요소(인풋)을 가져와서 focus
함수를 호출했다. element
가 어떻게 동작하는지 궁금하면 공식문서 Element API를 참고해라.
이제 남은 작업을 이 디렉티브를 사용하는 것 뿐이다. 포커스를 주고자 하는 요소에 이 디렉티브 이름을 추가하면 된다.
<!-- form.html -->
<body ng-app="app" ng-controller="MainCtrl">
What's your name?:
<input type="text" focus ng-model="user.name" />
<button ng-click="greet()">Click here!</button>
<h3>{{ message }}</h3>
</body>
의도한 기능이 잘 동작하지만 이 디렉티브는 정말 간단하다.(이 예제는 블로그 포스트내에서는 제대로 포커스가 동작하지 않으니 JSFiddle에서 직접 확인하기 바란다. - 글쓰고 확인할때는 포커싱이 잘 안되어 이렇게 써놨었는데 브라우저에 따라서는 아예 포커스가 옮겨가기도 하는것 같네요. 일단 실행결과가 바로 뜨지 않도록 수정했습니다.)
그러면 HTML을 렌더링하는 디렉티브는 어떻게 작성해야 할까? 다음 예제를 보자.
// hello.js
app.directive('hello', function() {
return {
restrict: "E",
replace: true,
template: "<div>Hello readers, thank you for coming</div>"
}
});
이 예제는 (앞에서 얘기했듯이) 몇 가지 속성이 설정된 객체를 반환한다.
- restrict: 디렉티브는 여러 위치에 사용할 수 있다.
A
ttribute, 예시:<div foo></div>
E
lement, 예시:<foo></foo>
C
lass, 예시:<div class="foo"></div>
- Co
M
ment, 예시:<!-- directive: foo -->
- replace: 이 값을
true
로 설정하면 해당 요소는 새로운 템플릿으로 대체될 것이다. - template: HTML 요소에 추가할(또는 대체할) 템플릿을 여기에 둔다.
요소에 사용할 디렉티브를 제한하고(기본값은 속성으로 제한된다.) HTML 요소를 대체할 템플릿을 지정했다. 디렉티브에서 사용할 수 있는 많은 옵션이 더 있기는 하지만 추가적인 작업이 좀 더 필요하다. 이 디렉티브에서는 로직이 필요없으므로 link
함수는 사용하지 않았다. 사용방법은 다음 예제를 보자.
<hello></hello>
코드를 보면 기대한 대로 <hello></hello>
가 <div>Hello readers, thank you for coming</div>
로 대체된 것을 알 수 있다.
필터
쇼핑 장바구니를 보여주는 화면이 있다고 해보자.
<span>There are 13 phones in the basket. Total: {{ 1232.12 }}</span>
이 예제로 인터폴레이션에서 기본적인 표현식을 사용하는 방법을 알 수 있다. 예제에서는 숫자를 출력했는데 당연히 읽을 수 있고 이 숫자가 $1,232.12를 의미한다는 것을 알 수 있지만 숫자를 금액으로 변환해서 보여준다면 훨씬 좋을 것이다. 이는 필터를 사용하면 쉬운데 다음 예제는 currency
필터를 사용하는 예제다.
<span>There are 13 phones in the basket. Total: {{ 1232.12 | currency }}</span>
훨씬 나아졌다. 이 예제에서 볼 수 있듯이 |
로 필터를 사용할 수 있는데 이는 유닉스 환경에서 파이프를 사용하는 것과 비슷하다. 표현식에서는 다수의 필터를 파이프로 연결할 수 있는데 예를 들어 ng-repeat
에서 정렬을 할 수도 있다. 앞에서 보았던 개발자 목록을 출력하는 예제를 다시 보자.
<ul>
<li ng-repeat="person in developers | orderBy:'name'">
{{ person.name }} from {{ person.country }}
</li>
</ul>
이 예제에는 흥미로운 부분이 있는데 필터에 파라미터를 전달했다. orderBy
필터는 정렬에 사용할 값(predicate)를 받는다. 예제에서는 name
을 전달했으므로 name
으로 목록을 정렬할 것이고 이 파라미터에 -name
를 전달하면 역순으로 정렬할 것이다.
이정도로도 유용하다고 생각할 것이지만 좀 더 괜찮은 예제를 보자. 4명의 개발자가 아니라 300명의 개발자가 있고 이를 (name, country등으로) 필터링하기를 원한다고 해보자. 이를 위해서 컬렉터를 필터링하는 방법을 정하고 필터링되지 않은 컬렉션을 필터링한 컬렉션으로 교체하려고 할텐데 더 간단한 방법이 있다.(개발자 목록 예제에서 사용한 것과 같은 컨트롤러를 다시 사용한다.)
<body ng-app="app" ng-controller="MainCtrl">
Search: <input ng-model="search" type="text" />
<ul>
<li ng-repeat="person in developers | filter:search">
{{ person.name }} from {{ person.country }}
</li>
</ul>
</body>
놀랍지 않은가? 이 예제에서는 필터를 사용한 것이 전부인데 filter
필터에 담길 파라미터를 전달했다. 예제에서 스코프에 바인딩되어 있으면서 인풋에 할당된 search
를 전달했다. 필요하다면 다음과 같이 좀 더 정밀한 필터를 만들 수도 있다.
<body ng-app="app" ng-controller="MainCtrl">
Search: <input ng-model="search.name" type="text" />
<ul>
<li ng-repeat="person in developers | filter:search">
{{ person.name }} from {{ person.country }}
</li>
</ul>
</body>
이 예제에서는(인풋에서 search.name
를 바인딩하는 방법을 봐라.) 단순히 이름으로 필터링하고 있고 필터 파라미터는 바꾸지 않았다. 필터 파라미터는 search
객체에 바인딩되어 있고 입력의 이름을 찾아서 이름으로 필터링한다.
이번에는 자신만의 필터를 직접 생성해 보자. 첫글자를 대문자를 필터를 어떻게 작성하는지 보자.
app.filter('capitalize', function() {
return function(input, param) {
return input.substring(0,1).toUpperCase()+input.substring(1);
}
});
필터는 인풋(인터폴레이션의 결과값이다.)과 필터 파라미터를 받는 함수를 반환하고 반환된 함수는 새로운 인풋을 반환한다. 이 예제에서는 인풋의 첫글자를 대문자로 바꿨다. 이제 이 필터를 사용해 보자.
<span>{{ "this is some text" | capitalize }}</span>
문자열을 문자열 리터럴로 만들기 위해 대문자로 감싼 뒤 capitalize
필터를 "파이프"로 연결하면 동작한다.
서비스
이 글의 마지막 부분인 서비스다. 서비스는 무엇일까? 서비스는 어플리케이션의 어떤 기능을 제공하는 싱글톤 클래스다. 어플리케이션 로직을 컨트롤러에 분산시키는 대신 다른 서비스에 로직을 둘 수 있다.
Angular에는 HTTP 요청을 관리하는 $http
나 프로미스(Promise)에 대한 $q
와 같은 많은 내장 서비스가 있다. 하지만 내장 서비스는 설명하기가 더 어렵기 때문에 다른 글에서 설명하기로 하고 여기서는 내장 서비스는 따로 설명하지 않을 것이다. 대신 간단한 서비스를 생성해 보자.
서비스를 사용하는 가장 일반적인 경우는 컨트롤러간에 정보를 공유해야하는 경우이다. 모든 컨트롤러는 자신만의 스코프를 가지므로 다른 컨트롤러의 스코프를 바인딩할 수 없다. 이 문제를 해결하기 위해 서비스를 사용하면 한 곳에서 데이터를 가지고 있고 필요한 어디서나 이 데이터를 사용하도록 할 수 있다. 우선 문제의 상황을 보기 위해 서비스가 없는 다음 예제를 살펴보자.
<!-- index.html -->
<div ng-controller="MainCtrl">
MainCtrl:
<input type="text" ng-model="user.name">
</div>
<div ng-controller="SecondCtrl">
SecondCtrl:
<input type="text" ng-model="user.name">
</div>
// controllers.js
app.controller('MainCtrl', function($scope) {
});
app.controller('SecondCtrl', function($scope) {
});
인풋을 같은 모델에 바인딩했으므로 인풋에 글을 쓰면 다른 쪽에도 업데이트 되기를 기대할 것이다. 즉, 다음과 같은 형태를 기대한 것이다.
하지만 이런 형태가 되는 것이 아니라 다음과 같이 된다.
이 문제를 해결하기 위해 두 컨트롤러에서 사용할 수 있도록 사용자 이름을 가진 서비스를 생성할 것이다.
// user_information.js
app.factory('UserInformation', function() {
var user = {
name: "Angular.js"
};
return user;
});
서비스를 생성하기 위해 app
모듈의 factory
함수를 사용했다. 서비스를 생성하는 좀더 고급적인 방법도 있다.(service
와 provider
함수를 사용하지만 이는 다른 글에서 설명하겠다.) 서비스를 생성하는 여러가지 방법이 있지만 이 예제에서는 미리 정의해 놓은 이름으로 private 사용자 객체를 생성해서 반환했다. 이 서비스는 컨트롤러에서 다음과 같이 사용한다.
// controllers.js
app.controller('MainCtrl', function($scope, UserInformation) {
$scope.user = UserInformation;
});
app.controller('SecondCtrl', function($scope, UserInformation) {
$scope.user = UserInformation;
});
이 예제는 다음과 같이 된다.
이 예제는 의도대로 잘 동작한다. MainCtrl
와 SecondCtrl
양쪽의 $scope.user
는 UserInformation
를 사용하고 서비스가 싱글톤이기 때문에 한 컨트롤러에서 UserInformation
의 값을 바꾸면 다른 쪽에서도 바뀐다.
여기서 UserInformation
파라미터가 어디서 왔는지 궁금할 것이다. Angular는 서비스를 필요로 하는 곳에 서비스를 주입하는 의존성 주입을 사용한다. 의존성 주입이 동작하는 방식을 설명하는 것은 이 글의 주제를 벗어나지만 간단히 말하자면 서비스를 생성하면 어느 컨트롤러나 디렉티브, 다른 서비스에도 이 서비스를 주입할 수 있다. 주입하는 방법은 그냥 파라미터에 서비스의 이름을 전달하면 된다. 아마 이 의존성 주입이 $scope
파라미터를 사용한 것과 같은 것인지 궁금할텐데 $scope
는 다른 컨트롤러에 주입되기는 하지만 실제로 서비스는 아닌 예외사항 중 하나이다.
결론
이 글이 Angular Tips 블로그의 첫번째 글이다.(마지막은 아니다. ^^) Angular.js는 뛰어난 프레임워크이고 아마도 이미 그 매력을 느꼈을 것이다. 이 글이 도움이 되었기를 바란다.
덧) 참고삼아 얘기하면 예제는 Angular.js 앱으로 동작하기 위해서 body태그에 ng-app속성과 컨트롤러를 위한 속성등이 들어가 있다. 이런 부분까지 보려면 JSFiddle에 예제에서 소스보기를 해서 봐야할 것이다.
정말 좋은 소개글 이군요. 감사합니다.
예제를 이해하기 쉽게 잘 만들어놨더라구요.
좋은글 잘 봤습니다~~
감사합니다. ㅎ
Outsider 블로그는 왜 좋은가? 라는 글도 나와야 할 판 ㅋ.
이번에도 좋은글 잘 읽었습니다 :)
하하하하 재밌네요.. ㅋ
감사합니다. 글 너무너무 잘 봤습니다.
예전에 data binding 을 javascript로
구현하려고 낑낑 댓던 적이 있었는데 이젠 lib가 나왔군요..
근데 이렇게 글 내용을 번역하고
예제도 넣어서 포스팅 작성하는데 순수 소요시간은 얼마나 걸리나요?
이번 같은 경우는 글도 길고 번역하고 글도 좀 다듬고 하다보니 꽤 시간이 걸렸습니다. 시간을 재보지는 않았지만 10시간정도 투자되지 않았을까 싶네요..
그렇군요. 역시 만만치 않군요.
오랜 시간 작업해서 이렇게 좋은 글 올려 주신 것 다시금 감사드려요.
좋은 글 감사합니다. 많은 도움이 되었습니다.
도움되셨다니 다행입니다 ^^
이제야 backbone.js + marionette.js 에 조금 익숙해져 가는데...
다시 이것도 공부해야겠네요 ㅠㅠ..
좋은글 감사합니다 ^^;;
오~ 백본은 안써봤긴 한데.. 마리오넷트라는건 처음 알았네요.
AngularJS에 대해 좋은 글 읽고 갑니다.
감사합니다 :)
네 방문해 주셔서 감사합니다.
정말 많은 도움 되었습니다. Angular.js 참 매력적인 프레임워크네요ㅎㅎ
네 요즘 angular에 푹 빠져있네요. ㅎ
AngularJS 에서 필요한 부분만 포스팅하셨네요
directive 에 대해서 쉽게 이해했어요
knockout 이랑 angular 랑 고민하다가 angluar로 갔네요
앞으로도 좋은 글 부탁 드립니다.
저도 knockout때는 많이 관심안가지고 있었는데 angular는 열심히 파보고 있네요.
Thanks for great post! Helped me a lot
AngularJs is definitely attractive framework
이번 새 프로젝트에 AngularJS 을 사용해볼까 고심하고 있던차에 이런 멋진 포스팅을 찾았네요. 좋은 글 감사합니다!
감사합니다. 외국에 계신것 같은데 원문이나 영어로는 다른 좋은 자료도 많은데요. ^^;;
좋은 글 잘 보았습니다.
궁금한 것이 있는데.. 개발쪽으로 보면 좋은거 같은데..
디자이너들이 볼때 괜찮은지 궁금합니다..
html 코드에 익숙해서 디자인 붙인다고 영망으로 하거나 할거 같다는 생각이 들어서요..
열심히 페이지 구성하고, 디자인쪽엣 못하겠다거나.. 수정시 힘들어 하지 않을까 하는 걱정이 되는데..
제대로 디자인을 하면서 퍼블리셔나 디자이너가 이것을 같이 배워야 하겠죠?
궁금해서 여쭤봅니다..
angular의 구조상 HTML에 다양한 코드가 들어가야 하는 문제는 있습니다.
이건 회사의 프로세스마다 다를것 같기는 하지만 디자인이나 마크업을 작성하는 쪽의 코드를 그대로 개발에서 사용하는 경우는 여태껏 보지 못했습니다. 간단한 자바스크립트 코드 때문에라도 추가적인 class를 추가하거나 서버의 뷰탬플릿엔진을 적용하기 위해서라도 angular같은 뷰탬플릿엔진의 코드나 레이아웃용으로 코드를 분리하게 됩니다.
그래서 보통은 마크업쪽의 코드 수정을 추적해서 서버나 프론트작업에서 계속 변경해 주어야 하기 때문에 angular를 적용한다고 딱히 문제가 될지는 모르겠고 퍼블리셔나 디자이너가 직접보고 수정할일도 그렇게 많지는 않아보입니다.
정말 잘 만들어주셨습니다.
감사합니다.
네 원문이 워낙 잘된 설명이라서요. ㅎ
안녕하세요.
아웃사이더님 글은 구글검색을 통해 가끔 보는데,
항상 심도있는 글 작성해주셔서 감사합니다.
근데 질문이 있는데요..
위의 앙골라JS HTML의 태그 중에 ng-*로 시작되는 속성이 있는데..
이는 hmtl5의 표준에 없는 거 같던데.. 이는 어찌된 건지요?
그리고 위 글에 예로 드신 pie-chart 태그 또한 html5 엔 없는거 같던데...
혹시 앙골라JS에서 내부적으로 한번 컴파일을 하여 순수 html로 변경하는
것인지도 궁금하네요.
만약 이렇다면 일반 html 에디터를 통해 작성을 할 경우 해당 라인에
경고 메시지가 뜰텐데.. 좀 신경이 쓰일거 같기도 하네요..
감사합니다.
이는 HTML하고도 관련이 있는데 HTML 렌더링 엔진은 보통 그리 엄격하지 않기 때문에 표준에 없는 태그를 작성해서 문제가 생기지는 않습니다. 다만 모르는 속성이나 태그는 그냥 무시할 뿐이죠.
위 글에 나온대로 Angular에서는 이를 디렉티브라고 부르는데 이러한 커스텀 속성이나 태그를 그냥 이용한 것입니다. 디렉티브 동작방식을 간단히만 설명드리면 Angular가 DOM을 파싱해서 필요한 디렉티브와 관련된 태그나 속성을 찾고 해당 디렉티브를 실행하는 방식입니다. 디렉티브내에서는 필요한 DOM을 생성해서 DOM에 추가하거나 자바스크립트를 실행하거나 하는 다양한 동작을 할 수 있습니다.
이러한 커스텀 속성이나 태그는 HTML 표준이 아니므로 말씀하신대로 에디터에서 오류로 표시되거나 유효성 검사에서 오류로 나옵니다. 이 부분이 신경쓰이신다면 에디터 설정에 추가해 줄수도 있지만 HTML5에는 이러한 커스텀 속성을 위한 data-* 라는 속성이 있습니다. 그래서 ng-app이 싫다면 data-ng-app이라고 쓸수 있고 이는 HTML5 표준에 들어가게 됩니다. 그리고 디렉티브는 정의할 때 태그/속성/주석/클래스 를 지원하게 만들 수 있으므로(디렉티브마다 다릅니다.) 말씀하신 부분을 해결하려면 data-* 형식으로 쓰거나 주석이나 클래스를 이용해서 사용하면 됩니다. (data-* 방식은 속성일때 angular가 자동으로 인식합니다.)
감사합니다. 쉽게 풀어주셔서 감사합니다. 정말 감사합니다. ㅠ ㅠ
네 원 글이 예제랑 잘 묶여서있어서 이해하기 쉽죠.. ㅎ
와우.... 정말 흥미롭네요.
한번 봐야지 봐야지 하면서 차일피일 미루다가 오늘 이 글을 정독해보니..
angular.js ...
정말 매력있네요.
러닝커브는 좀 있지만 매력적인 프레임워크임에는 틀림없어보입니다.
너무나도 훌륭하네요.
개념잡기 힘들었는데.. 정말 감사합니다
네 저도 처음에 도움이 많이 된 내용이죠.
좋은 내용을 잘보고 갑니다 ^^
네.. ㅎㅎ
정말 잘보고 갑니다.
네네 댓글 감사합니다.
Angular.js 를 해보고 싶게 만드네요. 좋은 글, 좋은 번역 고맙습니다.
제 글도 이렇게 쓰고싶네요 ㅎㅎㅎ
구글링을 통해 포스팅 읽게 됐습니다. 원전도 좋았겠지만 깔끔하고 명료한 번역도 돗보였던 것 같습니다. Bootstrap 시작했다가 Angular.js 도 보게 되는군요. 자주 들르게 될 것 같습니다. 고맙습니다.
Angular.js 글 쓰려다가 너무 좋아서 그냥 번역을 해버렸네요. 블로그에서 자주 뵙겠습니다. ^^
Angular.js를 공부하기 위해 책을사서 보고있었는데, 어려워서 다소 막막하다고 생각했습니다. 정말 쉽고 간단하게 정리해주신 덕분에 큰 도움이 됬습니다. 정말 감사합니다!
많은 분들이 좋아해 주셔서 이글을 번역하길 잘했다는 생각이 드네요. ㅎㅎ
Angular.js 개념 잡는데 너무 큰 도움 주신듯하네요. 감사합니다. 글 너무 잘 봤습니다.
네 댓글 감사합니다 ^^
와 정말 감사합니다.
잘 보고 갑니다.
관심있어서 자주 들어와서 참고합니다. 감사합니다.
음 제가 좀 부족해서 이 글을 읽고 왜 써야하는지 와닿지가 않아서요.
기존 mvc패턴에서 뷰부분을 개발할때 jquery나 js로 충분히 할수있는건데, angular js를 써서 더 좋은점이 뭔지 알고싶습니다.
번역글이라 제목을 제가 적은게 아니라.. ;
각 프레임워크의 특성이 있으니 개개인의 취향이나 프로젝트 성격에 따라 모두에게 장점으로 받아들려지진 않을 수 있습니다. 저도 앙굴라를 좋아하지만 모든 프로젝트에서 쓰는 것은 아닌데 단순히 폼 유효성체크만 해도 jQuery나 JS로도 다 작성할 수 있지만 angular를 쓰면 훨씬 적은코드로 작성할 수 있고 폼 유효성체크는 중요한 로직은 아니면서도 잘 만들려면 시간은 많이 드는 작업이기도 하죠.
물론 이런 부분은 소소한 부분이지만 예시일뿐이고 적용하기 주로 좋은 부분은 SPA(싱글 페이지 어플리케이션)을 만들때라고 생각합니다. 이렇게 작업하면 JS만으로는 코드가 너무 비대해져서 관리가 쉽지 않아집니다.
angular의 어느 부분이 매력적인가 했는데
데이터 바인딩 저 부분 상당히 좋네요.
한번 이제 angular 혼자 해봐야겟어요~
장단점이 꽤 있긴 하지만 양방향 바인딩으로 편해지는 부분이 꽤 있습니다. ㅎ
막상 실무에서 사용하려고 뒤적뒤적해봐도 다들 개념 설명하느라 뺑뺑 돌아서 설명하는데 이건 이해하기 쉽네요
잘보고 갑니다!
이 이후에도 알아야 할 내용이 많지만 초기에 개념잡기에 정리가 잘 되어 있는 글이죠.
너무 감사하네요...정말 너무감사합니다. ㅎㅎ
angularjs를 왜쓰는지 잘 이해가 됐네요 감사합니다 ㅎㅎ
지나가면서 맨날그냥보고갔는데 정말 보고 이해가 너무너무x100
잘되는것같아서 글까지남기고갑니다 잘보고갑니다!!
혹시 서비스에대해서 따로 중점적으로 리뷰하시면 정말 좋을것같습니다!
ps reCAPTCHA 시스템이 엄청나군요! 숫자를입력하지않아도된다니!
이 글은 원글이 너무 정리가 잘 되어 있어서 저는 업혀가는 글이 되었네요.
서비스라고 하신 건 angular.service 얘기신가요? angular로 서비스를 만드는 걸 얘기하시는 건가요?
ps. reCAPTCHA는 정말 볼 때마다 놀랍네요. 저도 처음 설치하고는 시크릿창 열어서 여러가지로 테스트해봤네요. ㅎ
음...여긴 다른 세상에 사는 사람들만 모인곳이네...
한국 개발자가 아닌가벼..
내 주위에는 document.write / window.open 이런것만 알고 있는데...
새로운 프로젝트가 앵귤러프로젝트인데
훌륭한 글이네요. 도움받고 갑니다.
잘 보고 갑니다
네 ^^
정말 좋은 글 잘 봤습니다~!!!!!!!!!!
이해가 ㄷㄷㄷㄷㄷㄷㄷ
감사합니다ㅎㅎ
네 ^^
관련 내용 검색하다 보게되었는데요,. 참고를 좀 해봐야 겠네요~
네 참고로 이제 angular2가 나올때쯤 되어서 지금 새로 공부하시기에 타이밍이 좀 애매하긴 합니다.
잘보고 가요. 개념잡기에 좋은글이네요 책으로 써도 되겠어요.
네 감사합니다. 근데 제 글은 아니고 번역글이라서요 ㅎㅎ
다른 각도로 함 보시기 바랍니다
이건 일반적인 HTML을 wrapping 한 겁니다.
dynamic tag 를 사용한것이죠.
이게 과연 좋기만 한것인지는 의문이네요.
이걸 공부하는 사람은 기본 HTML은 제대로 알지도 못하면서
Angular 만 알게 됩니다.
이걸로만 공부한 사람은 기본적인 web을 이해하지 못하게 된다는거죠.
제가 보기에 Angular 는 무엇보다도
기존 웹개발시 분업화 되어 있던 부분
디자인, 퍼블리싱, 개발을 1개의 프레임으로 해결할려고 하는 걸로
보입니다.
그리고 죄송한 말씀이지만 ANgular을 사용하지 않을떄와
사용했을떄의 코드 량은 오히려 Angular 가 배이상 많아집니다
물론 AA가 클라이언트 프로토타입을 얼마나 잘 잡았냐에 따라
달라지긴 하겠지만요.
무슨 의도의 말씀인지는 이해하지만 완전히 동의하기는 어렵습니다.
Angular로 공부하면 HTML을 알지 못한다는 것은 추상화된 어떤 라이브러리나 프레임워크에서는 항상 발생하는 문제고 jQuery 시대에도 항상 나오던 얘기였습니다. 이건 추상화된 프레임워크의 문제가 아니라 개발자의 태도에 달려있다고 생각하고 그게 걱정되서 추상화를 안할수는 없습니다.(물론 추상화가 항상 옳다는 것은 아닙니다.)
죄송할 필요는 없지만 Angular를 써야할 정도의 복잡한 어플리케이션이라면 Angular의 코드가 배이상 많아진다는 것은 동의하기 어렵습니다. angular 라이브러리의 사이즈가 있기는 하지만 폼에 인풋 10개있는 페이지의 유효성검사 로직만 작성해도 아마 angular가 반이상 적은 코드로 작성할 수 있을거라고 봅니다.
이건 필요성에 맞게 기술을 쓰냐 안쓰냐에 문제에 가깝지 Angular에 대한 비판은 되지 않는다고 생각합니다. 지금은 이미 Angular 1은 지고 2로 넘어가는 상황이지만요.
그리고 저는 이전처럼 디자인나오면 HTML로 만들고 이를 받아서 js 로직 붙이는 식으로 작업하던 시대는 이미 지났다고 생각합니다. 요즘 만드는 애플리케이션은 이 단계들이 훨씬 긴밀하게 붙어서 작업하는 경우가 많아졌다고 봅니다. 프론트앤드 개발자가 이 모든 단계를 거의 커버해야 하고 서버도 알아야 하는 상황이죠.
혹시 쓰시는 이클립스테마 뭔가요 ㅎㅎ
되게 눈편하고좋아보이는데
이글에는 이클립스 테마가 없는데 어떤 걸 얘기하신느 건가요?
윗글 제 글 답글인데 오류가 나네요
여기에 대신 적습니다
전 지금 ANgular JS 로 프로젝트를 진행중입니다
전 25년차 프로그래머구요.
실제로 제가 해본결과
ANgular JS 를 사용하는 목적은 CRUD에 대한 간편화입니다 추상화와 Factory를 통한 재활용성의 활용이죠.
하지먄 전통적인 방식으로 하는경우
공통화만 제대로 한다면 ANgular JS 와 비교시
코드량은 반이하로 듭니다.
실제 같은 프로젝트(단일 프로그램이 아니라) 를 하면서 해본 결과입니다
실제 경험입니다
Angular JS 가 복작한 프레임에 적용하는것은 더더군다나 아닙니다
이미 Angular 2가 나와서 상황이 많이 달라진 상황이고 저도 지금은 Angular를 많이 쓰고 있진 않습니다. 이 글은 Angular.js를 소개하는 글을 적은것뿐이지 제가 어느쪽 입장을 딱 가지고 있지는 않습니다.
그럼에도 말씀하신 반대 이유는 잘 수긍이 되지 않습니다. angular가 모든 면에서 좋은 것은 당연히 아니지만 그렇다고 형편없다고 보진 않습니다. 저는 지금이라도 복잡한 UI를 가졌지만 성능은 아주 중요치 않은 내부도구나 어드민을 만든다면 angular를 고려해 볼것 같습니다. 단순히 잘 작성하면 OO보다 더 적은 코드로 작성할 수 있다만으로는 어떤 부분이 문제인지 잘 모르겠습니다. 이런 비교는 비단 angular가 아니더라도 어떤 프레임워크에도 가능한 표현이라고 생각합니다.
좀 늦었네요 저도 angular js 로 작업중입니다. 일종의 알바죠 ^^
outsider 님의 마지막 글에 충분히 공감합니다.
말씀하신대로 각각의 장점이 다 있죠.
저도 angular js 가 아주 나쁘다 이렇게 말씀드린건 아닙니다
다만 제 필력이 부족하야....
Outsider 님 말씀처럼 angular js도 장점과 단점이 있으니 그 장단점을 잘 파악하여
씀이 좋을거 같다라는 취지인데 님 말씀처럼요.
다만 윗글에서 보면 angular js에 대한 장점만 주구장창 나열하심에
조금 반발심이 있었던 것이 사실입니다.
그리고 멸가지 사실들중에 outsider 님이 말씀하신 내용에 반하는 것이
있어 예를 들어 코드량이 줄어든다든지 하는 부분이요.
이런 부분은 제가 직접 angular js 를 써보니 전혀 그렇지 않더라는
것을 경험하였기에 그런 부분을 적어드린겁니다.
대체로 큰틀에서 님이 말씀하신대로 각각의 장단점을 살려
적절한 프레임을 사용함에 대해서는 적극적으로 동의합니다.
그럼..............
실제로 제가 작성하고 있는 프레임웍에 angular js의 추상화 개념을 적용중입니다.
그리고 필요없는 부분은 과감히 도려내고 있습니다.
jquery의 selector 부분의 장점을 취하는것처럼요.
모 말씀하신 validation 부분 같은 경우에도
클라이언트 validation 과 서버 validation 등을 공통 코드화 하여
사용하고 있기 때문에 그리고 프레임단에서 공통부분을 처리하기 떄문에
실제 개발자가 해야 할 코딩량은 많지 않습니다.
제가 실제 코딩량이라고 하는 것은
프레임 라이브러리를 포함한겁니다.
그럼.....
네 그런 부분은 이 글은 번역글이기도 하고 벌써 몇년 된 글이지만 Angular를 지지하는 글이라는 걸 감안하고 보셨으면 합니다. 모든 기술에는 장단점이 있지만 또 글에서 장단점을 다 적으면 아무 색이 없는 글이 되기는 하죠. 반대글은 또 다른 글에서 반박이 될테고요 ^^
요즘 angular공부중에 있는데 다시 한 번더 머릿속에 새기고 갑니다.
감사합니다.
앵귤러에 관심이 생겨서 여기저기 보다가 여기까지 오게되었는데
정말 큰 도움이 되었습니다! 감사합니다!!
Angular JS 가 어떤것 인지 아주 잘 설명이 되어있어 보기 너무 편했네요 감사합니다!!
angular js 처음 하는데... 개념 이해하는데, 도움이 많이 됐습니다.
지금은 Angular.js 1의 시대가 아니지만... 도움되셔서 다행입니다.