# 백본 모델과 컬렉션에서 fetch 를 통해 JSON 가져오기!

## 모델

* [참고1](https://github.com/jashkenas/backbone/issues/4035)
* [참고2](https://stackoverflow.com/questions/18652437/backbone-not-parse-each-model-in-collection-after-fetch/18654257)
* [참고3](https://www.javatpoint.com/backbonejs-model-parse)
* 백본의 모델과 컬렉션에서는 **fetch** 메서드를 통해서 서버로부터 데이터를 가져올 수 있다.
* 모델은 `urlRoot`, 컬렉션은 `url` 을 사용해서 api 주소를 매핑한다.
* 여기서 중요한게 모델을 예로 들어보면

  ```javascript
  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` 에 선언해주는것.

  ```javascript
  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을 보내도 이제 모델을 초기화시킬 수 있다.
  ```

## 컬렉션 ( 문제 발생 )

* ```ruby
  def index
    users = User.all
    render :json => { users: users}
  end

  def show
    user = User.find_by_id(1)
    render :json => { user: user}
  end
  ```
* ```javascript
  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` 를 수정해주면 된다.
* ```javascript
  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;
      }
  })
  ```
*


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://simian114.gitbook.io/blog/undefined/backbonejs/fetch-json.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
