REST API 클라이언트로서의 웹 애플리케이션 : 자원 식별자를 처리하는 방법


21

REST를 구현할 때 REST와 관련된 몇 가지 개념이 머리에서 충돌합니다.

비즈니스 논리를 보유하는 REST-ful 백엔드 API 시스템과 UI를 제공하는 웹 응용 프로그램이 있습니다. REST에 대한 다양한 리소스 (특히 REST in Practice : Hypermedia and Systems Architecture )에서 엔티티의 원시 식별자를 공개해서는 안되고로 하이퍼 링크를 반환해야한다는 것을 알고 rel="self"있습니다.

예를 고려하십시오. REST API에는 사람을 반환하는 리소스가 있습니다.

<Person>
  <Links>
    <Link rel="self" href="http://my.rest.api/api/person/1234"/>
  </Links>
  <Pets>
    <Link rel="pet" href="http://my.rest.api/api/pet/678"/>
  </Pets>
</Person>

웹 응용 프로그램에서 문제가 발생합니다. 브라우저에 대한 하이퍼 링크가 포함 된 페이지를 반환한다고 가정 해 봅시다.

<body class="person">
  <p>
    <a href="http://my.web.app/pet/???????" />
  </p>
</body>

href속성에 무엇을 넣어야 합니까? 사용자가 대상 페이지를 열 때 엔티티를 가져올 수 있도록 웹 애플리케이션에서 API 엔티티 URL을 유지하려면 어떻게해야합니까?

요구 사항이 상충되는 것 같습니다.

  1. 하이퍼 링크 href는 UI를 호스팅하는 시스템이기 때문에 웹 응용 프로그램으로 연결되어야합니다.
  2. href웹 응용 프로그램이 대상 페이지가 열릴 때 엔티티를 해결 할 수 있어야하기 때문에 엔티티의 일부 ID를 가지고 있어야
  3. 웹 응용 프로그램은 REST URL이 충분하지 않기 때문에 REST URL을 구문 분석 / 구성해서는 안됩니다.

URI는 소비자에게 불투명해야합니다. URI의 발행자 만이이를 해석하고이를 자원에 맵핑하는 방법을 알고 있습니다.

따라서 1234RESTful 클라이언트 인 것처럼 마치 마치 API 응답 URL을 가져갈 수 없습니다 http://my.rest.api/api/AGRIDd~ryPQZ^$RjEL0j. 반면에, 나는 내 웹 앱으로 연결되는 URL을 제공해야하며 앱이 어떻게 든 API의 원래 URL을 복원하고 해당 URL을 사용하여 API 리소스에 액세스하기에 충분합니다.

가장 간단한 방법은 아마도 리소스의 API URL을 문자열 식별자로 사용하는 것입니다. 그러나 웹 페이지 URL http://my.web.app/person/http%3A%2F%2Fmy.rest.api%2Fapi%2Fperson%2F1234은 추악합니다.

데스크톱 앱이나 단일 페이지 자바 스크립트 앱은 매우 쉬운 것 같습니다. 지속적으로 사용되므로 애플리케이션 수명 동안 서비스 객체와 함께 URL을 메모리에 유지하고 필요할 때 사용할 수 있습니다.

웹 응용 프로그램을 사용하면 여러 가지 접근법을 상상할 수 있지만 모두 이상하게 보입니다.

  1. API URL에서 호스트를 교체하고 결과 만 유지하십시오. 큰 단점은 웹 응용 프로그램이 API가 생성하는 모든 URL을 처리해야한다는 것입니다. 또한 웹 응용 프로그램이 URL 해석을 시작하기 때문에 다시 RESTful하지 않습니다.
  2. 링크와 함께 REST API의 원시 ID를 노출하고이를 사용하여 웹 애플리케이션의 URL을 빌드 한 다음 웹 애플리케이션 서버의 ID를 사용하여 API에서 필요한 자원을 찾으십시오. 이 방법이 더 좋지만 웹 앱은 브라우저의 요청을 처리하기 위해 특정 형식의 get-by-id 요청 체인을 발행하는 REST 서비스 탐색을 거쳐야하기 때문에 웹 앱 서버 성능에 영향을 미칩니다. 다소 중첩 된 리소스의 경우 비용이 많이들 수 있습니다.
  3. selfAPI가 반환 한 모든 URL을 웹앱 서버의 영구 (DB?) 매핑에 저장합니다. ID를 생성하고 ID를 사용하여 웹 앱 페이지 URL을 빌드하고 REST 서비스 자원의 URL을 가져 오십시오. 즉 http://my.rest.api/pet/678, 새 키로 URL을 어딘가에 유지하고으로 3웹 페이지 URL을 생성하십시오 http://my.web.app/pet/3. 이것은 일종의 HTTP 캐시 구현처럼 보입니다. 왜 그런지 모르겠지만 나에게는 이상해 보인다.

아니면 RESTful API가 웹 애플리케이션의 백엔드로 사용될 수 없다는 것을 의미합니까?


1
당신이 이루고자하는 것이 확실하지 않다. 아마도 당신의 단순한 의도가 당신이 서로 엮고있는 아키텍처의 계층들 아래에 있기 때문에 아마도 "RESTful APIs"가 정말로 당신을 도울 지 말하기 어렵다. 내가 당신의 문제를 이해 한 것에서, 옵션 2는 간단하고 실행 가능한 솔루션입니다. 여기서 "문제"는 "RESTful API"에 내재되어 있습니다. RestIsJustSqlReinvented 및 RDBMS에서 충분히 복잡한 하위 그래프를 검색하려고 할 때 실제로 동일한 문제가 발생합니다. 쿼리에 최적화 된 캐시 또는 표현을 사용하십시오.
back2dos

답변:


5

질문 업데이트를 해결하기 위해 편집, 이전 답변 제거

귀하의 질문에 대한 귀하의 변경 사항을 살펴보면 귀하가 조금 더 직면 한 문제를 이해하고 있다고 생각합니다. 리소스의 식별자 인 필드 (링크 만)가 없으므로 GUI 내에서 특정 리소스를 참조 할 수있는 방법이 없습니다 (예 : 특정 애완 동물을 설명하는 페이지에 대한 링크).

가장 먼저 결정해야 할 것은 애완 동물이 주인 없이도 합당한 지 여부입니다. 우리가 주인없이 애완 동물을 가질 수 있다면 애완 동물에 대한 일종의 독특한 재산이 필요하다고 말할 것입니다. 실제 리소스 ID가 여전히 REST 클라이언트가 구문 분석하지 않는 링크에 고정되어 있기 때문에 이것이 ID를 직접 노출시키지 않는 것이 아니라고 생각합니다. 이를 염두에두고 애완 동물 자원은 다음과 같습니다.

<Entity type="Pet">
    <Link rel="self" href="http://example.com/pets/1" />
    <Link rel="owner" href="http://example.com/people/1" />
    <UniqueName>Spot</UniqueName>
</Entity>

이제 응용 프로그램 전체에서 실제로 리소스 ID를 망칠 필요없이 해당 애완 동물의 이름을 Spot에서 Fido로 업데이트 할 수 있습니다. 마찬가지로 GUI에서 애완 동물을 다음과 같이 참조 할 수 있습니다.

http://example.com/GUI/pets/Spot

애완 동물이 소유자없이 이해가되지 않는 경우 (또는 소유자가없는 시스템에서는 애완 동물이 허용되지 않음) 시스템에서 애완 동물의 "정체성"의 일부로 소유자를 사용할 수 있습니다.

http://example.com/GUI/owners/John/pets/1(John 의 목록에서 첫 번째 애완 동물)

하나의 작은 메모, 애완 동물과 사람이 서로 별개로 존재할 수 있다면 API의 시작점을 "사람"리소스로 만들지 않을 것입니다. 대신 사람과 애완 동물에 대한 링크를 포함하는보다 일반적인 리소스를 만들려고합니다. 다음과 같은 리소스를 반환 할 수 있습니다.

<Entity type="ResourceList">
    <Link rel="people" href="http://example.com/api/people" />
    <Link rel="pets" href="http://example.com/api/pets" />
</Entity>

따라서 API에 대한 첫 번째 진입 점 만 알고 시스템 식별자를 파악하기 위해 URL을 처리하지 않으면 다음과 같이 할 수 있습니다.

사용자가 응용 프로그램에 로그인합니다. REST 클라이언트는 다음과 같은 사용 가능한 전체 인력 자원 목록에 액세스합니다.

<Entity type="Person">
    <Link rel="self" href="http://example.com/api/people/1" />
    <Pets>
        <Link rel="pet" href="http://example.com/api/pets/1" />
        <Link rel="pet" href="http://example.com/api/pets/2" />
    </Pets>
    <UniqueName>John</UniqueName>
</Entity>
<Entity type="Person">
    <Link rel="self" href="http://example.com/api/people/2" />
    <Pets>
        <Link rel="pet" href="http://example.com/api/pets/3" />
    </Pets>
    <UniqueName>Jane</UniqueName>
</Entity>

GUI는 각 리소스를 반복하고 UniqueName을 "id"로 사용하여 각 개인에 대한 목록 항목을 인쇄합니다.

<a href="http://example.com/gui/people/1">John</a>
<a href="http://example.com/gui/people/2">Jane</a>

이 작업을 수행하는 동안 "pet"과 관련하여 찾은 각 링크를 처리하고 다음과 같은 pet 리소스를 얻을 수 있습니다.

<Entity type="Pet">
    <Link rel="self" href="http://example.com/api/pets/1" />
    <Link rel="owner" href="http://example.com/api/people/1" />
    <UniqueName>Spot</UniqueName>
</Entity>

이를 사용하여 다음과 같은 링크를 인쇄 할 수 있습니다.

<!-- Assumes that a pet can exist without an owner -->
<a href="http://example.com/gui/pets/Spot">Spot</a>

또는

<!-- Assumes that a pet MUST have an owner -->
<a href="http://example.com/gui/people/John/pets/Spot">Spot</a>

첫 번째 링크로 이동하여 입력 리소스에 "애완 동물"관계가있는 링크가 있다고 가정하면 제어 흐름은 GUI에서 다음과 같이 진행됩니다.

  1. 페이지가 열리고 애완 동물 반점이 요청됩니다.
  2. API 진입 점에서 자원 목록을로드하십시오.
  3. "애완 동물"이라는 용어와 관련된 리소스를로드하십시오.
  4. "애완 동물"응답에서 각 리소스를 살펴보고 스팟과 일치하는 리소스를 찾으십시오.
  5. 스팟에 대한 정보를 표시하십시오.

두 번째 링크를 사용하는 것은 People 이 API의 진입 점이라는 점을 제외하고 비슷한 이벤트 체인이 될 것입니다. 먼저 시스템의 모든 사람 목록을 가져 와서 일치하는 사람을 찾은 다음 소속 된 모든 애완 동물을 찾습니다. rel 태그를 다시 사용하여 그 사람에게 특정 이름을 지정하여 Spot과 관련된 특정 정보를 표시 할 수 있습니다.


고마워, 마이크 질문을 좀 더 명확하게하기 위해 업데이트했습니다. 귀하의 답변에 관한 문제는 REST 클라이언트가 URL을 구문 분석 할 수 있다는 것에 동의하지 않는다는 것입니다. 그렇다면 URL에 연결됩니다. 그리고 이것은 REST의 핵심 아이디어 중 하나를 위반 rel합니다. REST는 API가 rel동일하게 유지 되는 한 자유롭게 URL을 변경할 수 있다고 주장합니다 . URL을 구문 분석하면 REST보다 SOAP에 더 가깝게 이동합니다.
Pavel Gatilov

다시 감사합니다. 지금까지 우리가 취한 접근법을 설명했습니다. 어떤 식 으로든 식별자를 노출시킵니다. 유일하게 가능한 한 자연 식별자를 공개하려고합니다.
Pavel Gatilov 08

6

RESTful API가 웹 애플리케이션의 백엔드로 기능 할 수 없다는 것을 의미합니까?

REST API와 웹 애플리케이션을 구별하는 것이 가치가 있는지에 대해 질문합니다. 귀하의 "웹 응용 프로그램은"그냥 같은 자원의 대체 (HTML) 표현해야 - 어떻게, 왜 액세스 기대, 내가 이해하지 못하는 말을하는 것입니다 http://my.rest.api/...그리고 http://my.web.app/...그들은 동시에 동일한와 다를 수 있음.

이 경우 "클라이언트"는 브라우저이며 HTML 및 JavaScript를 이해합니다. 즉 이다 내 의견으로는 웹 응용 프로그램입니다. 이제 당신은 동의하지 않고 foo.com을 사용하여 웹 응용 프로그램에 액세스하고 api.foo.com을 통해 다른 모든 것을 노출한다고 생각할 수 있습니다. 그러나 foo.com은 어떻게 리소스의 표현을 제공 했습니까? foo.com의 "백엔드"는 api.foo.com에서 리소스를 검색하는 방법을 완벽하게 이해할 수 있습니다. 웹 응용 프로그램은 프록시가되었습니다. 다른 API와 다른 사람과 함께 대화하는 경우와 다르지 않습니다.

따라서 귀하의 질문은 "다른 시스템에 존재하는 고유 한 URI를 사용하여 리소스를 어떻게 설명 할 수 있습니까?"로 일반화 될 수 있습니다. 클라이언트 (HTML / JavaScript)가 아니라 서버를 수행하는 방법을 이해해야한다고 생각하면 사소한 것입니다. 첫 번째 과제에 동의하면 웹 애플리케이션을 다른 REST API를 프록시하거나 위임하는 별도의 REST API로 생각하면됩니다.

따라서 클라이언트가 액세스 my.web.app/pets/1할 때 서버 측 템플릿에서 반환 한 것이거나 다른 표현 (예 : JSON 또는 XML)에 대한 비동기 요청 인 경우 애완 동물 인터페이스를 표시하는 것을 알고 컨텐츠 유형 헤더가 알려줍니다 .

이를 제공하는 서버는 애완 동물이 무엇인지, 원격 시스템에서 애완 동물을 발견하는 방법을 이해해야합니다. 이 작업을 수행하는 방법은 전적으로 사용자에게 달려 있습니다. ID를 가져 와서 다른 URI를 생성 할 수 있습니다.이 URL은 부적절한 것으로 생각되거나 원격 URI를 저장하고 요청을 프록시하는 자체 데이터베이스를 보유 할 수 있습니다. 이 URI를 저장하는 것은 괜찮습니다. 이는 북마크에 해당합니다. 별도의 도메인 이름을 가지기 위해이 모든 작업을 수행해야합니다. 왜 당신이 이것을 원하는지 정직하게 모르겠습니다-REST API URI도 북마크 가능해야합니다.

귀하는 이미 귀하의 질문 에이 대부분을 제기했지만, 실제로 귀하가하고 싶은 일을하는 실제적인 방법임을 인정하지 않는 방식으로 액자를 만들었다 고 생각합니다 (내가 느끼는 것에 기초하여 임의의 제약-API와 응용 프로그램이 분리되어야 함). REST API가 웹 애플리케이션의 백엔드가 될 수 없는지 묻고 성능이 문제가 될 수 있다고 제안함으로써, 나는 당신이 모두 잘못된 것에 집중하고 있다고 생각합니다. 매시업을 작성할 수 없다고 말하는 것과 같습니다. 웹이 작동하지 않는다고 말하는 것과 같습니다.


웹 앱이 단순히 API를 나타내는 것으로 기대하지는 않습니다. 예를 들어 여러 하위 리소스를 단일 페이지에 루트 리소스와 함께 표시하는 등 많은 차이가있을 수 있습니다. 웹 응용 프로그램 URL에 api 데이터 저장소의 내부 ID를 포함시키지 않기를 원합니다.이 경우 두 시스템이 동일하다고 기대하면됩니다. 나는 여기서 성능에 관심이 없으며 문제가 아닙니다. 문제는 실제로 ' my.web.app/pets/3REST API URL을 구문 분석하지 않고 어떻게 3을 넣 습니까?'입니다.
Pavel Gatilov

내 자신의 문구를 수정 : ' my.web.app/pets/3해당 REST API 리소스의 URL을 구문 분석하지 않고 3을 어떻게 넣 my.rest.api/v0/persons/2/pets/3습니까? 아니면 내가 무엇을 넣을 까? '
Pavel Gatilov

나는 당신이 클라이언트의 상태를 그 상태를 결정하는 표현과 혼동하고 있다고 생각합니다. 당신은 넣지 마십시오 3app/pets/3있기 때문에 app/pets/3불투명, 그것은 당신의 웹 응용 프로그램이 원하는 어떤 리소스를 가리 킵니다. 그것이 다른 여러 리소스 (다른 시스템-API 중 하나)의 구성된보기 인 경우 웹 응용 프로그램 서버 내의 해당 시스템에 대한 하이퍼 링크를 저장 한 다음 검색하여 해당 표현으로 해결해야합니다 ( 예를 들어 JSON 또는 XML)을 입력 한 다음 응답의 일부로 제공하십시오.
Doug

API와 앱은 잊어 버리십시오. 사람들이 좋아하는 Facebook 및 Twitter 게시물을 수집 할 수있는 사이트를 만들고 싶다고 가정합니다. 그것들은 원격 시스템입니다. 자신의 시스템을 통해 URI를 이러한 시스템에 터널링하거나 템플릿으로 만들려고하지 않습니다. 당신은 '보드'리소스를 만들 것과는 알고 서버 것 board/1포인트 facebook.com/post/123twitter.com/status/789- 당신이 당신의 보드의 표현을 제공하기 위해 갈 때, 당신은 당신이 작업 할 수있는 표현으로 그 URI를 해결해야합니다. 필요한 곳에 캐시하십시오.
Doug

따라서 API가 앱과 크게 다르기를 원하기 때문에 (여전히 의심 스럽다고 생각합니다.) 원격 시스템처럼 처리하는 것이 다르지 않습니다. 당신은 성능이 문제가 아니라고 말했지만, 이와 같은 것이 '성능에 영향을 미칠 것'이라고 질문했습니다.
Doug

5

머리말

이 답변은 구체적으로 백엔드 REST API가 명시 적으로 식별자를 노출하지 않고 API에서 제공 한 URL을 해석하지 않고 고유 한 책갈피 가능한 URL을 포함하여 고유 한 URL 스킴을 관리하는 방법에 대한 질문을 다룹니다.


검색 가능성에는 어느 정도의 지식이 필요하므로 실제 시나리오를 살펴 보겠습니다.

http://my.web.app/person결과에 각 사람의 세부 정보 페이지에 대한 링크가 포함 된 검색 페이지가 필요하다고 가정 해 봅시다 . 프론트 엔드 코드 알아야 할 것은 REST 데이터 소스의 기본 URL입니다 http://my.rest.api/api. 이 URL에 대한 GET 요청에 대한 응답은 다음과 같습니다.

<Links>
    <Link ref="self" href="http://my.rest.api/api" />
    <Link rel="person" href="http://my.rest.api/api/person" />
    <Link rel="pet" href="http://my.rest.api/api/pet" />
</Links>

우리의 의도는 사람들의 목록을 표시하는 것이므로 다음으로 링크 href GET에서 href 로 요청을 보냅니다 person.

<Links>
    <Link ref="self" href="http://my.rest.api/api/person" />
    <Link rel="search" href="http://my.rest.api/api/person/search" />
</Links>

검색 결과를 표시하려고하므로 link href에 GET요청을 보내 검색 서비스를 사용합니다 search.

<Persons>
    <Person>
        <Links>
            <Link rel="self" href="http://my.rest.api/api/person/1"/>
        </Links>
        <Pets>
            <Link rel="pet" href="http://my.rest.api/api/pet/10"/>
        </Pets>
    </Person>
    <Person>
        <Links>
            <Link rel="self" href="http://my.rest.api/api/person/2"/>
        </Links>
        <Pets>
            <Link rel="pet" href="http://my.rest.api/api/pet/20"/>
        </Pets>
    </Person>
</Persons>

우리는 마침내 결과를 얻었지만 프런트 엔드 URL을 어떻게 구축합니까?

API 기본 URL을 알고있는 부분을 제거하고 나머지를 프론트 엔드 식별자로 사용합니다.

  • 알려진 API 기반 : http://my.rest.api/api
  • 개별 엔티티에 대한 주어진 URL : http://my.rest.api/api/person/1
  • 고유 ID : /person/1
  • 기본 URL : http://my.web.app
  • 생성 된 프런트 엔드 URL : http://my.web.app/person/1

결과는 다음과 같습니다.

<ul>
    <li><a href="http://my.web.app/person/1">A person</a></li>
    <li><a href="http://my.web.app/person/2">A person</a></li>
</ul>

사용자가 세부 정보 페이지로 연결되는 프런트 엔드 링크를 따라 가면 해당 URL에 GET대한 세부 정보 요청 을 어떤 URL로 보냅니 person까? 우리는 백엔드 URL을 프론트 엔드 URL로 매핑하는 방법을 알고 있습니다.

  • 프론트 엔드 URL : http://my.web.app/person/1
  • 기본 URL : http://my.web.app
  • 고유 ID : /person/1
  • 알려진 API 기반 : http://my.rest.api/api
  • 생성 된 API URL : http://my.rest.api/api/person/1

나머지의 API가되도록 변경하는 경우 personURL 지금 http://my.rest.api/api/different-person-base/person/1누군가가 이전에 북마크를 http://my.web.app/person/1, 나머지 API는 (한 번에 적어도) 신규로 리디렉션으로 이전 URL에 응답하여 이전 버전과의 호환성을 제공해야한다. 생성 된 모든 프런트 엔드 링크에는 새 구조가 자동으로 포함됩니다.

알다시피 API를 탐색하기 위해 알아야 할 몇 가지 사항이 있습니다.

  • API 기본 URL
  • person관계
  • search관계

나는 이것에 문제가 있다고 생각하지 않습니다. 우리는 어느 시점에서든 특정 URL 구조를 가정하지 않으므로 엔티티 URL의 구조 http://my.rest.api/api/person/1가 변경 될 수 있으며 API가 이전 버전과의 호환성을 제공하는 한 코드는 여전히 작동합니다.


라우팅 로직이 두 프런트 엔드 URL의 차이점을 어떻게 알 수 있는지 물었습니다.

  • http://my.rest.api/api/person/1
  • http://my.rest.api/api/pet/3.

먼저이 예제에서 UI와 REST API에 별도의 기본 URL을 사용하는 경우 주석에 API 기반을 사용했음을 지적하겠습니다. 별도의베이스를 사용하여 예제를 계속 하겠지만베이스를 공유하는 것은 문제가되지 않습니다. 요청의 Accept 헤더에서 미디어 유형을 사용하여 UI 라우팅 방법을 매핑 할 수 있거나 매핑 할 수 있어야합니다.

특정 세부 정보 페이지로 라우팅하는 경우 selfAPI에서 제공 하는 URL 의 구조 (예 : 불투명 문자열 ID)에 대한 지식을 피해야하는 경우 두 URL을 구분할 수 없습니다 . 이 작업을 수행하기 위해 알려진 정보 중 하나 (우리가 작업중인 엔터티 유형)를 프런트 엔드 URL에 포함시켜 보겠습니다.

이전에는 프런트 엔드 URL 형식이 다음과 같습니다. ${UI base}/${opaque string id}

새로운 형식은 다음과 같습니다. ${UI base}/${entity type}/${opaque string id}

따라서이 /person/1예제를 사용하면로 끝납니다 http://my.web.app/person/person/1.

이 형식을 사용하면 UI 라우팅 논리가로 작동 /person/person/1하고 문자열의 첫 번째 토큰이 직접 삽입 된 것을 알면이를 뽑아서이를 기반으로 적절한 (이 예제에서는 개인) 세부 정보 페이지로 라우팅 할 수 있습니다. 해당 URL에 대해 양감을 느끼면 여기에 조금 더 삽입 할 수 있습니다. 아마도: http://my.web.app/person/detail/person/1

어느 경우에 우리 /person/detail는 라우팅을 위해 구문 분석 하고 나머지를 불투명 문자열 ID로 사용합니다.


나는 이것이 웹 응용 프로그램을 API에 매우 밀접하게 결합한다고 생각합니다.

생성 된 프런트 엔드 URL에 API URL의 일부가 포함되어 있기 때문에 이전 구조를 지원하지 않고 API URL 구조가 변경되면 북마크 된 URL을 웹 사이트로 변환하려면 코드 변경이 필요합니다. 새로운 버전의 API URL. 즉, REST API가 리소스의 ID (불투명 한 문자열)를 변경하면 이전 ID를 사용하여 해당 리소스에 대해 서버와 대화 할 수 없습니다. 그 상황에서 코드 변경을 피할 수 있다고 생각하지 않습니다.

웹앱의 URL 구조가 API의 URL 구조와 다르도록하려면 어떻게해야합니까?

원하는 URL 구조를 사용할 수 있습니다. 하루가 끝나면 특정 리소스의 북마크 가능한 URL에 해당 리소스를 고유하게 식별하는 API URL을 얻는 데 사용할 수있는 URL이 포함되어야합니다. 접근 방식 # 3에서와 같이 고유 식별자를 생성하고 API URL로 캐시하면 해당 항목이 캐시에서 지워진 후 누군가가 북마크 된 URL을 사용하려고 시도 할 때까지 작동합니다.

내 웹앱 엔티티가 API 엔티티 1-1에 매핑되지 않은 경우 어떻게합니까?

대답은 관계에 따라 다릅니다. 어느 쪽이든 프런트 엔드를 API URL에 매핑하는 방법이 필요합니다.


이 접근법에는 한 가지 문제가 있습니다. 실제로 내 솔루션 목록에서 1 번입니다. 내가 얻지 못하는 것은 이것입니다 : 웹 응용 프로그램이 URL을 해석하지 않고 고유 한 ID를 불투명 문자열 ( person/1, pet/3) 로 취급 하면 브라우저가 열리면 http://my.rest.api/api/person/1사람 UI를 표시 해야하는지 어떻게 알 수 있습니까? 을 연 http://my.rest.api/api/pet/3다음 애완 동물 UI?
Pavel Gatilov 08

좋은 질문! 응답으로 답변을 업데이트했습니다.
Mike Partridge

고마워, 마이크 나는 이것이 웹 응용 프로그램을 API에 매우 밀접하게 결합한다고 생각합니다. 웹앱의 URL 구조가 API의 URL 구조와 다르도록하려면 어떻게해야합니까? 내 웹앱의 엔티티가 API 엔티티 1-1에 매핑되지 않은 경우 어떻게합니까? 나는 여전히 일부 식별자를 노출하는 방법을 사용하는 것이 더 좋지만 클라이언트가 탐색을 위해 링크를 사용하도록 촉구한다고 생각합니다.
Pavel Gatilov 2013

이것은 흥미로운 주제이므로 아무것도 빠지지 않기를 바랍니다. 귀하의 의견에 대한 답변으로 답변을 업데이트했습니다. 일부 식별자를 노출하는 것이 완전한 RESTfulness와 유용성 사이의 좋은 절충안이라고 생각합니다.
Mike Partridge

나의 주요 관심사는 조금 더 실용적입니다. ASP.NET MVC를 사용하여 웹 앱을 구현하고 일부 내부 규칙으로 인해 앱이 지원하는 URL 패턴을 정의해야합니다. 즉, / a / {id}가 정의 된 경우 앱은 / a / 1 / b / 2가 아닌 / a / 1을 처리합니다. 이로 인해 REST API URL이 책갈피 된 URL을 보존하기 위해 변경 될뿐만 아니라 루트에서 탐색 할 때 단순히 웹 앱이 작동하도록하는 경우 웹 앱을 다시 컴파일해야합니다. HTML 페이지에 포함 된 하이퍼 링크가 없으면 작동하지 않습니다.
Pavel Gatilov

2

그것을 직면하자 마법의 해결책은 없습니다. Richardson Maturity Model 을 읽었 습니까? REST 아키텍처 성숙도를 리소스, HTTP 동사 및 하이퍼 미디어 제어의 3 가지 수준으로 나눕니다.

엔티티의 원시 식별자를 공개해서는 안되며 rel = "self"를 사용하여 하이퍼 링크를 반환해야합니다.

이것은 하이퍼 미디어 컨트롤입니다. 정말로 필요합니까? 이 방법은 매우 좋은 이점이 있습니다 ( 여기에서 이에 대해 읽을 수 있음 ). 그러나 무료 식사와 같은 것은 없으며, 식사를하려면 열심히 노력해야합니다 (예 : 두 번째 해결책).

균형의 문제입니다-성능을 희생하고 코드를 더 복잡하게 만들고 싶지만 더 유연한 시스템을 원하십니까? 아니면 더 빠르고 간단하게 유지하고 싶지만 나중에 API / 모델을 변경할 때 비용을 지불 하시겠습니까?

비슷한 시스템 (비즈니스 로직 계층, 웹 계층 및 웹 클라이언트)을 개발 한 사람으로서 두 번째 옵션을 선택했습니다. 우리 그룹이 모든 계층을 개발 했으므로 웹 계층에 엔티티 ID를 알리고 API URL을 작성함으로써 약간의 커플 링을 갖는 것이 더 좋으며 대신에 더 간단한 코드를 얻는 것이 좋습니다. 우리의 경우에는 이전 버전과의 호환성도 관련이 없었습니다.

웹 응용 프로그램이 타사에서 개발되었거나 이전 버전과의 호환성이 문제인 경우 웹 응용 프로그램을 변경하지 않고 URL 구조를 변경할 수 있다는 점에서 큰 가치가 있었기 때문에 다르게 선택했을 수 있습니다. 코드 복잡성을 정당화하기에 충분합니다.

RESTful API가 웹 애플리케이션의 백엔드로 기능 할 수 없다는 것을 의미합니까?

완벽한 REST 구현을 만들 필요가 없다는 것을 의미한다고 생각합니다. 두 번째 솔루션을 사용하거나 엔티티 ID를 노출하거나 api urls를 전달할 수 있습니다. 의미와 장단점을 이해하는 한 괜찮습니다.


0

당신과 비슷한 것을 고집 Atom Syndication Format하면 좋을 것 같습니다.

여기에서 추가되는 요소 / 속성을 사용하여 표현되는 항목을 설명하는 메타 데이터를 지정할 수 있습니다.

  • [RFC4287] , 고유의 항목을 식별하는 URI를 포함

  • [RFC4287] ,이 요소는 선택 사항이다. 포함 된 경우 클라이언트가 항목을 검색하는 데 사용해야하는 URI를 포함합니다.

이것은 단지 내 두 센트입니다.


어쩌면 나는 뭔가를 얻지 못했지만 귀하의 답변에 REST API의 클라이언트 인 웹 응용 프로그램의 URL을 생성하는 방법을 설명하지 않는 것 같습니다.
Pavel Gatilov 2013

0

URL에 대해 걱정하지 말고 미디어 유형에 대해 걱정하십시오.

여기를 참조하십시오 (특히 세 번째 글 머리 기호).

REST API는 리소스를 표현하고 애플리케이션 상태를 구동하는 데 사용되는 미디어 유형을 정의하거나 기존 표준 미디어 유형에 대한 확장 관계 이름 및 / 또는 하이퍼 텍스트 가능 마크 업을 정의하는 데 거의 모든 설명 노력을 기울여야합니다. .


일반적인 웹 앱의 경우 클라이언트는 사람입니다 . 브라우저는 에이전트 일뿐 입니다.

따라서 앵커 태그는

          <a href="example.com/foo/123">click here</a>

같은 것에 해당

          <link type="text/html" rel="self" href="example.com/foo/123">

URL은 여전히 ​​사용자에게 불투명하며, 관심있는 것은 미디어 유형 (예 :) text/html, application/pdf, application/flv, video/x-flv, image/jpeg, image/funny-cat-picture etc입니다. 앵커 (및 제목 속성)에 포함 된 설명 텍스트는 인간이 이해할 수있는 방식으로 관계 유형을 확장하는 방법 일뿐입니다.

URI가 클라이언트에게 불투명하게되는 이유는 커플 링 (REST의 기본 목표 중 하나)을 줄이기 위해서입니다. 서버는 클라이언트에 영향을주지 않고 URI를 변경 / 재구성 할 수 있습니다 (캐싱 정책이 양호하다면 캐싱이 전혀 없을 수 있음).

요약해서 말하자면

클라이언트 (휴먼 또는 머신)가 URL이 아닌 미디어 유형 및 관계에 관심을 갖도록하면 괜찮습니다.


Rodrick, 내 질문은 API 작성에 관한 것이 아니라 RESTful API 위에있는 웹 응용 프로그램 작성에 관한 것입니다. 미디어 유형이 웹앱의 URL을 구축하는 데 어떻게 도움이되는지 거의 이해할 수 없습니다. 미디어 유형은 서비스 계약 및 검색 가능성에 중요합니다.
Pavel Gatilov 2013

@PavelGatilov-웹앱의 클라이언트는 인간입니까?
Rodrick Chapman 2013

그렇습니다. 그리고 매우 미숙 한 사람.
Pavel Gatilov

0

가장 간단한 방법은 아마도 리소스의 API URL을 문자열 식별자로 사용하는 것입니다. 그러나 http://my.web.app/person/http%3A%2F%2Fmy.rest.api%2Fapi%2Fperson%2F1234 와 같은 웹 페이지 URL 은 추악합니다.

나는 당신이 옳다고 생각합니다. 그것이 가장 간단한 방법입니다. URL을 상대적으로 http://my.rest.api/api덜 추악하게 만들 수 있습니다.

http://my.web.app/person/person%2F1234

API가 제공 한 URL이 해당 기준과 관련이없는 경우 추악한 형식으로 저하됩니다.

http://my.web.app/person/http%3A%2F%2Fother.api.host%2Fapi%2Fperson%2F1234

한 단계 더 나아가려면 API 서버의 응답을 검사하여 어떤 종류의보기를 제공할지 결정하고 경로 세그먼트 구분 기호 및 콜론 인코딩을 중지하십시오.

http://my.web.app/person/1234 (best case)
http://my.web.app/http://other.api.host/api/person/1234 (ugly case)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.