project: loginId typeahead while adding new member

프로젝트 관리 > 멤버 > 추가할 사용자의 login id 입력창에 자동완성(typeahead)을 적용합니다. 창에 글자를 입력하면, 그 글자를 포함한 loginId들의 목록이 보여집니다.

### 동작에 대한 설명

1. [twitter bootstrap의 typeahead 기능](http://twitter.github.io/bootstrap/javascript.html#typeahead)을 사용합니다.

2. 자동완성을 위해 사용자의 목록이 필요하면, 클라이언트는 서버에 `/users?query=keyword` 형식의 url로 `keyword`를 포함하고 있는 모든 loginId의 목록을 요청합니다.

3. 서버는 요청한 목록을 보내주되, 목록 내 항목의 갯수가 `controllers.UserApp.MAX_FETCH_USERS`보다 큰 경우, `controllers.UserApp.MAX_FETCH_USERS` 개 만큼만 보내줍니다. 이 때, 서버는 `Content-Range` 헤더를 이용해 총 몇 개의 loginId 중 몇 개를 보내주었는지 알려줍니다. 문법을 [ABNF](http://tools.ietf.org/html/rfc5234)로 표현하면 다음과 같습니다.

    ```abnf
    Content-Range = items-unit SP num-of-items "/" complete-length
    pages-unit = "items"
    num-of-items = 1*DIGIT
    complete-length   = 1*DIGIT
    SP = <US-ASCII SP, space (32)>
    ```

4. 응답의 `Content-Type`은 `application/json` 입니다. 따라서 서버는 요청의 Accept 헤더에 근거하여 클라이언트가 이를 받아들이지 못할 것으로 판단한 경우 `406 Not Accepted`로 응답합니다.

4. 클라이언트는 서버가 보낸 응답을 캐시하여, loginId의 목록이 필요하지 않을 것으로 짐작되는 경우(캐시된 목록이 새로 받을 목록을 포함할 것이라고 짐작하는 경우. 만약 캐시된 이후에 새로운 사용자가 추가되었다면 이 짐작은 틀리게 됩니다)에는 새로 요청을 보내지 않습니다.

5. 유의할 점
    * 위 3번의 명세는 HTTP/1.1의 `bytes-range-spec`과는 다릅니다.
    * 응답에 `Content-Range` 헤더를 포함하지만, Status Code가 `206 Partial Content` 인 것은 아닙니다.
    * 서버는 Range 요청을 이해하지 못합니다.

### 참고

[Fielding, R., Ed., Y. Lafon, Ed and J. Reschke, Ed., "Hypertext Transfer Protocol (HTTP/1.1): Range Requests", Internet-Draft draft-ietf-httpbis-p5-range-latest (work in progress), February 2013.](http://tools.ietf.org/html/draft-ietf-httpbis-p5-range-22)