[04/15]REST소개
사용법:
- 플러그인 설정에서 '슬라이드로 보기' 플러그인을 사용하도록 설정합니다.
- 아래의 형식처럼 프리젠테이션할 내용을 작성하세요. '단락제목1'은 슬라이드 1 컷에 해당합니다.
- 상단 툴바의 '확장기능▼ > 슬라이드로 보기'를 누르면, 새 창으로 슬라이드쇼를 볼 수 있습니다.
REST
정지웅
SN인프라팀
차례
- 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 버전)
Comments (0)