Backbone.js 개발자가 저지르는 가장 흔한 8가지 실수
게시 됨: 2022-03-11Backbone.js는 구조화된 웹 애플리케이션의 프론트 엔드를 생성하는 데 사용할 수 있는 간단한 데이터 구조 및 기능 세트를 제공하는 것을 목표로 하는 최소한의 프레임워크입니다. 기본적으로 Backbone.js의 구성 요소는 백엔드에서 모델 및 보기로 작업할 때 이미 익숙할 수 있는 직관적인 환경을 제공합니다. Backbone.js의 모델 및 컬렉션은 단순하지만 REST JSON API와 쉽게 통합하는 옵션과 같은 몇 가지 매우 유용한 기능이 함께 제공됩니다. 그러나 그들은 또한 거의 모든 실제 사용에 적응할 수 있을 만큼 충분히 유연합니다.
이 Backbone.js 튜토리얼에서는 프리랜스 개발자가 Backbone.js를 처음 배울 때 자주 저지르는 몇 가지 일반적인 실수와 이를 피하는 방법을 살펴보겠습니다.
실수 #1: Backbone.js 기능의 무기고 무시
Backbone.js는 최소한의 프레임워크일 수 있지만 Underscore.js와 함께 최신 웹 애플리케이션을 개발할 때 발생하는 가장 기본적이고 중요한 요구 사항을 쉽게 다룰 수 있는 과다한 기능을 제공합니다. 초보자 개발자가 자주 범하는 한 가지 일반적인 실수는 Backbone.js를 웹용 MVC와 유사한 또 다른 클라이언트 프레임워크로 간주한다는 것입니다. 이 섹션에서 매우 분명한 것에 대해 이야기하지만 Backbone.js와 관련하여 프레임워크를 철저히 탐색하지 않는 것은 정말 중요한 실수입니다. 프레임워크는 크기가 작을 수 있지만 이것이 이 철저한 탐색을 위한 훌륭한 후보가 되는 이유입니다. 특히 작고 멋지게 주석이 달린 소스 코드.
Backbone.js는 웹 애플리케이션이 혜택을 받을 수 있는 구조를 제공하는 데 필요한 최소한의 기능을 제공합니다. 확장성과 과다한 플러그인을 통해 Backbone.js를 학습하면 몇 가지 놀라운 웹 애플리케이션을 구축할 수 있습니다. Backbone.js의 가장 명백한 기능 중 일부는 모델, 컬렉션 및 보기를 통해 노출됩니다. 라우터 및 기록 구성 요소는 클라이언트 측 라우팅을 지원하는 간단하면서도 우아한 메커니즘을 제공합니다. Underscore.js는 Backbone.js의 종속 항목이지만 모델과 컬렉션 모두 이 놀라운 JavaScript용 유틸리티 벨트의 이점을 많이 누리고 마음대로 사용할 수 있으므로 프레임워크에 매우 잘 통합되어 있습니다.
프레임워크의 소스 코드는 너무 잘 작성되고 주석이 달려 있어서 커피 한 잔을 마시면서 모두 읽을 수 있을 것입니다. 초보자는 프레임워크가 내부적으로 작동하는 방식에 대해 많은 것을 배울 수 있고 JavaScript와 관련하여 깔끔한 모범 사례 세트를 채택할 수 있기 때문에 소스 주석을 읽으면 많은 이점을 얻을 수 있습니다.
실수 #2: 임의의 이벤트에 대한 직접적인 응답으로 DOM 수정
Backbone.js를 처음 배울 때 하는 경향이 있는 것은 Backbone.js에서 권장하는 대로 하지 않는 것입니다. 예를 들어, 우리는 단순한 웹사이트에서 jQuery를 사용하는 방식으로 이벤트를 처리하고 업데이트를 보는 경향이 있습니다. Backbone.js는 적절한 분리를 통해 웹 애플리케이션에 견고한 구조를 제공하기 위한 것입니다. Backbone.js로 자주 하는 경향은 임의의 DOM 이벤트에 대한 응답으로 보기를 업데이트하는 것입니다.
var AudioPlayerControls = Backbone.View.extend({ events: { 'click .btn-play, .btn-pause': function(event) { $(event.target).toggleClass('btn-play btn-pause') } }, // ... })
이것은 어떤 대가를 치르더라도 피해야 하는 것입니다. 이것이 의미가 있을 수 있는 모호한 예를 생각해내는 것이 가능할 수도 있습니다. 그러나 대부분의 경우 훨씬 더 나은 방법이 있습니다. 사실, 여기에서 내가 예시할 수 있는 한 가지 방법은 모델을 사용하여 오디오 플레이어의 상태를 추적하고 해당 상태 정보를 사용하여 버튼(또는 더 구체적으로 클래스 이름)을 렌더링하는 것입니다.
var AudioPlayerControls = Backbone.View.extend({ events: { 'click .btn-play, .btn-pause': function(event) { this.model.set('playing', !this.model.get('playing')) } }, initialize: function() { this.listenTo(this.model, 'change', this.render) this.render() }, // ... })
<button class=”btn btn-<%- playing ? 'pause' : 'play' %>”></button>
이벤트 핸들러에서 DOM을 직접 조작하는 것이 의미가 있는 드문 상황이 있을 수 있지만 이벤트 핸들러에서 복잡한 DOM 조작을 관리하는 데 드는 비용은 거의 가치가 없습니다. 이것은 Backbone.js가 해결하고자 하는 것입니다. Backbone.js를 사용하여 이와 같은 작업을 수행하는 것은 실수입니다.
실수 #3: 렌더링 비용을 과소평가
Backbone.js를 사용하면 마음대로 또는 이벤트에 대한 응답으로 DOM을 매우 쉽게 렌더링하고 다시 렌더링할 수 있으므로 이것이 웹 애플리케이션의 전체 성능에 미치는 영향을 간과하는 경우가 많습니다. 우리의 뷰에서 렌더 메소드를 스래싱할 수 있는 많은 방법이 있습니다. 최신 웹 브라우저가 고성능 소프트웨어가 되고 있기 때문에 종종 이것이 많지 않은 것처럼 보일 수 있습니다. 그러나 웹 애플리케이션이 성장하고 처리하는 데이터의 양이 늘어남에 따라 성능 저하가 점점 더 분명해집니다.
작은 모델 컬렉션으로 시작하여 목록 보기로 렌더링하는 인위적인 예제를 통해 이것이 실제로 작동하는 것을 볼 수 있습니다.
var AudioPlayerPlaylist = Backbone.View.extend({ template: _.template('<ul> <% _.each(musics, function(m) { %> <li><%- m.title %></li> <% }) %> </ul>'), initialize: function() { this.listenTo(this.collection, 'add', this.render) }, // ... })
이 Backbone.js 예제에서는 모델이 컬렉션에 추가될 때마다 다시 렌더링합니다. 이것은 잘 작동합니다. 그러나 "add" 이벤트는 모델이 목록에 추가될 때마다 발생하므로 서버에서 많은 모델 목록을 가져오는 것을 상상해 보십시오. render 메서드는 서버 응답의 모든 모델에 대해 한 번씩 연속적으로 여러 번 호출됩니다. 충분히 큰 모델은 애플리케이션을 더듬거리게 만들고 사용자 경험을 망치기에 충분합니다. 때로는 렌더링되는 뷰의 복잡성에 따라 작은 응답으로 충분합니다.
이에 대한 매우 빠른 해결책은 추가되는 모든 단일 모델에 대해 단순히 render 메소드를 호출하지 않는 것입니다. 이와 같은 상황에서 모델은 일괄 처리로 추가되며 실제로는 지정된 시간 내에 다시 호출되지 않고 호출될 때만 render 메서드가 실행되도록 할 수 있습니다. Backbone.js의 종속성 Underscore.js는 이를 위한 편리한 유틸리티 기능인 "_.debounce"와 함께 제공됩니다. 이것을 활용하기 위해 필요한 것은 이벤트 바인딩 JavaScript 라인을 다음과 같이 변경하는 것입니다.
this.listenTo(this.collection, 'add', _.debounce(_.bind(this.render), 128))
이렇게 하면 "add" 이벤트가 발생할 때마다 이벤트 콜백이 시작되지만 실제로 render 메서드를 호출하기 전에 마지막 이벤트에서 128밀리초 동안 대기합니다.
대부분의 경우 이것은 솔루션과 같은 빠른 수정으로 간주됩니다. 사실, 렌더 스래싱을 피하는 더 적절한 방법이 있습니다. Trello의 개발자는 Backbone.js를 사용하는 동안 렌더링 성능을 개선한 경험과 접근 방식에 대해 논의하는 블로그 게시물을 작성한 적이 있습니다.
실수 #4: 이벤트 리스너를 사용 범위 이상으로 남겨두는 것
사용하지 않는 이벤트 리스너를 바인딩된 상태로 두는 것은 사용하는 JavaScript 프레임워크에 관계없이 또는 전혀 사용하지 않는 경우 발생할 수 있는 문제일 수 있습니다. Backbone.js를 사용하면 이 문제를 쉽게 피할 수 있지만 웹 응용 프로그램에서 쉽게 메모리 누수가 발생할 수 있는 잠재적인 구멍을 남겨두는 것은 확실히 실수입니다. Backbone.js의 "이벤트" 구성 요소는 확실히 꽤 깔끔한 구현입니다. 이를 통해 JavaScript 객체는 이벤트 기반 기능을 쉽게 구현할 수 있습니다. 뷰는 이벤트 소비의 대부분이 일반적으로 발생하는 곳이므로 다음과 같은 실수를 하기 쉽습니다.
var AudioPlayerControl = Backbone.View.extend({ initialize: function() { this.model.on('change', _.bind(this.render, this)) // ... }, // ... })
이 코드 조각의 이벤트 바인딩 줄은 첫 번째 예의 줄과 크게 다르지 않습니다. 여기서 한 일은 "this.listenTo(this.model, ...)"을 "this.model.on(…)"으로 변경한 것뿐입니다. 우리는 다른 JavaScript 프레임워크 및 라이브러리에 대한 경험에서 이벤트 바인딩에 대한 ".on()" 호출에 매우 익숙하기 때문에 Backbone.js를 사용하기 시작할 때 바인딩을 위해 ".on()" 호출을 사용하는 경향이 있습니다. 이벤트. 이벤트 핸들러가 더 이상 필요하지 않을 때 바인딩을 해제하기 위해 ".off()"를 호출하는 경우에만 괜찮았을 것입니다. 그러나 우리는 그렇게 하는 경우가 거의 없으며 결국 메모리 누수의 원인이 됩니다.

Backbone.js는 이 문제를 해결하는 간단한 방법을 제공합니다. "object.listenTo()" 메서드를 사용하는 것입니다. 이렇게 하면 "listenTo()"를 호출하는 객체가 수신 대기 중인 이벤트를 추적하고 모든 이벤트를 한 번에 쉽게 바인딩 해제할 수 있습니다. 예를 들어 뷰는 "remove()"를 호출하는 즉시 모든 바인딩된 이벤트 수신을 자동으로 중지합니다.
실수 #5: 모놀리식 뷰 생성
생각해 보면 Backbone.js의 미니멀리즘은 웹 애플리케이션의 프론트 엔드를 설계하는 방식에 엄청난 유연성을 제공합니다. 모델, 컬렉션 및 뷰가 구성 요소의 빌딩 블록이므로 가능한 한 가볍고 구체적으로 유지하는 것이 중요합니다. 종종 코드 측면에서 웹 애플리케이션의 가장 무거운 측면이 되는 것은 보기입니다. 그러나 애플리케이션이 제공해야 하는 모든 작업을 수행하려고 하는 거대한 모놀리식 뷰를 만들지 않는 것이 정말 중요합니다. 모든 논리가 꽉 찬 거대한 "AudioPlayer" 보기를 만드는 대신 재생 목록 보기, 컨트롤 보기, 시각화 도우미 보기 등과 같은 여러 논리 보기로 분할합니다. 확인하려는 세분성은 구축하려는 애플리케이션에 따라 다를 수 있습니다.
각 보기가 특정 작업을 수행하고 올바르게 수행하는 세분화된 보기를 사용하면 Backbone.js로 웹 애플리케이션을 개발하는 것이 쉬워지기 때문입니다. 당신의 코드는 더 유지하기 쉬워야 하고 미래에 확장하거나 수정하기 쉬워야 합니다. 그런 다음 과도하게 사용하는 다른 극단이 있습니다. Backbone.js 보기는 모델이나 컬렉션으로 작업하는 것이 편리하도록 설계되었으며 애플리케이션을 구성하는 방법에 대한 힌트로 작동할 수 있습니다. Ian Storm Taylor는 보기를 구현하는 동안 염두에 두어야 할 몇 가지 귀중한 아이디어를 블로그에서 공유했습니다.
실수 #6: Backbone.js가 RESTful이 아닌 API에 적용될 수 있다는 사실을 깨닫지 못함
Backbone.js는 기본적으로 JSON 기반 RESTful API와 함께 작동합니다. 이를 위해 필요한 것은 jQuery(또는 Zepto와 같이 이를 대체할 수 있는 것)뿐입니다. 그러나 Backbone.js는 확장성이 매우 뛰어납니다. 실제로 Backbone.js는 다른 유형의 API 및 다른 유형의 인코딩 형식을 사용하도록 조정할 수 있습니다.
프론트 엔드와 백 엔드 서비스의 상호 작용을 처리하는 Backbone.js의 구성 요소는 "동기화"입니다. 이 구성 요소는 API 끝점과 상호 작용하는 Backbone.js의 방식을 사용자 지정하기 위해 쉽게 재정의할 수 있는 여러 속성을 노출합니다. 실제로 기본 동기화 메커니즘을 백엔드 서비스 대신 localStorage를 사용하여 데이터를 유지하는 것과 같이 일반적이지 않은 것으로 교체하는 것도 가능합니다.
Backbone.js의 동기화 동작을 쉽게 사용자 정의할 수 있는 수많은 플러그인이 있습니다. 예를 들어 Backbone.dualStorage라는 플러그인을 사용하면 백엔드 서비스와 localStorage를 모두 사용하여 데이터를 유지할 수 있습니다. 애플리케이션이 오프라인 상태가 되면 플러그인은 localStorage를 사용하여 캐시된 데이터의 요청을 계속 제공하고 나중에 온라인 상태일 때 서버와 동기화할 수 있는 변경 사항을 추적합니다.
RESTful하고 호환되도록 설계된 백엔드와 함께 Backbone.js를 사용하는 것이 사용하기 더 쉽지만 이것이 Backbone.js가 모두 작동할 수 있다는 것을 의미하지는 않습니다. 기본 Backbone.js 동기화 메커니즘을 일부 변경하여 다양한 백엔드 서비스 API 및 인코딩 형식에 적용할 수 있습니다.
Backbone.js의 다른 부분도 유연하고 선택 사항이라는 점을 언급할 가치가 있습니다. 예를 들어 Underscore.js와 함께 제공되는 기본 템플릿 엔진을 사용할 필요가 없습니다. Backbone.js의 보기 구성 요소를 사용할 필요도 없으며 원하는 경우 완전히 다른 것으로 대체할 수 있습니다.
실수 #7: 모델 대신 뷰에 데이터 저장
Backbone.js를 배우는 초보자가 자주 범할 수 있는 한 가지 실수는 뷰에 직접 데이터를 속성으로 저장하는 것입니다. 이 데이터는 일부 상태 또는 일부 사용자 선택을 추적하기 위해 존재할 수 있습니다. 이것은 피해야 할 사항입니다.
var AudioPlayerVisualizer = Backbone.View.extend({ events: { 'click .btn-color': function(event) { this.colorHex = $(event.target).data('color-hex') this.render() } }, // ... })
끝점 없이 항상 몇 가지 추가 모델 및 컬렉션을 만들 수 있습니다. 이것들은 반드시 백엔드에 유지될 필요가 없거나 본질적으로 일시적일 수 있는 데이터를 저장하는 데 도움이 될 수 있습니다. 모델에 저장하면 변경 사항을 수신할 수 있다는 이점이 있습니다. 관련 보기 또는 여러 보기에서 이러한 모델을 관찰하고 필요에 따라 자체적으로 다시 렌더링할 수 있습니다.
실제로 뷰에 상태 추적 변수를 저장하고 변경할 때마다 렌더링 메서드를 호출해야 한다고 상상해 보십시오. 이 렌더 메서드에 대한 호출을 한 번만 놓치면 사용자가 화면에서 경험하는 것과 관련하여 응용 프로그램이 손상된 상태로 남을 수 있습니다. 게다가 작은 보기의 경우 여러 보기 개체에서 이러한 상태 변수를 동기화한 다음 해당 개체에 대해서도 render 메서드를 호출해야 할 수 있습니다.
실수 #8: 위임된 이벤트 대신 jQuery ".on()" 사용
내 생각에 Backbone.js는 DOM 이벤트를 처리하는 한 가지 훌륭한 방법을 가지고 있습니다. 사용하지 않으면 여러 가지 단점이 있습니다. jQuery의 ".on()" 이벤트 바인딩 기능은 편리하게 느껴질 수 있지만 장기적으로 보면 번거로운 경우가 많습니다. 예를 들어, 요소가 DOM에서 분리되면 jQuery는 ".on()"을 사용하여 요소에 바인딩된 모든 이벤트 핸들러를 자동으로 삭제합니다. 즉, DOM에서 루트 요소를 분리했다가 다시 연결하는 경우 뷰 내에서 바인딩하려는 모든 DOM 이벤트를 리바운드해야 합니다.
var AudioPlayerControls = Backbone.View.extend({ events: { 'click .btn-play, .btn-pause': function() { /* ... */ }, 'click .btn-prev': function() { /* ... */ }, 'click .btn-next': function() { /* ... */ }, 'click .btn-shuffle': function() { /* ... */ }, 'click .btn-repeat': function() { /* ... */ } }, // ... })
이 뷰에 해당하는 요소가 DOM에 다시 연결되면 뷰에서 "delegateEvents()"를 호출하여 이러한 모든 이벤트를 바인딩하기만 하면 됩니다.
이러한 이벤트가 바인딩되는 방식을 이해하는 것이 중요합니다. 선택기에 의해 지정된 요소에 대한 이벤트를 바인딩하는 대신 Backbone.js는 실제로 이벤트 핸들러를 뷰의 루트 요소에 바인딩합니다. 이것은 거의 모든 경우에 잘 작동하며 실제로 대부분의 필요에 더 잘 작동합니다. 뷰의 DOM 하위 트리에서 자식 요소를 변경하거나 교체할 때 Backbone.js가 새 요소에서 각 이벤트를 다시 바인딩할 필요가 없습니다. 기존 리스너는 계속 작동합니다.
그러나 이렇게 하면 특정 이벤트가 수신되지 않습니다. 한 가지 예는 "창" 또는 스크롤 가능한 자식 요소에서 스크롤 이벤트를 수신하려는 경우입니다. 자식 요소의 경우 해당 요소에 대한 하위 보기를 만들고 거기에서 이벤트를 처리할 수 있습니다.
결론
매우 컴팩트하지만 확장 가능한 프레임워크인 Backbone.js는 이면에서 상당한 유연성을 요구하는 웹 애플리케이션에 탁월한 선택입니다. 원하는 작업을 수행하는 방법을 알려주기 위해 항상 존재하는 Angular.js 및 Ember.js와 같은 프레임워크와 달리 Backbone.js는 한 걸음 물러서서 강력한 도구 세트를 제공하고 사용 방법을 결정할 수 있도록 합니다. 그들을. 초보자를 위한 이 Backbone.js 튜토리얼이 일반적인 개발 실수를 피하고 놀라운 것을 구축하는 데 도움이 되기를 바랍니다.