모델(Model)과 뷰(View)의 분리, Backbone.js의 등장

62025년 08월 21일4

스파게티 코드의 미궁을 탈출하기 위한 페이스북 엔지니어들의 탐색은 하나의 이름으로 수렴했다. 바로 제레미 애쉬케나스(Jeremy Ashkenas)가 만든 경량 라이브러리, 백본(Backbone.js)이었다.

백본은 당시 난립하던 자바스크립트 코드에 ‘뼈대(Backbone)’를 세워주겠다는 야심 찬 목표를 가지고 있었다. 그 핵심 철학은 지극히 단순하고 명료했다.

“데이터(Model)와 화면(View)을 분리하라.”

이 한 문장은 페이스북 개발자들에게 거대한 울림을 주었다. 그들이 겪던 모든 문제의 근원을 정확히 꿰뚫고 있었기 때문이다. 팀은 즉시 백본을 이용한 소규모 실험에 착수했다.

가장 먼저 한 일은 모델(Model)을 정의하는 것이었다. 모델은 순수한 자바스크립트 객체로, 오직 데이터와 그 데이터를 다루는 로직만을 담았다. 예를 들어 ‘사용자 프로필’ 모델은 다음과 같은 형태였다.

// Backbone.js의 모델 정의
var UserProfileModel = Backbone.Model.extend({
  defaults: {
    name: 'Unknown User',
    profileImageUrl: 'default.jpg',
    notificationCount: 0,
  },
});

var mattProfile = new UserProfileModel({
  name: '맷',
  notificationCount: 1,
});

여기에는 HTML이나 화면에 대한 정보가 단 한 줄도 없었다. 오직 ‘맷’이라는 이름과 ‘알림 1개’라는 데이터만 존재했다. 데이터는 더 이상 DOM 여기저기에 흩어져 있지 않고, ‘mattProfile’이라는 명확한 객체 안에 안전하게 보관되었다.

다음 단계는 이 모델을 화면에 그려줄 뷰(View)를 만드는 것이었다. 뷰의 역할은 명확했다. 자신이 담당하는 모델의 데이터를 가져와서 HTML로 만들어 화면에 렌더링하는 것이다.

// Backbone.js의 뷰 정의
var ProfileView = Backbone.View.extend({
  initialize: function () {
    // 뷰가 생성될 때, 모델에서 'change' 이벤트가 발생하면
    // 자신의 render 함수를 실행하도록 등록한다.
    this.listenTo(this.model, 'change', this.render);
  },

  render: function () {
    var name = this.model.get('name');
    var count = this.model.get('notificationCount');

    var html_template = '<h1>' + name + '</h1>' + '<p>새 알림: ' + count + '개</p>';

    // 뷰가 관리하는 DOM 요소의 내용을 교체한다.
    this.$el.html(html_template);
  },
});

// 모델과 뷰를 연결하여 생성
var mattProfileView = new ProfileView({ model: mattProfile });

// 최초 렌더링 실행
mattProfileView.render();

마법은 initialize 함수 안의 this.listenTo(this.model, 'change', this.render); 한 줄에서 일어났다. 이 코드는 뷰에게 “네가 책임지고 있는 모델의 데이터에 어떤 변경이라도 생기면, 즉시 너의 render 함수를 다시 실행해라”고 명령하는 것과 같았다.

이제 개발자는 더 이상 DOM을 직접 찾아다닐 필요가 없었다. 어딘가에서 새로운 알림이 도착하면, 그저 이 한 줄만 실행하면 되었다.

mattProfile.set({ notificationCount: 2 });

이 코드가 실행되는 순간, mattProfile 모델은 자신의 데이터가 변경되었음을 감지하고 ‘change’ 이벤트를 발생시킨다. 그 이벤트를 듣고 있던 mattProfileView는 약속대로 자신의 render 함수를 자동으로 호출한다. render 함수는 모델에서 새로운 알림 개수인 ‘2’를 가져와 새로운 HTML을 만들고, 화면을 스스로 갱신한다.

“이거다…!”

코드를 테스트하던 개발자들의 입에서 탄성이 터져 나왔다. 드디어 질서가 보였다. 데이터는 모델에, 화면 표시는 뷰에. 각자의 역할이 명확하게 분리되었다. 한 기능의 데이터 변경이 다른 기능에 예기치 못한 버그를 일으키는 연쇄 작용의 고리를 끊어낼 실마리를 찾은 것이다.

백본의 등장은 한 줄기 희망과도 같았다. 페이스북의 복잡성은 마침내 관리 가능한 수준으로 들어오는 듯 보였다.

하지만 사무실 한편에서 이 모든 과정을 지켜보던 조던 워크의 눈에는, 새로운 희망의 그림자 뒤에서 또 다른 복잡성의 씨앗이 자라나는 것이 보이고 있었다. 그는 아직 아무 말도 하지 않았다. 그러나 그의 머릿속은 이미 다음 질문으로 넘어가고 있었다.

‘과연 이 분리만으로 충분할까?’