Backbone.js

Development/JavaScript 2013. 10. 13. 23:09


Backbone.js 시작하기 – 1. Backbone이 무엇인가요?

Backbone이 무엇인가요?

Backbone.js은 클라이언트 사이드 웹애플리케이션 개발에 MVC패턴 적용을 가능하게 해주는 자바스크립트 프레임워크들 중 하나입니다. 참고로 이런 자바스크립트 MVC패턴 프레임워크에는 다음과 같은 것들이 있습니다.

저는 위의 프레임워크들은 사용해 본적이 없어서 지금 이 글에서 소개해드리려는 Backbone.js와 비교를 하기는 어렵지만, Backbone.js의 특징과 장점에 대해서 말씀을 드리겠습니다.

Backbone.js를 사용하면 MVC패턴에 맞게 개발을 할 수 있습니다. 즉, M(model, 데이터), V(view, UI), C(controller, 로직, 데이터 처리)로 코드의 역할을 나눠서 작성하고 관리할 수 있게 해줍니다. 프로그램의 구조를 체계화 할 수 있게 됩니다. Backbone.js로 개발을 할 때 다음과 같은 틀에 맞춰 코드를 작성하게 됩니다.

  • Models – MVC에서의 model입니다. 개별 데이터를 나타냅니다.
  • Collections – model의 집합입니다. view와 연결되어, model에 변화가 생길 때 손쉽게 view(UI)를 갱신할 수 있습니다.
  • Routers – MVC에서의 controller 입니다. location.hash의 변경에 따른 처리를 담당합니다.
  • Views – MVC에서의 view입니다. 화면에 나타나는 UI를 담당하며 프론트엔드의 특성상 view가 controller 의 성격도 가지고 있습니다.
[참고] Backbone.js + Require.js 공부 참고 사이트

왜 Backbone을 사용하나요?

Backbone.js는 편리한 기능을 많이 가지고 있습니다. Collection과 View가 연동되어 데이터에 변화가 생길때 화면 UI를 갱신해주는 일을 편리하게 할 수 있습니다. 그리고 Router가 location.hash 변경에 따른 View의 갱신을 처리하는데 이는 Single Page Application의 개발을 대단히 용이하게 해줍니다.

Single Page Application은 하나의 html 파일로된 애플리케이션을 의미한다고 생각하시면 됩니다. 기본적으로 html 파일하나가 하나의 view를 의미했었지만 location.hash(url에서 # 이후에 나오는 것)를 사용하면 하나의 html파일에서도 즐겨찾기가 가능하도록 url을 변경해가면서 다양한 view를 보여줄 수 있습니다. 다른 view를 보여줄 때 html파일이 바뀌지 않으므로 화면갱신(refresh)가 발생하지 않아 사용자 UX 에서의 장점이 있습니다. 트위터 등이 현재 그렇게 되어 있습니다.

Backbone.js는 서버사이드와의 연동관련 기능도 있어서 데이터의 CRUD(저장, 조회, 갱신, 삭제)를 편리하게 구현할 수 있습니다. 그리고 Backbone.js는 Underscore.js라는 유틸리티 라이브러리에 의존성이 있어서, Backbone.js를 사용하려면 Underscore.js를 꼭 같이 사용해야 하는데, 이 underscore에도 유용한 기능들이 많이 있습니다.

그리고 jQuery와 함께 사용할 수 있습니다. 기존에 jQuery를 사용하시던 분들도 Backbone.js를 함께 사용하시는데에 아무 문제가 없습니다. jQuery를 사용해서 구현한 코드들을 그대로 가지고 가시고, 프로그램의 구조만 Backbone에 맞게 구성하시면 됩니다. Backbone의 View를 구현할 때 jQuery 셀렉터를 바로 사용할 수 있도록 되어 있어서 편리합니다.

참고로, 자바스크립트 개발에서 MVC패턴을 사용하면 좋은 점은 client-side MVC architecture options 잘 나와 있습니다. Backbone의 장점과 특징은 Getting Started with Backbone.js이나 Why do you need Backbone.js?을 읽어보시면 좋을 것 같습니다.

지금까지 Backbone.js에 대해서 간략한 소개를 드렸습니다. 다음부터는 실제 사용방법에 대해서 말씀드리겠습니다.


출처 - http://codefactory.kr/2011/12/22/getting-started-with-backbonejs-1-what-is-backbone/





Backbone.js 시작하기 – 2. Model

Model

Backbone에서 model은 하나의 단일한 데이터 덩어리 – 객체 – 를 의미한다고 보시면 됩니다. DB에 넣을때 하나의 레코드가 될 수 있습니다. 개발될 애플리케이션의 모든 로직들은 이 model을 만들고, 수정하고, 삭제하면서 그에 따라 view를 표시해주고 서버의 DB를 갱신하는 형태가 될 것입니다.

Backbone에서 model은 Backbone.Model을 확장해서 만들 수 있습니다. 이때 Backbone.Model.extend 메서드를 사용합니다. 앞으로 만들 Collection, View, Router도 모두 비슷한 형태로 만들어집니다.

[참고] 이제 본격적인 코딩에 들어가게되는데요, 먼저 Backbone.js의 공식사이트에 가서 최신 버전을 다운로드 받으십시오. 그리고 Backbone은 underscore.js라는 라이브러리에 의존성이 있습니다. 즉, HTML에 underscore.js를 먼저 포함시키고 그다음에 backbone.js를 넣어야 backbone을 사용할 수 있습니다. underscore.js는 여기에서 다운로드 받으십시오

생성하기

  1. var Photo = Backbone.Model.extend({});

일단 위와 같이 간단하게 model을 만들 수가 있습니다. 이렇게 만들어진 Photo는 model의 생성자 함수입니다. 실제로 사용할 model은 Photo의 인스턴스입니다.

  1. var myPhoto = new Photo;

이제 myPhoto는 Backbone에서의 model이 되었습니다. 가장 간단한 형태로 만들어봤는데요, 이제 model을 만들 때 Backbone.Model.extend에 사용할 수 있는 다양한 프로퍼티를 넣어가면서 Photo를 다시 만들어 보겠습니다.

  1. var Photo = Backbone.Model.extend({
  2. initialize: function () {
  3. console.log('model이 생성되었습니다.');
  4. }
  5. });
  6.  
  7. var myPhoto = new Photo;
  8. // 'model이 생성되었습니다.'

initialize에는 model이 생성된 후 실행될 콜백함수를 넣을 수 있습니다.

  1. var Photo = Backbone.Model.extend({
  2. defaults: {
  3. src: 'photo.jpg',
  4. title: 'photo 입니다.'
  5. }
  6. });
  7.  
  8. var myPhoto = new Photo;
  9. myPhoto.get('src'); // 'photo.jpg'
  10. myPhoto.get('title'); // 'photo 입니다.'

Getter, Setter

defaults에는 만들어질 model attribute들의 기본값을 설정할 수 있습니다. model에는 get메서드가 있어서 attribute의 값을 얻어올 수 있습니다. 그리고 아래의 코드처럼 model을 생성할 때 생성자 함수에 attribute 값들을 넘겨주면 기본값이 아닌 값을 설정해서 model을 만들 수 있습니다.

  1. var Photo = Backbone.Model.extend({
  2. defaults: {
  3. src: 'photo.jpg',
  4. title: 'photo 입니다.'
  5. }
  6. });
  7.  
  8. var myPhoto = new Photo({src: 'new_photo.jpg', title: '새로운 title', size: [480, 800]});
  9. myPhoto.get('src'); // 'new_photo.jpg'
  10. myPhoto.get('title'); // '새로운 title'
  11. myPhoto.get('size'); // [480, 800]

그리고 위의 size attribute처럼, defaults에 지정하지 않았던 attribute도 자유롭게 추가할 수 있습니다. model의 set 메서드를 사용하면 이미 만들어진 model에 attribute를 새로 추가하거나 값을 변경할 수 있습니다.

  1. var Photo = Backbone.Model.extend({
  2. defaults: {
  3. src: 'photo.jpg',
  4. title: 'photo 입니다.'
  5. }
  6. });
  7.  
  8. var myPhoto = new Photo({src: 'new_photo.jpg', title: '새로운 title', size: [480, 800]});
  9. myPhoto.set({newAttr: '새로운 attribute'});
  10. myPhoto.get('newAttr'); // '새로운 attribute'

이벤트

그리고 이건 진짜 신기한 기능인데, model이 변경되면 이벤트가 발생합니다. 이 이벤트에 리스너를 등록해놓으면, model이 변경될 때 작업을 수행할 수 있습니다. initialize안에 이벤트 리스너를 등록해 놓겠습니다.

  1. var Photo = Backbone.Model.extend({
  2. initialize: function () {
  3. this.bind('change:src', function () {
  4. console.log('src가 ' + this.get('src') + '로 변경되었습니다.');
  5. });
  6. }
  7. });
  8.  
  9. var myPhoto = new Photo;
  10. myPhoto.set({src: 'new_photo.jpg'}); // src가 new_photo.jpg로 변경되었습니다.

initialize 안에서 this.bind 를 사용해서 change 이벤트에 리스너를 등록했습니다. 이벤트 등록하는 코드의 패턴이 jQuery와 많이 유사하기 때문에 jQuery 사용자라면 이런 방식이 익숙하실 것입니다. ‘change:src’는 src attribute가 변경되었을 때 이 콜백을 실행하라는 의미입니다. 만약 ‘change’라고 한다면 src뿐 아니라 어떤 attribute가 변경될 때도 실행이 됩니다. 그리고 이벤트 리스너 안에서 this 키워드로 model에 접근할 수 있습니다. 그래서 this.get(‘src’)를 사용하면 변경된(변경 이후에 콜백이 실행되므로) 새로운 src attribute 값을 얻어올 수 있습니다.

커스텀 메서드 추가

그리고 지금까지 Backbone.Model.extend안에서 보여드렸던 defaults, initialize 등은 Backbone에서 기본 제공하는 것들인데, 이것 외에도 자유롭게 프로퍼티, 메서드를 추가해서 사용하실 수 있습니다.

  1. var Photo = Backbone.Model.extend({
  2. initialize: function () {
  3. this.bind('change:src', function () {
  4. console.log('src가 ' + this.get('src') + '로 변경되었습니다.');
  5. });
  6. },
  7. setTitle: function (newTitle) {
  8. this.set({title: newTitle});
  9. }
  10. });
  11.  
  12. var myPhoto = new Photo;
  13. myPhoto.setTitle('새로운 title');
  14. myPhoto.get('title'); // '새로운 title'

setTitle이라는 메서드를 새로 추가해봤습니다. setTitle 처럼 새로 추가한 메서드의 안에서도 this 키워드로 model에 접근할 수 있습니다. setTitle 메서드는 인자로 새로운 title을 받아 model의 title attribute의 값을 수정하고 있습니다.

Validate

그리고 validate 기능에 대해 알아보겠습니다. 지금까지 model에 자유롭게 값을 설정해 왔는데 validate를 사용하면 값을 설정하기 전에 검사를 진행하고 통과하지 못하면 값이 설정안되도록 할 수 있습니다.

  1. var Photo = Backbone.Model.extend({
  2. validate: function (attributes) {
  3. if (attributes.src === 'photo.jpg') {
  4. alert('이 값은 사용하지 마세요');
  5. return true;
  6. }
  7. }
  8. });
  9.  
  10. var myPhoto = new Photo;
  11. myPhoto.set({src: 'photo.jpg'}); // validate를 통과하지 못해 값이 설정되지 않음
  12. myPhoto.get('src'); // undefined
  13. myPhoto.set({src: 'new_photo.jpg'});
  14. myPhoto.get('src'); // 'new_photo.jpg'

위에서 보시는 것처럼 validate를 만들어 놓으면 model의 src attribute에 ‘photo.jpg’가 설정되지 못하도록 막을 수 있습니다. validate에 등록해 놓은 함수에 return 값이 falsy value(false, undefined 등 false로 판단되는 값들)이 아니면 validate를 통과하고, 위의 true와 같은 truthy value(falsy value가 아닌 모든 값들, true, 문자열, 숫자 등)이 되면 validate를 통과하지 못해 model에 값이 설정되지 않습니다.

위의 코드에서 사용자에게 alert하는 코드를 validate 안에 넣었지만 다른 곳에서 처리할 수도 있습니다. validate를 통과하지 못할 때 ‘error’ 이벤트가 발생하기 때문에 ‘error’ 이벤트에 리스너를 등록해 놓으면 됩니다.

  1. var Photo = Backbone.Model.extend({
  2. validate: function (attributes) {
  3. if (attributes.src === 'photo.jpg') {
  4. return '이 값은 사용하지 마세요';
  5. }
  6. },
  7. initialize: function () {
  8. this.bind('error', function (model, error) {
  9. alert(error);
  10. });
  11. }
  12. });
  13.  
  14. var myPhoto = new Photo;
  15. myPhoto.set({src: 'photo.jpg'}); // validate를 통과하지 못해 값이 설정되지 않음
  16. myPhoto.get('src'); // undefined

initialize 안에서 이벤트 리스너를 등록했습니다. 콜백함수의 두번째 인자에서 validate가 return 했던 값을 받게 되어 있습니다. 여기에서 alert을 처리하도록 했습니다.

정리

지금까지 작성했던 코드를 모두 종합해서 Photo model을 만들어 보면 다음과 같습니다.

  1. var Photo = Backbone.Model.extend({
  2. validate: function (attributes) {
  3. if (attributes.src === 'photo.jpg') {
  4. return '이 값은 사용하지 마세요';
  5. }
  6. },
  7. defaults: {
  8. src: 'photo.jpg',
  9. title: 'photo 입니다.'
  10. },
  11. initialize: function () {
  12. console.log('model이 생성되었습니다.');
  13. this.bind('change:src', function () {
  14. console.log('src가 ' + this.get('src') + '로 변경되었습니다.');
  15. });
  16. this.bind('error', function (model, error) {
  17. alert(error);
  18. });
  19. },
  20. setTitle: function (newTitle) {
  21. this.set({title: newTitle});
  22. }
  23. });
  24.  
  25. var myPhoto = new Photo({src: 'new_photo.jpg', title: '새로운 title', size: [480, 800]});
[참고] 브라우저의 개발자 도구 콘솔에서 위에서 만든 myPhoto 변수를 확인해보십시오. 여러 프로퍼티들을 가지고 있는데 그중에서 attributes 프로퍼티를 보시면 src, title, size 프로퍼티가 보이실 것입니다. 즉, 위 코드에서 myPhoto.get() 으로 접근 가능했던 myPhoto의 attribute들은 get 메서드를 사용하지 않고 myPhoto.attributes.src, myPhoto.attributes.title, myPhoto.attributes.size 로도 접근이 가능합니다. 값을 변경할 때에도 myPhoto.set() 메서드를 사용하지 않고도, myPhoto.attributes.src = ‘photo.jpg’; 와 같은 형태로 직접 설정이 가능합니다. 그런데 이렇게 직접 설정할 경우 validate에 의한 검사는 이루어지지 않습니다.


출처 - http://codefactory.kr/2011/12/22/getting-started-with-backbonejs-2-model/






Backbone.js 시작하기 – 3. Collection

Collection

Collection은 model들을 모아 놓은 것입니다. 배열처럼 생각하실 수 있는데요, model들을 만들어 놓고 collection에 넣어서 사용할 수 있습니다. model을 설명드릴 때 model이 DB에서 레코드 하나와 비교될 수 있다고 말씀드렸는데요, collection은 DB 쿼리 결과로 받은 레코드들이라고 생각하실 수 있습니다.

하나의 model이 하나의 collection에 속할 수 있지만, 여러 collection에 속할 수도 있습니다.

http://backbonetutorials.com/what-is-a-collection를 보시면 아래와 같이 설명이 되고 있습니다.

  • Model: Student, Collection: ClassStudents
  • Model: Todo Item, Collection: Todo List
  • Model: Animals, Collection: Zoo

이렇게 할 수도 있고, 아래처럼 하나의 model이 여러 collection에 속할 수도 있습니다.

  • Model: Student, Collection: Gym Class
  • Model: Student, Collection: Art Class
  • Model: Student, Collection: English Class

이제 실제 코드를 작성해가면서 Collection에 대해 알아보겠습니다.

[참고] 이전 글에서 backbone.js를 사용하기 위해서는 먼저 underscore.js를 포함시키고 backbone.js를 넣어야 한다고 말씀드렸는데요, 오늘 살펴볼 예제중에는 jQuery에 의존성이 있는 .fetch() 메서드가 있습니다. 그래서 HTML파일에 backbone.js를 넣기 전에 jQuery도 포함시키고 예제를 실행해 주십시오

생성하기

collection은 model이 있어야 만들 수 있으니 먼저 model을 만들어 보겠습니다.

  1. var Book = Backbone.Model.extend({
  2. defaults: {
  3. sort: 'default',
  4. title: 'default Title'
  5. }
  6. });
  7.  
  8. var book1 = new Book({sort: 'JavaScript', title: 'JavaScript Book 1'}),
  9. book2 = new Book({sort: 'JavaScript', title: 'JavaScript Book 2'}),
  10. book3 = new Book({sort: 'JavaScript', title: 'JavaScript Book 3'});

book1, book2, book3 라는 model 세 개를 만들었습니다. 그러면 collection을 만들고 이 model 들을 넣겠습니다.

  1. var Book = Backbone.Model.extend({
  2. defaults: {
  3. sort: 'default',
  4. title: 'default Title'
  5. }
  6. });
  7.  
  8. var book1 = new Book({sort: 'JavaScript', title: 'JavaScript Book 1'}),
  9. book2 = new Book({sort: 'JavaScript', title: 'JavaScript Book 2'}),
  10. book3 = new Book({sort: 'JavaScript', title: 'JavaScript Book 3'});
  11. var Books = Backbone.Collection.extend({ // Books 라는 collection을 만듭니다.
  12. model: Book
  13. });
  14.  
  15. var books = new Books(); // books 라는 Books collection의 인스턴스를 만듭니다.
  16.  
  17. books.add([book1, book2, book3]); // add 메서드를 사용해서 model들을 books에 넣습니다.

model을 만들때와 유사한 방법으로 collection은 Backbone.Collection.extend 를 통해 만들 수 있습니다. 그리고 이때 이 collection이 참조할 model을 model 프로퍼티에 명시해줍니다. 이렇게 만든 collection으로 books라는 인스턴스를 만든 후 거기에 실제 model들을 넣어서 사용하면 됩니다. add 메서드에는 model들을 배열로 넣어주면 됩니다.

collection에서 model을 삭제하고 싶을때에는 remove 메서드를 사용하면 됩니다. books.remove([book1, book2, book3]); 이런 형태로 model들을 삭제할 수 있습니다.

[참고] 하나의 model만 add하거나 remove하고 싶을 때에는 배열을 사용하지 않고 books.add(book1); 또는 books.remove(book1); 하시면 됩니다. 그러나 두 개 이상의 model을 다룰 때에는 배열형태를 사용하셔야 합니다. books.add(book1, book2, book3); 은 제대로 작동하지 않습니다. (book1만 추가됩니다.)

model 참조

이렇게 collection에 model들을 넣어놓으면 model들이 collection의 models라는 프로퍼티에 배열형태로 있는 것을 보실 수 있습니다.

  1. books.models[0]; // book1
  2. books.models[1]; // book2
  3. books.models[2]; // book3

이와 유사한 방법으로 collection의 at 메서드를 사용할 수도 있습니다.

  1. books.at(0); // book1
  2. books.at(1); // book2
  3. books.at(2); // book3

이 방법 외에 collection에 있는 model에 접근하는 방법이 몇 가지 더 있습니다. 먼저, model에 id라는 attribute가 있다면 collection에서 get 메서드를 사용해서 model에 접근할 수 있습니다. 위의 예제코드에서 book1, book2, book3 model에는 id attribute가 없었으니, 지금 추가하고 테스트해보겠습니다.

  1. book1.set({id: 0});
  2. book2.set({id: 1});
  3. book3.set({id: 2}); // Book model들에 id attribute를 추가해줬습니다.
  4.  
  5. books.get(0); // book1
  6. books.get(1); // book2
  7. books.get(2); // book3

위의 코드처럼, collection의 get메서드는 id attribute르 model에 접근할 수 있게 해줍니다.

[참고] collection은 model을 참조하고 있습니다. 그래서 model을 collection에 넣은 후 나중에 model을 수정(id attribute 추가)해도 collection에 바로 반영되어 get() 을 사용할 수 있습니다.

getByCid 라는 메서드도 있습니다. 이전 글에서 model을 말씀드릴때 cid를 말씀 안드린것 같은데요, model을 생성하면 Backbone이 자동으로 cid라는 고유한 값을 가진 프로퍼티를 만들어줍니다. 그래서 book1.cid 값을 가져올 수 있습니다. cid는 ‘c0′, ‘c1′, ‘c2′ 이런 식으로 c와 숫자를 붙여서 안겹치게 자동 생성이 됩니다. 그래서 model의 cid를 알고 있다면 getByCid 메서드를 사용해서 다음과 같이 model을 가져올 수 도 있습니다.

  1. books.getByCid('c0'); // book1
  2. books.getByCid('c1'); // book2
  3. books.getByCid('c2'); // book3

지금까지 books collection을 만든 다음에 model을 추가하는 방법을 보여드렸는데요, 처음 만들때 model을 넣어서 만들 수도 있습니다.

  1. var Book = Backbone.Model.extend({
  2. defaults: {
  3. sort: 'default',
  4. title: 'default Title'
  5. }
  6. });
  7.  
  8. var book1 = new Book({sort: 'JavaScript', title: 'JavaScript Book 1'}),
  9. book2 = new Book({sort: 'JavaScript', title: 'JavaScript Book 2'}),
  10. book3 = new Book({sort: 'JavaScript', title: 'JavaScript Book 3'});
  11. var Books = Backbone.Collection.extend({ // Books 라는 collection을 만듭니다.
  12. model: Book
  13. });
  14.  
  15. var books = new Books([book1, book2, book3]); // books 라는 Books collection의 인스턴스를 만들면서 model도 넣어줍니다.

이제 collection을 만들었으니 이 collection이 어떤 기능들을 할 수 있는지 알아보겠습니다.

이벤트

model과 마찬가지로 collection도 이벤트 리스너를 등록할 수 있습니다. collection에 model이 추가되면 add 이벤트가 발생합니다. model과 마찬가지로 collection도 initialize 메서드에서 collection이 생성될 때 수행할 일을 넣을 수 있는데 여기에서 이벤트 리스너를 등록하겠습니다.

  1. var Book = Backbone.Model.extend({
  2. defaults: {
  3. sort: 'default',
  4. title: 'default Title'
  5. }
  6. });
  7.  
  8. var book1 = new Book({sort: 'JavaScript', title: 'JavaScript Book 1'});
  9. var Books = Backbone.Collection.extend({ // Books 라는 collection을 만듭니다.
  10. model: Book,
  11. initialize: function () {
  12. this.bind('add', function (book) { // add 이벤트는 model이 추가될 때 발생합니다.
  13. // 이벤트 리스너는 인자로 추가된 model을 받습니다.
  14. console.log('방금 ' + book.get('title') + '라는 제목을 가진 책이 추가되었습니다.');
  15. });
  16. }
  17. });
  18.  
  19. var books = new Books();
  20. books.add(book1); // '방금 JavaScript Book 1라는 제목을 가진 책이 추가되었습니다.'

books collection에 book1을 add하면 이벤트 리스너가 실행되고 이때 book.get(‘title’)로 방금 추가된 model의 title attribute을 가져올 수 있습니다.

model들의 attribute 변화에 대해 change 이벤트 리스너를 등록할 수 있습니다. model때와 마찬가지로 ‘change’는 모든 변경에서 이벤트 리스너가 실행되고 ‘change:title’ 과 같이 하면 title attribute가 변경될 때만 이벤트 리스너가 실행됩니다.

  1. var Books = Backbone.Collection.extend({
  2. model: Book,
  3. initialize: function () {
  4. this.bind('change:title', function (book) {
  5. console.log('방금 ' + book.get('title') + '으로 제목이 수정되었습니다.');
  6. });
  7. }
  8. });
  9.  
  10. var books = new Books();
  11. books.add(book1);
  12.  
  13. book1.set({title: 'test'}); // title을 수정하면 아래의 메시지가 console에 나옵니다.
  14. // '방금 test으로 제목이 수정되었습니다.'

정렬

comparator 메서드를 사용하여 collection의 model들을 정렬할 수 있습니다. 이렇게 하면 model들을 add한 순서에 상관없이 comparator에서 정한 규칙에 따라 model들이 자동으로 정렬됩니다.

  1. var Book = Backbone.Model.extend({
  2. defaults: {
  3. name: 'default',
  4. title: 'default Title'
  5. }
  6. });
  7.  
  8. var book1 = new Book({name: 'book1', title: 'Hello'}),
  9. book2 = new Book({name: 'book2', title: 'JavaScript'}),
  10. book3 = new Book({name: 'book3', title: 'Book'});
  11. var Books = Backbone.Collection.extend({
  12. model: Book,
  13. comparator: function (book) { // comparator 는 정렬을 해줍니다.
  14. // 인자로 model을 받게됩니다.
  15. return book.get('title').toLowerCase(); // return 값을 model의 title을 소문자로 바꾼 걸로 해줍니다.
  16. }
  17. });
  18.  
  19. var books = new Books();
  20. books.add([book1, book2, book3]);

comparator 메서드에서 어떤 값을 return 하느냐에 따라 정렬 규칙이 만들어집니다. 위 코드에서는 comparator가 model의 title을 return 하고 있습니다. 이렇게 하면 title의 알파벳 순으로 model 들이 자동 정렬됩니다.

  1. books.models[0]; // book3
  2. books.models[1]; // book1
  3. books.models[2]; // book2

그래서 title이 ‘Book’인 book3가 제일 먼저, ‘Hello’인 book1가 다음, ‘JavaScript’인 book2이 제일 끝으로 정렬이 됩니다. 만약, book model들이 order라는 attribute가 있고 거기에 값이 0,1,2등으로 들어가 있을 때 collection의 comparator에서 return book.get(‘order’); 이런 식으로 처리해줬으면 order 값이 작은 순으로 정렬이 되었을 것입니다.

fetch

collection에서는 fetch라는 신기한 메서드를 사용할 수 있습니다. 이 메서드를 사용하면 서버의 DB나 브라우저의 localStorage등에 저장된 데이터를 받아와서(그 데이터를 model로 삼아) 바로 collection에 추가해 줄 수 있습니다. 이때는 collection을 만들때 model 프로퍼티가 있어도 되고 없어도 됩니다. 대신 url 프로퍼티가 있어야 합니다. fetch() 메서드를 실행시키면 url 프로퍼티에 있는 url로 ajax request를 합니다. 그 결과 받아온 데이터들이 collection에 들어가는 것입니다. model은 자바스크립트의 객체이기 때문에, 서버에서 출력해주는 데이터의 형태는 JSON(객체의 배열)이어야 할 것입니다.

먼저, 다음과 같이 collection을 만들어 보겠습니다.

  1. var Books = Backbone.Collection.extend({
  2. url: 'test.php'
  3. });
  4.  
  5. var books = new Books();

test.php의 소스코드는 다음과 같습니다. 그냥 아무것도 안하고 JSON만 출력해주는 파일입니다.

  1. <?php
  2.  
  3. $item1 = array('name' => 'book1', 'title' => 'Hello');
  4. $item2 = array('name' => 'book2', 'title' => 'JavaScript');
  5. $item3 = array('name' => 'book3', 'title' => 'Book');
  6.  
  7. $arr = array($item1, $item2, $item3);
  8.  
  9. echo json_encode($arr);
  10.  
  11. ?>

그러면 이제 fetch() 메서드를 사용해보겠습니다.

  1. books.fetch(); // fetch 메서드가 url에 등록된 url로 ajax request를 해서 받아온 데이터들을
  2. // books collection에 model로 넣어줍니다.
  3. books.models[0]; // name: 'book1', title: 'Hello' attribute를 가지고 있는 Backbone Model 객체
  4. books.models[1]; // name: 'book2', title: 'JavaScript' attribute를 가지고 있는 Backbone Model 객체
  5. books.models[2]; // name: 'book3', title: 'Book' attribute를 가지고 있는 Backbone Model 객체

이렇게 fetch() 메서드를 사용하면 서버와 통신해서 간단하게 collection을 만들 수 있습니다. 이것은 Backbone으로 애플리케이션을 만들 때 서버에서 주는 데이터들을 Backbone의 Collection으로 만들어서 사용하면 된다는 것을 의미합니다. fetch() 메서드는 ajax request를 할 때 jQuery의 ajax 메서드를 사용합니다. 이 글의 처음 부분에서 오늘 살펴볼 예제는 jQuery를 포함시켜야 한다고 말씀드렸었는데요 바로 fetch() 메서드 부분에서 사용해서 그렇게 말씀드렸습니다.

fetch() 메서드에 인자로 jQuery에서 ajax를 할 때 사용했던 옵션들을 넘겨줄 수 있습니다. 먼저, 서버측의 test.php를 다음과 같이 바꿔보겠습니다.

  1. <?php
  2.  
  3. $item1 = array('sort' => $_GET['sort'], 'name' => 'book1', 'title' => 'Hello');
  4. $item2 = array('sort' => $_GET['sort'], 'name' => 'book2', 'title' => 'JavaScript');
  5. $item3 = array('sort' => $_GET['sort'], 'name' => 'book3', 'title' => 'Book');
  6.  
  7. $arr = array($item1, $item2, $item3);
  8.  
  9. echo json_encode($arr);
  10.  
  11. ?>

jQuery의 ajax가 기본적으로 GET 방식을 사용하듯, fetch() 메서드도 기본적으로 GET 방식으로 통신합니다. 그래서 test.php에서 GET으로 넘겨받은 데이터를 출력하도록 수정했습니다. 그러면 fetch() 메서드 부분도 아래와 같이 바꿔보도록 하겠습니다.

  1. var Books = Backbone.Collection.extend({
  2. url: 'test.php'
  3. });
  4.  
  5. var books = new Books();
  6.  
  7. books.fetch({
  8. data: {
  9. sort: 'JavaScript' // 요청할 때 sort라는 데이터를 넘김
  10. // test.php에서는 $_GET['sort'] 로 받음
  11. },
  12. success: function () {
  13. alert('success!'); // 요청 성공하면 'success!' alert 띄우기
  14. }
  15. });
  16. books.models[0]; // sort: 'JavaScript', name: 'book1', title: 'Hello' attribute를 가지고 있는 Backbone Model 객체
  17. books.models[1]; // sort: 'JavaScript', name: 'book2', title: 'JavaScript' attribute를 가지고 있는 Backbone Model 객체
  18. books.models[2]; // sort: 'JavaScript', name: 'book3', title: 'Book' attribute를 가지고 있는 Backbone Model 객체

위 코드에서는 fetch() 메서드에 jQuery ajax에서 사용햇던 data, success 등의 프로퍼티와 메서드를 인자로 넘겨서 호출했습니다. ajax request가 성공하고 ‘success!’라는 alert가 떴고, books collection의 model들에는 ‘JavaScript’라는 값을 가진 sort attribute가 등록되었습니다.

[참고] POST방식으로 ajax request를 하기위해 fetch()에 인자로 type: ‘POST’를 한뒤 test.php에서는 $_GET을 $_POST로 바꾸고 테스트해봤는데 정상적으로 동작하지 않았습니다. fetch() 에서는 GET 방식 request만 사용할 수 있는 것 같습니다. 혹시, POST를 사용할 수 있는 방법을 아시면 댓글을 달아주시면 감사하겠습니다.


출처 - http://codefactory.kr/2011/12/25/getting-started-with-backbonejs-3-collection/

















Posted by linuxism
,