본문 바로가기

프로그래밍/ETC...

RESTful API Service Best Practices

Overview
REST = "REpresentational State Transfer" 네트워크 소프트웨어 아키텍처의 한가지로리소스를 정의하고 리소스에 대한 상태를 전송을 표헌하는 전반적인 방법론으로, HTTP 상에서 별로의 전송 계층 없이 리소스를 다루기위한 간단한 인터페이스를 가진다.
예를 들어 상에서 특정 사용의 주문목록을 조회한다고 했을 , RESTful 다음과 같이 표현될  있다.

[non-RESTful]
/service?userid=1234&action=orderlist
[RESTful]
/users/1234/Oders

위와 같이 URI 만으로 충분히  자체를 서술하고 있으며 기능적 의미가 표현되므로, API 작정시 또는 서비스 구현시 직관성이 뛰어나며리소스에 대한 일관된 주소(표현) 유지보수와 생산성을 동시에 높여준다.

Basic

  1. REST 아키텍처에 적용되는 6가지 제약조건

    REST  창시자인 로이 필드의 논문에 제시된 바에 따르면 다음 6가지 제약조건이 REST 적용된다.
    단일 인터페이스(Uniform Interface)
    무상태(Stateless)

      캐시처리가능(Cacheable)
      Client-Server
      계층화된 시스템
      온디멘드 코드(Code on Demand)

      단일 인터페이스(Uniform interface)
      Client Server 사이의 인터페이스 정의로아키텍처를 상호 비종속적이고독립적으로 구현한다.

      리소스 기반(Resource-Based)

      1. URI  통하여 리소스를 식별하고 요청한다.
      2. 리소스 자체는 클라이언트에 반환되는 결과 문서와는 개념적으로 분리된다.
        1. 서버는 데이터베이스 내부의 자료를 직접 전송하는 대신, 데이터베이스 레코드를 HTML, XML이나 JSON 등의 형식으로 표현한다.


        표현을 통한 리소스 조작(Manipulation of Resources through representations)

        1. 클라이언트가 리소스을 지칭하는 표현을 알고있다면,   것으로 서버상의 리소스를 수정하거나삭제할  있는 충분한 정보를 가진 



          자기서술적 메시지(Self-descriptive Message()

          1. 각각의 메시지는  자체로 해당 메시지를 어떻게 처리해야  지에 대한 충분한 정보를 알려주어야 한다.
            1. 어떤 미디어 파일 타입에 어떤 파서를 사용해야할지 알려주어야 한다.


              어플리케이션의 상태를 표현하는 하이퍼미디어(Hypermedia)

              1. 클라이언트는 Body 또는, query-string 파라미터요청 헤드  요청 URI 통해 상태를 전송한다.
                1. 서비스는 클라이언트에게 상태를 전송할 요청의 Body, response code, response 헤드를 통해 상태를 전송한다.
                  1. 위와 같은 것이 기술적으로 하이퍼미디어(Hypermedia) 한다.
                    1. 또는 하이퍼텍스트에서의 하이퍼링크를 예로 들을  있다.


                    또한 하이퍼미디어는 필요에 따라해당 객체 또는 관련 객체를 참조할 URI링크를 리턴 Body 포함  때도 사용된다.

                     상태(Stateless)

                    1. RESTful에서  상태(Statelessness) 핵심 키로서
                      1.  상태란 말은 요청을 처리하는데 필요한 상태는  요청 자체에 포함되어 있다는 의미
                        1. 서버로 요청할 모든 정보는 클라이언트가 가진다.
                          1. 상태 값은 URI  부분인쿼리-스트링, Body, 혹은 Header 통해전달
                            1. URI 리소스에 대한 식별자
                              1. Body에서 리소스의 상태를 포함한다.
                                1. 서버에서 요청에 대한 적절한 처리를  다음상태 값은 다시 클라이언트에 response Header  status 코드를 통해 전달한다.
                                  1.  서버 컨테이너에서 제공하는Session  비교
                                    1. REST에서는 서버는client  대한 어떠한상태 정보도 가지고있지 않는다.
                                    2. 확장성
                                      1. 서버는 사용자 세센을유지하지 않는다.
                                        1. 부하분산 용이


                                      캐시처리가능(Cacheable)

                                      1. 클라이언트의 response 캐시
                                        1. Response 반드시 명시적으로나암시적으로캐시가능 여부를 정의해야 한다.



                                          Client-Server

                                          1. 관점분리(separation of concerns)
                                            1. 단일 인터페이스는 서버과 클라이언트의 분리
                                              1. 클라이언트는 서버의 데이터 저장소내부 구조로 부터 독립적이므로이식성이 뛰어나다.
                                                1. 반면 서버는 사용자 인터페이스사용자 상태로부터 분리되어 있으므로확장성이 뛰어나다.



                                                  계층화된 시스템

                                                  1. 3 구조
                                                    1. Client  back-end 서버와 직접적으로 통신하지 않고중간 계층이 요청을 중계
                                                      1. 확정성과 부하분산 용이하고보안성 강화


                                                        온디멘드 코드(Code on Demand)(선택적)

                                                        1. 자바 애플릿이나 자바스크립트의 제공을 통해 서버가 클라이언트가 실행시킬 수 있는 로직을 전송하여 기능을 확장시킬 수 있다




                                                          REST API 정의

                                                          1. 동작을 나타내는 HTTP Verbs
                                                            1. GET, POST, PUT, DELETE 통해CURD 행위를 처리


                                                            분별력 있는 리소스 명명

                                                            1. /asp?type=posts&id=23  같은 경로보다는/posts/23  같이 보다 요청이 하고자 하는 바를 보다 명확하게 한다.
                                                            2. 적절한 리소스명은  이름 자체만으로 풍부한설명이 되므로이해력이 된다따라서 서술적이고 사용자 친화적인 명칭을 사용하도록 한다


                                                              XML  JSON

                                                              1. 기본적으로 JSON 지원하고경우에 따라서는JSON  XML 모두 지원하도록 한다.
                                                                1. 확장자 변경함으로써 .xml 에서 .json 으로 쉽게변경할  있게 지원



                                                                  정의(Definitions)

                                                                  1. 멱등성(Idempotence)
                                                                    1. In computer science, the term idempotent is used more comprehensively to describe an operation that will produce the same results if executed once or multiple times.  This may have a different meaning depending on the context in which it is applied. In the case of methods or subroutine calls with side effects, for instance, it means that the modified state remains the same after the first call.

                                                                    코드의 재진입성과 유사한 개념으로, RESTful이란 요청을 여러  호출하더라도동일한 결과를 가져다 주어야 한다.

                                                                    안전성(Safety)

                                                                    1. GET 요청은 안전적이다 메소스는 정보를 조회는 하나결코 서버의 상태를 수정할  없다.
                                                                      1. 따라서, GET  같은 요청은 읽기전용으로 안전하게 처리되어야 한다.


                                                                        HTTP 메소드

                                                                        1. GET
                                                                          1. HTTP 정의상 GET 메소드는 리소스로 부터 정보를 읽는다(수정불가)
                                                                            1. GET 메소드는 정상적으로 처리될경우응답코드 200 함께 XML 이나, JSON 리턴
                                                                            2. )
                                                                              1. GET http://www.example.com/customers/12345
                                                                              2. GET http://www.example.com/customers/12345/orders
                                                                              3. GET http://www.example.com/buckets/sample


                                                                            GET 메소드는 Idempotence

                                                                            PUT

                                                                            1. 리소스를 수정할  사용
                                                                            2. 경우에 따라리소스 ID 서버가 아닌 클라이언트에 의해 지정된 경우 PUS 메소드로 리소스를 생성할  있다.
                                                                              1. , PUT 메소드가 존재하지 않는리소스 ID 가지고 있는 경우라  있음


                                                                              )

                                                                              1. PUT http://www.example.com/customers/12345
                                                                              2. PUT http://www.example.com/customers/12345/orders/98765
                                                                              3. PUT http://www.example.com/buckets/secret_stuff

                                                                                성공시 200 리턴

                                                                                  만약 리소스 생성인 경우 201 리턴

                                                                                  1. 리소스 생성시 Location 헤더에 생성한 리소스ID 반환한다.
                                                                                    1. Location=http://www.example.com/customers/12345


                                                                                    PUT 메소스는 비안전 메소드

                                                                                    POST

                                                                                    1. POST 메소드는 새로운 리소스를 생성할  사용
                                                                                      1. )
                                                                                        1. POST http://www.example.com/customers
                                                                                        2. POST http://www.example.com/customers/12345/order
                                                                                        3. 성공시 201 리턴하고, Location 헤더에 생성한리소스 ID 반환한다.
                                                                                          1. POST 메소드는 SAFE 하지도 않고 Idempotent 하지도 않는다.


                                                                                            PUT/POST 리소스 생성

                                                                                            1. 일반적으로 POST 사용
                                                                                              1. 그러나이미 클라이언트가 생성할 리소스 ID알고 있거나 책임이 있는 경우 PUT 사용한다.


                                                                                                DELETE

                                                                                                1. 리소스 삭제에 사용
                                                                                                  1. )
                                                                                                    1. DELETE http://www.example.com/customers/12345
                                                                                                      1. DELETE http://www.example.com/customers/12345/orders
                                                                                                        1. DELETE http://www.example.com/buckets/sample


                                                                                                        삭제 성공시 200리턴

                                                                                                          실패시 204(NO CONTENT) 반환

                                                                                                            Idempotent 메소드(삭제한 리소스에 대해 다시 삭제 하도라도 동일)이나,
                                                                                                            존재하지 않는 리소스를 삭제시에는 404(NOT FOUND) 반환

                                                                                                            HTTP 메소드 리턴값




                                                                                                            리소스 명명(Resource Naming)

                                                                                                            1. URI 리소스 명명은 좋은 API 만드는데 있어매우 중요
                                                                                                            2. RESTful이란 결국 단순히 URI 집합을 말하여이런URI HTTP 통해 호출하고, JSON 이나, xml 형태로 리소스를 표현한 것이라   있다.


                                                                                                              명사를 사용하여 리소스명을 표현하고동사는 행위(action) 표현한다.

                                                                                                                )

                                                                                                                1. Users of the system.
                                                                                                                  1. Courses in which a student is enrolled.
                                                                                                                    1. A user's timeline of posts.
                                                                                                                    2. The users that follow another user.
                                                                                                                    3. An article about horseback riding.


                                                                                                                      사용자 관점에서 명명
                                                                                                                      Resource URI Examples
                                                                                                                      To insert (create) a new customer in the system, we might use:
                                                                                                                      POST http://www.example.com/customers

                                                                                                                      To read a customer with Customer ID# 33245:
                                                                                                                      GET http://www.example.com/customers/33245
                                                                                                                      The same URI would be used for PUT and DELETE, to update and delete, respectively.

                                                                                                                      Here are proposed URIs for products:
                                                                                                                      POST http://www.example.com/products
                                                                                                                      for creating a new product

                                                                                                                      GET|PUT|DELETE http://www.example.com/products/66432
                                                                                                                      for reading, updating, deleting product 66432, respectively.

                                                                                                                      다음 URI 의미하는 바는 무엇일까?
                                                                                                                      POST http://www.example.com/customers/33245/orders

                                                                                                                      GET http://www.example.com/customers/33245/orders

                                                                                                                      POSThttp://www.example.com/customers/33245/orders/8769/lineitems

                                                                                                                      GEThttp://www.example.com/customers/33245/orders/8769/lineitems/1

                                                                                                                      리소스 명명 안티패턴(Resource Naming Anti-Patterns)

                                                                                                                      1. 적합하지 않는 RESTful 리소스 URI
                                                                                                                        1.  하나의 URI 서비스 인터페이스를 만들어, query-string으로 요청의 동작을 처리하는 경우

                                                                                                                          GET http://api.example.com/services?op=update_customer&id=12345&format=json --> poor

                                                                                                                          사용자 업데이트 URI
                                                                                                                          GET http://api.example.com/update_customer/12345
                                                                                                                          GET http://api.example.com/customers/12345/update

                                                                                                                          복수명칭(Pluralization)

                                                                                                                          1. 리소스 명에 복수를 취할 것인가아니면 단수를 취할 것인가?
                                                                                                                            1. GET http://www.example.com/customer/33245
                                                                                                                              1. GET http://www.example.com/customers/33245


                                                                                                                              리소스는 보통 집합을 나타내므로복수를 사용

                                                                                                                              1. GET http://www.example.com/customers/33245/orders/8769/lineitems/1
                                                                                                                                1. POST http://www.example.com/customers
                                                                                                                                2. GET|PUT|DELETE http://www.example.com/customers/{id}


                                                                                                                                  경우에 따라서복수 개념이 없이  하나의 리소스임이 명확한 경우 단수를 사용

                                                                                                                                  1. GET|PUT|DELETEhttp://www.example.com/configuration
                                                                                                                                    1. 사용자 마다환경 구성 값은  
                                                                                                                                    2. GET|PUT|DELETEhttp://www.example.com/customers/12345/configuration


                                                                                                                                      리턴 문서포맷(Returing Representations)

                                                                                                                                      1. 리턴 문서는 JSON, XML
                                                                                                                                        1. GET http://www.example.com/customers.xml
                                                                                                                                          1. Xml 포맷으로 반환
                                                                                                                                          2. GET http://www.example.com/customers/12345
                                                                                                                                            1. 기본값이 생략된 경우json 포맷사용
                                                                                                                                            2. GET http://www.example.com/customers/12345.json
                                                                                                                                              1. Json 포맷임을 명시
                                                                                                                                              2. 반환 문서 포맷이 지원되지 않을경우 404 오류 리턴



                                                                                                                                              링크 포맷(Link Format) 권장

                                                                                                                                              1. POST http://api.example.com/users


                                                                                                                                                HTTP/1.1 201 CREATED
                                                                                                                                                Status: 201 Connection: close
                                                                                                                                                Content-Type: application/json; charset=utf-8
                                                                                                                                                Location: http://api.example.com/users/12346

                                                                                                                                                GET 요청 
                                                                                                                                                {“data”:[{“user_id”:”42”, “name”:”Bob”, “links”:[{“rel”:”self”, “href”:”http://api.example.com/users/42”}]}, {“user_id”:”22”, “name”:”Frank”, “links”: [{“rel”:”self”, “href”:”http://api.example.com/users/22”}]}, {“user_id”:”125”, “name”: “Sally”, “links”:[{“rel”:”self”, “href”:”http://api.example.com/users/125”}]}]}

                                                                                                                                                {"code":200,"status":"success","data": {"lacksTOS":false,"invalidCredentials":false,"authToken":"4ee683baa2a3332c3c86026d"}}
                                                                                                                                                {"code":401,"status":"error","message":"token is invalid","data":"UnauthorizedException"}

                                                                                                                                                <response> 
                                                                                                                                                <code>200</code> 
                                                                                                                                                <status>success</status> 
                                                                                                                                                <data class="AuthenticationResult">   
                                                                                                                                                <lacksTOS>false</lacksTOS>   
                                                                                                                                                <invalidCredentials>false</invalidCredentials>   
                                                                                                                                                <authToken>1.0|idm|idm|4ee683baa2a3332c3c86026d</authToken>
                                                                                                                                                 </data>
                                                                                                                                                </response>



                                                                                                                                                쿼리필터페이징처리

                                                                                                                                                1. 결과값 제한
                                                                                                                                                  1. Limiting via the Range Header

                                                                                                                                                  HTTP 헤더에 제한값 설정
                                                                                                                                                  Range: items=0-24

                                                                                                                                                  Limiting via Query-String Parameters

                                                                                                                                                  1. GET http://api.example.com/resources?offset=0&limit=25


                                                                                                                                                    Range-Based Responses
                                                                                                                                                     the server should respond with a Content-Range header to indicate how many items are being returned and how many total items exist yet to be retrieved:
                                                                                                                                                    Content-Range: items 0-24/66
                                                                                                                                                    Content-Range: items 40-65/66
                                                                                                                                                    Content-Range: items 40-65/*

                                                                                                                                                    Pagination
                                                                                                                                                    Via query-string parameters, this would be equivalent to:

                                                                                                                                                    GET ...?offset=25&limit=25

                                                                                                                                                    1. Range: items=25-49
                                                                                                                                                    2. Content-Range: 25-49/66 와 동일


                                                                                                                                                      For example, to retrieve up to 20 remarks around a given timestamp:
                                                                                                                                                      GET http://www.example.com/remarks/home_timeline?after=<timestamp>
                                                                                                                                                      Range: items=0-19

                                                                                                                                                      GET http://www.example.com/remarks/home_timeline?before=<timestamp>
                                                                                                                                                      Range: items=0-19

                                                                                                                                                      Equivalently, using query-string parameters:
                                                                                                                                                      GET http://www.example.com/remarks/home_timeline?after=<timestamp>&offset=0&limit=20
                                                                                                                                                      GET http://www.example.com/remarks/home_timeline?before=<timestamp>&offset=0&limit=20

                                                                                                                                                      Filtering

                                                                                                                                                      1. GET http://www.example.com/users?filter="name::todd|city::denver|title::grandpoobah”


                                                                                                                                                        Sorting

                                                                                                                                                        1. GET http://www.example.com/users?sort=last_name|first_name|-hire_date


                                                                                                                                                          Service Versioning

                                                                                                                                                          1. Support Versioning via Content Negotiation

                                                                                                                                                            어플리케이션 수정 또는 요구사항 변경 다양한 이유로 인해버저닝이필요







                                                                                                                                                            버전이 지정되지 않은 경우 기본 버전



                                                                                                                                                            지원되지 않는 버전요청시


                                                                                                                                                             이상 지원되지 않는 버전 요청시


                                                                                                                                                            Date/Time Handling

                                                                                                                                                            1. Date/Time Serialization In Body Content
                                                                                                                                                              1.  ISO 8601 time point format is a good solution, using the fully-enhanced format that includes hours, minutes, seconds and a decimal fraction of seconds (e.g. yyyy-MM-dd'T'HH:mm:ss.SSS'Z'


                                                                                                                                                              https://github.com/tfredrich/DateAdapterJ

                                                                                                                                                                 ISO8601 Timepoints are:

                                                                                                                                                                1. http://momentjs.com/
                                                                                                                                                                2. http://www.datejs.com/


                                                                                                                                                                  보안(Securing Service)

                                                                                                                                                                  1. Securing process





                                                                                                                                                                    인증(Authentication)

                                                                                                                                                                    1. OAuth2 권장
                                                                                                                                                                      1.  http://oauth.net/documentation/spec/.


                                                                                                                                                                      전송 보안(Transport Security)

                                                                                                                                                                      1. 모든 인증에 반드시 SSL사용
                                                                                                                                                                        1. OAuth2 서버 권한처리  access token 인증에 TLS요구
                                                                                                                                                                        2. HTTP HTTPS 사이의 전환은 보안상 취약하므로 항상 TLS 통신 사용


                                                                                                                                                                          권한처리(Authorization)
                                                                                                                                                                          Application Security

                                                                                                                                                                          Caching and Scalability






                                                                                                                                                                          The ETag Header
                                                                                                                                                                          The ETag header is useful for validating the freshness of cached representations
                                                                                                                                                                          The value for the ETag header can be as simple as a hash of the underlying domain object (e.g. Object.hashcode() in Java)

                                                                                                                                                                           It is recommended to return an ETag header for each GET (read) operation

                                                                                                                                                                          '프로그래밍 > ETC...' 카테고리의 다른 글

                                                                                                                                                                          HTTP 서버 응답 코드 (Response Code) 정리  (0) 2018.07.27
                                                                                                                                                                          IaaS, PaaS, SaaS란  (0) 2018.05.23
                                                                                                                                                                          AngularJS React Vue.js  (0) 2018.02.20
                                                                                                                                                                          REST(Representational State Transfer), RESTful 개념  (0) 2018.02.19
                                                                                                                                                                          코딩 테스트 연습할 곳  (0) 2018.01.27