REST , 데이터와 데이터가 가장 간단하게 대화하는 방식
이 글은 Data Web의 핵심 키워드, '리소스'라는 연재글의 일부입니다.
이 시리즈는 4월 28일부터 매일 오전 8시에 한편씩 발행됩니다. 이번 한 주 동안만큼이라도, Data Web에 대한 즐거운 상상들과 함께 아침을 맞이 해보시는 건 어떨까요? ^_^
[ 일일 차림표 ]
- Data Web의 핵심 키워드, '리소스' - 4월 29일
-
REST , 데이터와 데이터가 가장 간단하게 대화하는 방식 - 4월 30일
- AtomPub , 멋진 웹 애플리케이션을 만들기 위한 약속 - 5월 1일
-
리믹스할 수 있는 웹, 변화의 증거들 그리고 기회 - 5월 2일
- Data Web으로 가는 길 - 5월 3일
REST , 데이터와 데이터가 가장 간단하게 대화하는 방식
앞선 글에서, '리소스'라는 단위를 소개해드린바 있는데요. 이 글에서는 그런 리소스를 상세히 기술적으로 다루는 REST라는 흐름에 대해 살펴보겠습니다.
REST는 우리가 이미 사용하고 있는 일반적인 웹 기술(HTTP , URI 등)을 사용해서, 쉽고 간편하게 여러 네트워크간의 통신(소위 분산 컴퓨팅이라고 부르는)을 해보자는 취지에서 만들어진 아키텍쳐 스타일입니다.
주요 데이터들을 URI주소를 통해 외부에 노출하고, 필요하면 HTTP메소드를 통해 직접 주고받으라는 얘기지요. REST는 사실 REpresentational State Transfer라는 외계어같은 명칭의 줄임말입니다. 이 명칭의 의미는 무엇일까요? 잘 설계된 웹 서비스나 웹 애플리케이션은 '마치 리소스들이 요청에 따라 상태변화를 하는 것처럼 이루어진다'라는 취지를 설명하기 위한 것이지요. Resource with Representation 1 -> Request에 의해 -> Resource with Representaion 2로 변경하는 식이 되겠네요.
Rest~ 개발하는 사람, 사용하는 사람 모두, 두발 뻗고 푹 쉴 수 있을만큼 쉽고 간단한 기술
간단한 예 - 커피 자판기
커피 자판기를 예로 들어 보면 어떨까요? 우선 우리가 커피버튼(URI 1)을 누르면(HTTP 요청), 자판기는 요금요청상태로 변화한후에, 요금을 넣는 위치(동전출입구,URI 2)를 알려줍니다. 우리는 그 위치로 500원을 넘겨주고(HTTP요청 2), 자판기는 최종적으로 커피(리소스)를 완성품의 상태(Representaion 2)로 변화시켜 우리에게 전달합니다. 커피는 사실 자판기의 데이터베이스에 분말(Representation 1)의 형태로 존재하고 있었던 것이었구요.
즉, 하나의 서비스를, 결국 서버의 리소스를 다양한 표현으로 얻어오기 위한것으로 바라보게 되면서 사고관이 변화했다고 볼 수 있습니다. 서버에 갖혀있던 데이터들에 URI라는 저마다의 주소를 부여해서 노출하고, 적당히 어떻게 동작할것이라는 상태변화를 정의해두기만 하면 되는것이죠. 개발도 편해지고, 통신도 편해지고 , 무엇보다 갇혀있던 데이터들이 밖에 나오면서, 더 많은 가능성이 생겨납니다.
- 다음 글에 계속 -
더 읽어볼만한 자료들
REST에 대해서 이렇게 짧게만 언급한 이유는, 자세한 이해를 위해서는 다른 자료들을 좀 더 보시는 편이 나을것 같아서입니다.
열린 웹, 열린 플랫폼의 관점에서 REST가 어떤 의미를 가지는지를 살펴본 글입니다
안영회님께서 쓰신 글입니다. 추상적이기만 한, 제 글에 비해 핵심을 잘 짚어주신 것같아 , 일독을 권해드립니다.
REST를 XML웹서비스의 대안기술이라는 관점에서 바라본 짤막한 글입니다.
REST에 대한 짤막한 발표자료
하나 더! ^^
마침 얼마전 사내 스터디에서 REST에 대해 정리했던 내용이 있어, 공유해보려고 합니다. 내용의 대부분은 RESTful Webservices 라는 책의 내용을 발췌,정리한것입니다. 스프링노트 슬라이드 기능을 통해, 프리젠테이션했던 내용이라 단락구성이 좀 두서가 없음을 양해해주세요 ^^;
REST
차례
- REST 소개
- 무엇으로 만들까?
- 어떻게 만들까?
- REST 디자인 패턴
- 내 서비스는 RESTful한가?
REST?
- REST = 네트워크 시스템을 위한 아키텍쳐 "스타일"
-
아키텍쳐 스타일?
- 아키텍쳐적인 constraints 와 restricts를 정의해놓은 일련의 집합
- 스펙이나 규약이 아닌, 따르면 좋은 "스타일" (구현하는 측이 보태거나 뺄 수 있음)
-
HTTP같은 기존의 기술을 이용해, 잘 설계된 웹(분산) 애플리케이션을 만들게끔 하는 설계지침
- vs RPC , XML Webservice
REST와 Resource
-
데이터들을 'Resource'라는 단위로 추상화
- 문서,이미지,서비스,사람,친구관계,컬렉션... 모두 Resource
-
Resource는
- 상태를 가진다 (State)
- 어디서나 참조할 수 있다 (Identifier)
- 정해진 인터페이스를 통해 노출된다 (uniform interface)
REST의 동작
-
Representational State Transfer
- 잘 설계된 웹 애플리케이션은 어떻게 동작하는지에 대한 이미지를 묘사
- 웹 페이지(Resource)들의 네트워크가 존재하고
- 사용자가 링크를 선택하면 상태가 변경되어 (State Change)
- 다음 페이지가 보여진다 (Next State Representation)
REST의 기본원칙
- 모든 것에 ID를 부여하기
- 모든 것을 링크로 연결하기
- 표준 메소드를 사용하기
- 리소스를 다양한 표현으로 나타내기
- 상태를 유지하지 않으며 통신하기
무엇으로 구현할까?
이미 쓰고 있는들을 가지고
- HTTP 1.1
- URI
- MIME
다시 보는 HTTP
HTTP - 앞서 말한 constraints를 다 지킴.
- Stateless , c/s , req/res app protocol
- four main operation (GET , POST ,PUT ,DELETE)
- request는 특정 URI로 (addressability)
- HTTP req/res는 일종의 봉투 역할 (envelope) - header가 resource representation
어떻게 만들까?
- 리소스 찾기
- 포맷 정하기
- 동작 정하기
- 상태 정하기
리소스 찾기
- 명사가 될수 있을만한 것 모두 찾아내기
- 리소스 = 명사.
- 리소스를 기반으로 URI 설계하기
URI 설계 지침
-
계층구조는 URI Path로 표현 (다른 기호는 피하기 ; , )
- /page/1234
-
알고리즘에 필요한 입력은 Query로
- /search?approved=false
-
생각보다 쿼리가 필요 없을수도 있음
- /expense?start=20071031&end=20080103 => /expense/20070131-20080103
URI 설계 지침
- 플랫폼 정보를 흘리지 말기
-
- /expense.php/123
-
URI 템플릿 만들어보기
- /{expense-id}/{line-item}
포맷 정하기
- 다양한 representation 을 가질수 있음 (xml , json ,binary(jpg,mpg)
- well-known media type (MIME)을 사용
- 가능한한 상위 수준의 media type을 사용할것
-
- 분간하기 쉽고, 활용이 극대화
- 예> xml 대신, XHTML , ATOM같이 더 구체적인 타입을
포맷 정하기
-
xhtml 을 적극 고려
- xml 이기때문에 parsing가능.
- class, rel 같은 semantic value
- microformat (extension using class ,re l,rev ) .. rdfa
동작 정하기
HTTP Verb
-
GET
- 가급적 GET을 사용하도록 설계하기
- GET은 안전함 (Safe) 기본적으로 리소스의 상태를 변경하지 않음
- 멱등원 연산(idempotent )임. 여러 request나, single request나 차이가 없음. concurrency
-
PUT
- 특정 URI 의 리소스를 Create / Update
- Not Safe , Idempotent
동작 정하기
-
DELETE
- 리소스 삭제
- Not Safe , Idempotent
-
PUT
- 골칫거리 Not Safe , Not Idempotent
- 요청처리 / 특정 URI 의 하부에 위치한 리소스 생성 / 특정 URI 에 있는 리소스(팩토리 역할)로부터 리소스 생성
상태 정하기
- HTTP가 정의하는 다양한 상태코드를 활용하기
- 1xx Information
- 2xx Success - 200 OK / 204 No Content
- 3xx Redirection
- 4xx Client Error
- 5xx Server Error
REST 디자인 패턴
- Content Negotiation
- Conditional Get
- Caching
- Writable Web
- Asynchronous Operation
- Transaction
- Security
- Redirection
1. Content Negotiation
- 하나의 리소스가 다양한 Representation을 가지도록
-
원래는 Accept Header가 그런 용도이나, 클라이언트들의 지원 미흡
- Accept : text/xml , application/xml
-
Accept Header는 물론, URI에 컨텐츠 타입을 명시하기
- http://a.com/123.xml
- http://a.com/123.json
- ( http://a.com/123/xml 보다는 dot 타입을 선호)
2. Conditional Get
-
리소스가 예전 요청때에 비해 변경되지 않았으면 전송하지 않아도~
- 클라이언트 처리 , bandwidth , 그리고 서버 처리를 경감
- Last-Modified
-
Etag
- ETag "UID" / If-None-Match "UID"
- 304 Not Modified로 서버가 알려줌
- 항상 지원하는 것이 좋음. Last-Modified , Etag 둘 다 지원하는것이 좋음
- Deep Etags : 애플리케이션 차원에서 지원할것 (e.g 데이터베이스 컬럼에 timestamp 컬럼)
3. Caching
- (non-SSL) GET 만이 캐싱될 수 있다 (POST등은 안됨)
-
캐시의 종류
- Browser (user agent)
- Proxy
- 애플리케이션 차원에서 캐싱이 어떻게 동작하고 제어되는지 알필요가 있음
- Cache-Control Header
- Validation은 Conditional GET을 사용해서 (e.g Cache-Control : max-age=3600 , must-revalidate)
3. Caching
|
Header |
Property |
|
Expires |
HTTP date.Hold till expiry |
|
Cache-Control: max-age |
Seconds.Hold for this amount of time |
|
Cache-Control: s-maxage |
Seconds.As above, but proxies only |
|
Cache-Control: public |
Cacheable even if authN required |
|
Cache-Control: no-cache |
Cacheable, but cache must validate freshness |
|
Cache-Control: no-store |
Don’t cache |
|
Cache-Control: must-revalidate |
Do not allow stale representations |
|
Cache-Control: proxy-revalidate |
As above, but proxies only |
4. Writable Web
- 각 Verb(HTTP 메서드)의 특성을 잘 알고 사용하기
-
리소스 생성시
- 서버가 uri 을 결정하는 경우엔 POST
- 클라이언트가 uri를 결정하는 경우엔 PUT
- 요청 처리 (Process This) - 주로 POST를 사용하나..
-
리소스를 가져올때 GET을 사용할수 없는 구조라면(POST를 사용하는 등), 설계를 다시 한번 생각해볼것
4. Writable Web
-
PUT , DELETE는 지원하지 않는 Client,Server,Middleware가 있으므로 POST를 사용해서 흉내
- POST /123/abc/2?method=delete
|
URI |
Method |
Business Operation |
Return Codes |
|
/users/{uname}/expenses |
POST |
Create new expense header |
201 Created 400 Bad Request 409 Conflict 404 (User) not found 415 Unsupported media type 405 Method not allowed |
|
/users/bill/expenses/123 |
POST PUT DELETE |
Add line items Update expense header Delete expense header and line items |
201 400, 409, 404, 415
|
|
/users/bill/expenses/123/line_items/2 |
PUT DELETE |
Update line item Delete line item |
204 No Content 400, 409, 404, 415, 405 |
5. Asynchronous Operation
-
e.g 처리는 원격에서 이루어지고 (긴 대기시간) 각 Request는 Job Queue에 쌓이는 경우
- Queue를 리소스로 노출
- 202 Accepted 응답을 먼저 주고
- 새 Job Resource를 생성하고, 클라이언트가 해당 주소로 생성 요청을 하게
POST /payment+queue
HTTP 1.1
Host: expenses.example.com
<representation of a payment>
►
202 Accepted
►
Location: /payment+queue/4567
5. Asynchronous Operation
- 처리 상태는 Job Resource에 계속 Polling (GET)해서 알아내도록
GET /payment+queue/4567 HTTP 1.1
Host: expenses.example.com
> 200 OK
> Content-Type: text/plain
> queued payment of $100 to Pete Lacey
(later) > dequeued payment of $100 to Pete Lacey
(later) > Check for $100 paid to Pete Lacey
6. Transaction
-
여러개의 리소스를 Atomically하게 업데이트하기
- 일반적으로 POST를 사용 (Overloaded POST)
- 트랜잭션 리소스의 도입
6. Transaction
POST /transactions/payment (factory resource)
> 201 Created
> Location: /transactions/payment/3094 (transaction resource)
작업1
POST /transactions/payment/3094/payment+queue HTTP 1.1
Host: expenses.example.com
<representation of a payment>
6. Transaction
작업 2
PUT /transactions/payment/3094/expenses/123 HTTP 1.1
Host: expenses.example.com
<representation of a a paid expense>
6. Transaction
롤백을 원하면 DELETE
DELETE /transactions/payment/3094
트랜잭션 Commit
PUT /transactions/payment/3094 HTTP 1.1
Host: expenses.example.com
committed=true
7. Security
- HTTP Basic / SSL이 선호됨
-
그러나, SSL은 그다지 RESTful하지 않음
- 메시지가 캐시서버등의 중간자들에 불투명해짐 (self-descriptiveness 침해)
-
HTTP를 확장한 여러가지 대안들...아직 표준은 없음
- Atom-Authentication , HTTPSec ..
8. Redirection
-
30x 상태코드가 사용됨
- 301 moved Permanently - 리소스 URI를 변경한경우 사용
-
303 See Other
- GET : URI 축약등에 적용하기 좋음 /user/bill/123 -> /bill/123
- POST/PUT/DELETE "요청 성공. 결과를 보기위해서 다른곳으로 redirect"
- 304 Not Modified - Conditional Get
-
307 Tempororay Rediect
- GET 303과 동일
- POST/PUT/DELETE "동작 실패. 다음 주소로 resubmit하시오"
내 서비스는 RESTful할까?
-
Bad Smell
- GET 요청에 상태가 바뀌는가?
- 공개된 URL이 적은가?
- 오퍼레이션(VERB)이 메시지 바디나 URI에 존재하는가?
내 서비스는 RESTful할까?
-
알아둬야 할것들
- 세션 대신 쿠키를 쓸수 도 있다
- representation에는 다른 리소스에 대한 링크를
-
action을 쿼리에서 리소스 path로 한단계 up
-
- 커스텀 헤더가 정말 필요할까?
- 미디어 타입 더 세분화. 가능한한 가장 높은 단계의 타입을 사용할것
관련기술
-
Atom Publising Protocl (AtomPub)
-
WADL
- Interface Description Language for REST (WSDL의 REST 버전)
History
Last edited on 04/28/2008 22:49 by 험블
Comments (0)