RESTful API에서 경로 매개 변수와 쿼리 매개 변수를 언제 사용합니까?


141

RESTful API를 매우 예측 가능하게 만들고 싶습니다. 쿼리 매개 변수를 사용하지 않고 URI를 사용하여 데이터를 분할 할시기를 결정하는 가장 좋은 방법은 무엇입니까?

페이지 매김, 정렬 및 그룹화를 지원하는 시스템 매개 변수는 '?'다음에 오는 것이 좋습니다. 그러나 '상태'및 '지역'또는 컬렉션을 분류하는 다른 속성과 같은 필드는 어떻습니까? 이것들이 쿼리 매개 변수가되어야한다면, 경로 매개 변수를 언제 사용 해야하는지 아는 규칙은 무엇입니까?


1
비슷한 질문이 여기에 대답됩니다 ... stackoverflow.com/questions/3198492/…
Lalit Mehra

답변:


239

RESTful API 설계의 모범 사례는 경로 매개 변수를 사용하여 특정 자원을 식별하고 쿼리 매개 변수를 사용하여 해당 자원을 정렬 / 필터링하는 것입니다.

다음은 예입니다. Car라는 엔티티에 RESTful API 엔드 포인트를 구현한다고 가정하십시오. 엔드 포인트를 다음과 같이 구성하십시오.

GET /cars
GET /cars/:id
POST가 /cars
PUT /cars/:id
DELETE/cars/:id

이렇게하면 가져올 리소스를 지정할 때 경로 매개 변수 만 사용하지만 어떤 식 으로든 리소스를 정렬 / 필터링하지는 않습니다.

이제 GET 요청에서 자동차를 색상별로 필터링하는 기능을 추가하려고한다고 가정하십시오. 색상은 리소스가 아니므로 (리소스의 속성)이를 수행하는 쿼리 매개 변수를 추가 할 수 있습니다. 다음 과 같이 해당 검색어 매개 변수를 GET/cars 요청에 추가합니다 .

가져 오기 /cars?color=blue

이 엔드 포인트는 파란색 자동차 만 반환되도록 구현됩니다.

구문과 관련하여 URL 이름은 모두 소문자 여야합니다. 일반적으로 영어로 두 단어로 된 엔티티 이름이 있으면 낙타 대소 문자가 아닌 하이픈을 사용하여 단어를 구분합니다.

전의. /two-words


3
답변 해 주셔서 감사합니다. Mike. 이것은 명확하고 간단한 방법입니다. 나에게서 최대 투표 가치가 있습니다. 아직도, 개발자들은 종종 'cars / blue'접근 방식을 선택하는데, 그들의 추론이 무엇인지 궁금합니다. 아마도 그들은 필수 필드에 대한 경로 매개 변수를 만들거나 아마도 그것을 지시하기 위해 할 것입니다 데이터베이스는 해당 샤드에 의해 파티션됩니다.
cosbor11

1
그들의 추론이 무엇인지 잘 모르겠습니다. 솔직히, 나는 그것에 동의하지 않습니다. 다음 규칙을 따르고 단순하게 유지하는 것이 가장 합리적이라고 생각합니다. 이렇게하면 API 소비자가 기능에 액세스하기 위해 수행해야하는 작업을 정확하게 이해할 수 있습니다.
Mike

3
cars / 1 /? color = blue 대신 / cars? id = 1 & color = blue는 어떻습니까? 각 시나리오에서 기본적으로 자동차 리소스를 필터링하고 있습니다
mko

1
id 1의 자동차는 하나만 존재하지만 파란색이 많은 자동차는 여러 개일 수 있으므로 잘못되었습니다. 아이덴티티와 필터의 차이점이 있습니다.
paul

1
왜 경로 매개 변수를 사용하는 것이 널리 퍼져 있는지에 대한 나의 가설은 많은 개발자들이 REST 원칙 (특히 Ruby on Rails)을 잘 이해하지 못하는 사람들이 디자인 한 프레임 워크에서 배웠기 때문입니다.
Chris Broski

58

이 주제에 대해 생각하는 기본 방법은 다음과 같습니다.

URI는 리소스 TYPE의 특정 인스턴스를 고유하게 식별하는 리소스 식별자입니다. 인생의 다른 모든 것들과 마찬가지로, 모든 객체 (일부 유형의 인스턴스)는 시간에 따라 변하거나 일시적인 속성 집합을 갖습니다.

위의 예에서 자동차는 절대 변하지 않는 제조사, 모델 및 VIN과 같은 속성과 시간에 따라 변할 수있는 색상, 서스펜션 등을 갖는 매우 실질적인 객체입니다. 따라서 시간이 지남에 따라 변경 될 수있는 속성 (일시적)으로 URI를 인코딩하면 동일한 객체에 대해 여러 개의 URI가 생길 수 있습니다.

GET /cars/honda/civic/coupe/{vin}/{color=red}

그리고 몇 년 후,이 자동차의 색상이 검은 색으로 바뀌면 :

GET /cars/honda/civic/coupe/{vin}/{color=black}

자동차 인스턴스 자체 (객체)는 변경되지 않았습니다. 변경된 색상 일뿐입니다. 동일한 객체 인스턴스를 가리키는 여러 개의 URI를 사용하면 여러 개의 URI 핸들러를 작성해야합니다. 이는 효율적인 설계가 아니며 당연하지도 않습니다.

따라서 URI는 변경되지 않으며 수명 동안 해당 리소스를 고유하게 계속 식별하는 부분으로 만 구성되어야합니다. 변경 될 수있는 모든 것은 다음과 같이 쿼리 매개 변수를 위해 예약되어야합니다.

GET /cars/honda/civic/coupe/{vin}?color={black}

결론-다형성을 생각하십시오.


2
흥미로운 패러다임 .. 이것은 일반적으로 사용되는 디자인 패턴입니까? 설명서에서이 API를 사용하는 API 또는이 전략을 설명하는 일부 참조를 제공 할 수 있습니까?
cosbor11

1
"URI는 리소스 TYPE의 특정 인스턴스를 고유하게 식별하는 리소스 식별자입니다"라고 쓸 때 "TYPE"을 강조한 방식이 마음에 듭니다. 이것이 중요한 차이점이라고 생각합니다.
jrahhali

15

REST API에서는 예측 가능한 URI에 지나치게 신경을 쓰지 않아야합니다. URI 예측 가능성에 대한 제안은 RESTful 아키텍처에 대한 오해를 암시합니다. 클라이언트는 URI 자체를 구성해야한다고 가정합니다. URI는 실제로 필요하지 않습니다.

그러나 귀하는 진정한 REST API가 아니라 'REST에서 영감을 얻은'API (예 : Google 드라이브 API)를 생성한다고 가정합니다. 이러한 경우 경험의 규칙은 '경로 매개 변수 = 자원 식별'및 '쿼리 매개 변수 = 자원 정렬'입니다. 따라서 질문은 상태 / 지역없이 자원을 고유하게 식별 할 수 있습니까? 그렇다면 쿼리 매개 변수 일 수 있습니다. 아니라면 경로 매개 변수입니다.

HTH.


11
좋은 API는 예측 가능해야합니다. RESTful 또는 기타.
cosbor11

3
나도 그렇게 생각해. 엔드 포인트를 임의로 명명하는 대신 URI가 형성되는 방식에 대한 운율과 이유가 있어야합니다. 문서를 지속적으로 참조하지 않고 API 클라이언트를 직관적으로 작성할 수 있다면 좋은 API를 작성했다고 생각합니다.
cosbor11

2
"문서를 지속적으로 참조하지 않고 API 클라이언트를 직관적으로 작성할 수있는 경우" REST에 대한 이해가 다르다고 생각하는 곳입니다. API 클라이언트는 URL을 '빌드'할 필요가 없습니다. 이전 API 호출의 응답에서이를 선택해야합니다. 웹 사이트를 비유로 가져 가면 ... facebook.com으로 이동 한 다음 이벤트 페이지에 대한 링크를 선택하십시오. 당신은 그것을 입력하지 않은 페이스 북 이벤트 URL이 '예측 가능한'인지 상관하지 않습니다. 당신은 하이퍼 미디어 링크를 통해 도착. REST API에서도 마찬가지입니다. 그래서, URI를 사용하면 (서버)에 의미가 있지만 일 클라이언트 만들기
올리버 McPhee

2
메모를 추가했습니다. 이것은 URI가 이해하기 쉬운 패턴을 따라서는 안된다는 것을 의미하는 것이 아니라 RESTful API의 제약 조건이 아니라는 것을 의미합니다. 이 영역의 가장 큰 문제는 클라이언트가 URL을 직접 만들어야한다고 가정하는 사람들입니다. 존재하지 않아야하는 클라이언트와 서버 사이에 커플 링을 작성하기 때문에 사용해서는 안됩니다. (예 : 서버는 모든 클라이언트 응용 프로그램을 중단하지 않고 URL을 변경할 수 없습니다). REST API에서 서버는 원하는대로 변경할 수 있습니다.
Oliver McPhee

3
" 'path params = resource identification'및 'query params = resource sorting'"단어를 사용하는 경우 +1 이것은 정말로 나를 위해 그것을 정리했습니다.
Doug

3

일단 내가 주된 리소스 인 API를 디자인했다 people. 일반적으로 사용자는 필터링을 요청하여 사용자가 매번 people같은 것을 호출하지 않도록 나중에 나중에 쉽게 추가 할 수 있도록 /people?settlement=urban구현했습니다 . 또한 나중에 사용할 경우 전체 목록 에 액세스 할 수 있습니다. 요컨대, 내 추론은 일반적인 하위 집합에 경로를 추가하는 것이 었습니다/people/urban/people/rural/people

에서 여기 :

일반적인 검색어에 대한 별칭

일반 소비자에게 API 환경을보다 즐겁게하려면 조건 세트를 쉽게 액세스 할 수있는 RESTful 경로로 패키징하는 것이 좋습니다. 예를 들어, 최근에 마감 된 티켓 쿼리는 다음과 같이 패키지 될 수 있습니다.GET /tickets/recently_closed


1

일반적으로 말하자면, 리소스에 명백한 '계층 구조'가있을 때 경로 매개 변수를 사용하는 경향이 있습니다.

/region/state/42

해당 단일 리소스에 상태가있는 경우 다음을 수행 할 수 있습니다.

/region/state/42/status

그러나 'region'이 실제로 노출되는 리소스의 일부가 아닌 경우 아마도 언급 한 것처럼 페이지 매김과 유사한 쿼리 매개 변수 중 하나 일 수 있습니다.


0

세분화는 더 계층 적이며 "예쁜"이지만 제한적일 수 있습니다.

예를 들어, 세 개의 세그먼트가있는 URL이있는 경우 각각 하나는 다른 매개 변수를 전달하여 제조업체, 모델 및 색상을 통해 자동차를 검색합니다.

www.example.com/search/honda/civic/blue

이것은 매우 예쁜 URL이며 최종 사용자가 더 쉽게 기억할 수 있지만 이제는이 구조에 붙어 있습니다. 검색에서 사용자가 모든 파란 차 또는 모든 혼다 시빅을 검색 할 수 있도록하려면? 쿼리 매개 변수는 키 값 쌍을 제공하므로이 문제를 해결합니다. 그래서 당신은 전달할 수 있습니다 :

www.example.com/search?color=blue
www.example.com/search?make=civic

이제 쿼리 코드에서 "color"또는 "make"키를 통해 값을 참조 할 수 있습니다.

더 많은 세그먼트를 사용하여 다음과 같은 종류의 키 값 구조를 만들면이 문제를 해결할 수 있습니다.

www.example.com/search/make/honda/model/civic/color/blue

이해가 되길 바랍니다 ..


-2

URL 예 : /rest/{keyword}

이 URL은 경로 매개 변수의 예입니다. 를 사용하여이 URL 데이터를 얻을 수 있습니다 @PathParam.

URL 예 : /rest?keyword=java&limit=10

이 URL은 쿼리 매개 변수의 예입니다. 를 사용하여이 URL 데이터를 얻을 수 있습니다 @Queryparam.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.