rest api url 설계시 resource를 가져오는 건데, 다중 필터가 필요한 경우 어떻게 해결하나요?

2015-09-17 10:18

제목과 같습니다.

restful 을 지향하며 api 작업중에 있습니다.

처음 이렇게 작업을 하다보니 자주 부딪히는 문제가 있어 여쭙습니다.

예를 들어 회원목록이라는 resource 를 가져와야 하는 경우가 있습니다.

이 회원목록에는 사는 도시, 이름, 성별, 등등 많은 분류가능한 정보가 있습니다.

이 분류가능한 정보들은 또 여러개의 정보를 가질 수 있습니다. (예를 들어 이름에는 김문수, 홍길동, 이둘리, 박둘라 등등 많지요. 도시는 서울, 성남, 용인, 수원, 등등 많구요.)

이러한 분류가능한 정보들에 대해 필터를 적용할 경우 이 때 rest 는 메소드와 url 이 어떻게 설계되는게 옳은지 고민이네요.

분명히 GET 을 써야하는게 옳은데 그렇게 되면 rest spec 상 reqeust body 를 가질 수가 없고...

url 만으로 해결해야하는데.

{ "city" : [seoul, seoung-nam, 'yong-in'], "name" : [munsu, 'kil-dong'] "sex" : male, }

이러한 정보를 url 로 넘길 수 있을지...

그리고 이걸 server side 에서는 어떻게 받는지 고민이네요. (다행히 스프링에서 파라미터 인자로 pathvariable 파라미터 타입을 array 로 지정할 수 있는데, 위와 같이 nested array (?) 로 잡을 수 있을지 모르겠네요...)

사실 위 괄호 안의 고민보다는 이게 옳은 rest 인가도 의문입니다.

같은 고민하시는 분들이 계시거나,

이런 문제를 어떻게 해결하셨었는지 경험이 있으시다면 공유 부탁드립니다.

2개의 의견 from SLiPP

2015-09-17 14:55

rest api 설계할 때 항상 고민이 되는 부분이네.

이런 경우는 get 방식으로 요청하고 query string으로 전달하는 것이 맞지 않을까? rest api라고 해서 query string을 사용하지 말아야 하는 것이 아니라고 생각하는데..

query string 사용하지 않고 매번 다른 url로 처리할 수도 있겠지만 그럼 추가할 url이 너무 많아진다는 단점이 있겠네. 암튼 정답은 없는 영역이지 않을까?

2015-09-22 11:36

GET Parameter로 List 전달하기

요청 형태

http://test.dev/search?name[]=tael&name[]=moon&name[]=slipp&city[]=seoul&city[]=soowon&sex[]=male&sex[]=female

결과

  'name' => 
    array (size=3)
      0 => string 'tael' (length=4)
      1 => string 'moon' (length=4)
      2 => string 'slipp' (length=5)

  'city' => 
    array (size=2)
      0 => string 'seoul' (length=5)
      1 => string 'soowon' (length=6)

  'sex' => 
    array (size=2)
      0 => string 'male' (length=4)
      1 => string 'female' (length=6)

평론

조건이 많아지면 쿼리가 지저분해지는 것은 감안해야 할겁니다. 당연히 GET/POST 모든 형태에서 전달이 가능합니다. 만약 구조적 복잡한 계층을 전달해야 하는 상황이라면 분명 좋은 디자인은 아닐겁니다. 하지만 현실적으로 불가피한 상황이 있다면 아래와 같은 형태로 하나의 파라미터로 인코딩/디코딩 해서 사용합니다. 이러한 형태는 코드상에서 추가로 인코딩/디코딩이 있어야 하니 어떠한 형태로의 인코딩/디코딩 인지에 대한 '약속'이 추가로 필요합니다. 프로토콜 안에 프로토콜인 셈이니 디자인적으로 좋지 않은 것이고, REST 의 기본 철학도 있는 기능이나 잘쓰자. 에 가까우니 전혀 맞지 않다고 봅니다. 차라리 WS를 이용해 복잡한 계층을 처리하는 것이 적합한 것일지도 모릅니다.

오브젝트 전달

http://bugatti.dev/test?filterobject={%22name%22:%22tael%22,%22age%22:%227%22,%22friend%22:{%22name%22:%22moon%22,%22age%22:%225%22}}

결과

object(stdClass)[257]
  public 'name' => string 'tael' (length=4)
  public 'age' => string '7' (length=1)
  public 'friend' => 
    object(stdClass)[258]
      public 'name' => string 'moon' (length=4)
      public 'age' => string '5' (length=1)

참고

https://datatracker.ietf.org/doc/rfc6570/?include_text=1

의견 추가하기

연관태그

← 목록으로