백본 모델과 컬렉션에서 fetch 를 통해 JSON 가져오기!
모델
백본의 모델과 컬렉션에서는 fetch 메서드를 통해서 서버로부터 데이터를 가져올 수 있다.
모델은
urlRoot
, 컬렉션은url
을 사용해서 api 주소를 매핑한다.여기서 중요한게 모델을 예로 들어보면
let User = Backbone.Model.extend({ urlRoot: '/api/users' }) let user = new User( { id: 1 }); // id를 1로 하는 user 백본 모델이 생긴다.(아직 이 백본 모델은 id를 제외한 어떠한 정보들도 가지고 있지 않다) user.fetch() // /api/users/1 의 url로 서버에게 요청을 보낸다.
위의
fetch()
의 결과로 서버가JSON
을 어떻게 주냐에 따라 백본에서 해줘야 할 처리가 달라진다.
// 1. JSON에 특정 객체를 키로 만들어서 주는 방법.
// 루비에서 render :json => { user: user }
{
"user": {
"id": 1,
"name": "sanam",
"imageUrl": "/~~"
}
}
// 2. 특정 객체가 아닌 그냥 값 주기
// 루비에서 render :json => user
{
"id": 1,
"name": "sanam",
....
}
여기서 만약 1번 의 방법을 사용해서 서버가 프론트에 데이터를 전송해준다면, 우리의
User
모델은 제대로 초기화 되지 않는다. 왜냐하면 백본 모델은 기본적으로 이미 모든게 파싱된 JSON 을 인자로 받아들여서 모델 자신을 초기화 하는데 1번 의 경우에는 서버가 모든게 파싱된 데이터가 아닌 아직 한겹의user
라는 객체를key
로 하는 JSON 을 줬기 때문이다. 따라서 특정 방법을 사용해주지 않는다면 2번 의 방법으로만 모델을 제대로 초기화할 수 있다.이 문제를 해결할 수 있는 방법이 있는데 바로
parse
메서드를model
에 선언해주는것.let User = Backbone.Model.extend({ urlRoot: '/api/users' parse: function() { return response.user; // JSON에 user라는 키로 데이터가 전송되기 때문에, user를 키로 하는 value 만을 가져오겠다! } }) let user = new User({ id: 1 }) user.fetch() // 위의 1번 방법으로 서버가 JSON을 보내도 이제 모델을 초기화시킬 수 있다.
컬렉션 ( 문제 발생 )
def index users = User.all render :json => { users: users} end def show user = User.find_by_id(1) render :json => { user: user} end
let User = Backbone.Model.extend({ urlRoot: '/api/users' parse: function() { return response.user; // JSON에 user라는 키로 데이터가 전송되기 때문에, user를 키로 하는 value 만을 가져오겠다! } }) let Users = Backbone.Collection.extend({ url: '/api/users', parse: function() { return response.users; } }) let users = new User(); users.fetch() window.users = users // 브라우저의 콘솔에서 users를 확인해보자.
서버에서 JSON 을 하나의 객체로 감싸서 프론트에 전송해주고, 프론트는 이제 이 값을
fetch
로 받을 때parse
를 통해 한꺼풀 벗겨서 가져온다.코드상으로 분명 문제가 없을거 같지만, 이 코드를 실행하면 정말 엄청난 에러가 생긴다.
브라우저에서
users
를 분석해보자. 그러면 이users
가 모델의 배열이 아닌, 자시 자신의 배열로 무한 참조가 된다는 것을 확인할 수 있다. 엄청난 문제다...
문제 해결
이렇게 된 원인은
parse
메서드에 존재한다. (솔직히 정확한 원인은 모른다. 머리가 아프다. 자고 싶다)해결법은 아래처럼
model
에서의parse
를 수정해주면 된다.let User = Backbone.Model.extend({ urlRoot: '/api/users' parse: function() { if (options.collection) { return response; } else { return response.user; } } }) let Users = Backbone.Collection.extend({ url: '/api/users', parse: function() { return response.users; } })
Last updated
Was this helpful?