ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • RESTful API를 살펴보자
    API 2022. 12. 23. 23:08

    프론트엔드 개발자와 백엔드 개발자가 만나는 지점인 API에 대한 이야기를 해보려고한다.

    일반적으로 앱이나 웹 상에서 작동하는 어플리케이션을 개발할 때는 주로 HTTP나 HTTPS 프로토콜을 사용하여 API를 만들게 되는데, 이 API의 정의가 얼마나 직관적이고 명확하냐에 따라 프로젝트의 복잡도가 크게 낮아지게 될 만큼 시스템 설계에 있어서 꽤나 중요한 자리를 차지하고 있다.

    그래서 우리는 일종의 약속을 통해 이 API가 어떤 동작을 수행하는 API인지를 명확하게 정의해야 하며, 이 API 정의 과정에서 우리가 사용할 수 있는 요소들이 바로 HTTP 메소드와 URI(Uniform Resource Identifiers)이다.

     

    GET https://evan.com/users/1

    HTTP API의 엔드포인트는 위와 같이 HTTP 메소드와 URI를 사용하여 이 API가 어떠한 동작을 수행하는 API인지를 표현하게 된다.

     

    REST가 의미하는 것

    REST는 REpresentational State Transfer의 약자이다. 이를 조금 더 유연하게 번역해보자면 표현된 상태라고 할 수 있다. 이때 이야기하는 상태라 함은 서버가 가지고 있는 리소스의 상태를 이야기한다.

     

    우리가 API를 통해 주고 받는 리소스는 어떤 문서일수도 있고, 이미지 또는 단순한 JSON 데이터일 수도 있다. 하지만 사실 우리는 리소스를 직접 주고 받는 것이 아니다. 

     

    한번 간단한 예시를 통해 이 말이 어떤 의미인지 살펴보도록 하자.

    자, 여기 클라이언트가 서버에게 특정 유저의 정보를 받아오는 API 엔드포인트를 통해 요청을 보냈다고 가정해보자.

    GET https://iamserver.com/api/users/2
    Host: iamserver.com
    Accept: application/json

    클라이언트는 이 API 엔드포인트를 사용하여 서버에게 2번 유저의 자원을 요청했고, 서버가 요청을 성공적으로 처리했다면 클라이언트는 서버로부터 대략 이런 느낌의 응답을 받을 수 있다.

    HTTP/1.1 200 OK
    Content-Length: 45
    Content-Type: application/json
    
    {
      id: 2,
      name: 'Evan',
      org: 'Viva Republica',
    }

    서버가 보내준 응답의 바디에는 2번 유저의 데이터가 담겨있다. 일반적으로 우리는 이 상황을 /api/users/2라는 엔드포인트를 통해서 2번 유저 데이터 리소스를 받아왔다고 표현하고는 한다.

     

    그런데…정말로 지금 서버가 보내준 저 JSON 데이터가 리소스 자체일까?

    사실 서버에서 보내준 저 JSON은 리소스 원본이 아니라 데이터베이스에 저장된 2번 유저의 데이터 리소스를 표현한 것에 불과하다. 서버는 클라이언트의 요청을 받고 2번 유저의 정보를 데이터베이스에서 조회한 후 요청의 헤더에 담겨있던 application/json이라는 방식으로 표현하여 응답에 담아준 것이다.

     

    서버가 접근하는 진짜 리소스 원본은 그저 데이터베이스에 담겨있는 하나의 로우이거나 파일에 작성된 데이터일 것이다.

    포인트는 서버가 보내준 저 JSON이 원본 리소스가 아니라는 것

    REST가 이야기하는 Representation State라는 단어는 원본 리소스를 표현한 상태라는 것을 의미한다. 원본 리소스는 데이터베이스에 저장된 하나의 로우로써 존재하지만 클라이언트에게 이걸 그대로 넘겨줄 수는 없으니 서버가 원본 리소스를 읽어와서 적당한 상태로 표현해주는 것이다.

     

    클라이언트는 서버에게 2번 유저의 리소스를 요청하며 요청 헤더의 Accept라는 키에 application/json이라는 값을 담아서 보냈다.

    클라이언트가 서버에게 “2번 유저의 상태를 json으로 표현해줘”라는 요청을 보낸 것이다.

    만약 클라이언트가 application/json이 아닌 application/xml을 담아보냈고, 서버가 XML 포맷의 표현을 지원하도록 작성되어있다면 2번 유저의 리소스는 XML 형태로 표현되어 내려왔을 것이다.

     

    RESTful API

    앞서 이야기했듯이, REST는 결국 리소스를 어떻게 하면 명확하게 표현할 수 있을지에 대한 것에 집중하는 아키텍처 스타일이다. 하지만 우리가 HTTP API를 사용할 때는 단순히 리소스의 표현 상태만으로는 클라이언트가 API를 호출했을 때 서버에서 정확히 어떤 일이 발생하는지 알기가 어렵다.

     

    REST는 단지 리소스가 표현된 상태만을 이야기할 뿐, 어떠한 “행위”에 대해서는 이야기하고 있지 않기 때문이다. 하지만 클라이언트가 서버의 API를 사용할 때 원하는 것은 소스를 생성하거나 삭제하거나 수정하는 등 명백히 어떠한 행위이다.

     

    RESTful API에서는 REST 아키텍처를 통해 표현된 리소스와 더불어 어떠한 행위를 명시할 수 있는 HTTP 메소드와 URI까지 활용하게 되며, 각 요소들이 표현하고 있는 것들은 다음과 같다.

     

    1. 리소스가 어떻게 표현되는지? - REST
    2. 어떤 리소스인지? - URI
    3. 어떤 행위인지? - HTTP 메소드

     

    즉, 이 요소들을 사용하여 명확하게 정의된 API를 사용하는 클라이언트는 굳이 API에 대한 구구절절한 설명이 없이 GET /users/2와 같은 엔드포인트만 보고도 “음, 2번 유저의 정보를 가져오는 API겠군”이라고 추측할 수 있게 되는 것이다.

     

    어떤 자원에 대해 CRUD(Create, Read, Update, Delete) 연산을 수행하기 위해 URI(Resource)로

    GET, POST 등의 방식(Method)을 사용하여 요청을 보내며, 요청을 위한 자원은 특정한 형태(Representation of Resource)로 표현됩니다.

     

    REST의 구성 요소

    1. 자원(Resource) - URI

    • 모든 자원에는 고유한 ID가 존재하고, 이 자원은 Server에 존재합니다.
    • 자원을 구별하는 ID는 '/exgroups/:exgroup_id'와 같은 HTTP URI 입니다.
    • Client는 URI를 이용해 자원을 지정하고 해당 자원의 상태(정보)에 대한 조작을 Server에 요청합니다.

    2. 행위(Verb) - Method

    • HTTP 프로토콜의 Method를 사용합니다.
    • HTTP 프로토콜은 GET, POST, PUT, PATCH, DELETE의 Method를 제공합니다. ( CRUD ) 
      GET Read : 정보 요청, URI가 가진 정보를 검색하기 위해 서버에 요청한다.
      POST Create : 정보 입력, 클라이언트에서 서버로 전달하려는 정보를 보낸다.
      PUT Update : 정보 업데이트, 주로 내용을 갱신하기 위해 사용한다. (데이터 전체를 바꿀 때)
      PATCH Update : 정보 업데이트, 주로 내용을 갱신하기 위해 사용한다. (데이터 일부만 바꿀 때)
      DELETE Delete : 정보 삭제, (안전성 문제로 대부분 서버에서 비활성화한다.)

    3. 표현 ( Representation of Resource )

    • Client와 Server가 데이터를 주고받는 형태로 JSON, XML, TEXT, RSS 등이 있습니다.
    • JSON, XML을 통해 데이터를 주고 받는 것이 일반적입니다.

     

    REST API의 정의

    • REST의 특징을 기반으로 서비스 API를 구현한 것
    • 최근 OpenAPI(누구나 사용할 수 있도록 공개된 API: 구글 맵, 공공 데이터 등), 마이크로 서비스(하나의 큰 어플리케이션을 여러 개의 작은 어플리케이션으로 쪼개어 변경과 조합이 가능하도록 만든 아키텍처) 등을 제공하는 기업 대부분은 REST API를 제공합니다.

    REST API의 특징

    • REST API의 가장 큰 특징은 각 요청이 어떤 동작이나 정보를 위한 것인지를 그 요청의 모습 자체로 추론이 가능한 것 입니다.

    REST API 디자인 가이드

    REST API 설계 시 가장 중요한 항목은 다음의 2가지로 요약합니다.

    • 첫 번째, URI는 정보의 자원을 표현해야 한다.
    • 두 번째, 자원에 대한 행위는 HTTP Method(GET, POST, PUT, PATCH, DELETE)로 표현한다.
      • 행위(Method)는 URI에 포함하지 않는다.

    REST API의 설계 규칙

    1. URI는 명사를 사용한다.(리소스명은 동사가 아닌 명사를 사용해야 한다.)

    1-1. 아래와 같은 동사를 사용하지 말 것

    • /getAllUsers
    • /getUserById
    • /createNewUser
    • /updateUser
    • /deleteUser

    2. 슬래시( / )로 계층 관계를 표현한다.

     

    3. URI 마지막 문자로 슬래시 ( / )를 포함하지 않는다.

     

    4. 밑줄( _ )을 사용하지 않고, 하이픈( - )을 사용한다.

     

    5. URI는 소문자로만 구성한다.

     

    6. HTTP 응답 상태 코드 사용

    - 클라이언트는 해당 요청에 대한 실패, 처리완료 또는 잘못된 요청 등에 대한 피드백을 받아야 한다.

     

    그래서 REST API와 RESTful API의 차이는 뭘까?

    RESTful은 REST의 설계 규칙을 잘 지켜서 설계된 API를 RESTful한 API라고 합니다.

    즉, REST의 원리를 잘 따르는 시스템을 RESTful이란 용어로 지칭됩니다.

     

    RESTful하게 만든 API는 요청을 보내는 주소만으로도 어떤 것을 요청 하는지 파악이 가능합니다.

    예를들어, https://school.com/grade 의 주소는 학교의 학년들을 목록으로 받는 요청일 것입니다.

    {
    "results" : [
        {"idx": 1, "name": "1학년"},
        {"idx": 2, "name": "2학년"},
        {"idx": 3, "name": "3학년"}
        ]
    }

    https://school.com/grade/2 이렇게 idx, 고유번호가 붙는다면, idx가 2인 학년의 정보가 올 겁니다. 

    그리고 https://school.com/grade/2/students 의 students가 붙으면 2반 학생들의 정보를 받아올 수 있습니다.

    {
    "results" : [
        {"idx": 1, "name": "홍길동", "gender": "male"},
        {"idx": 2, "name": "성춘향", "gender": "female"},
        {"idx": 3, "name": "전우치", "gender": "male"},
        {"idx": 4, "name": "나기백", "gender": "male"},
        ...
        ]
    }

    또, https://school.com/grade/2/students/15 라는 idx를 붙이면 그 학생들 중 15의 idx를 가진 학생의 정보가 오겠죠.

    혹은 https://school.com/grade/2/students?gender=male 와 같이 조건을 붙여서 남학생들의 정보만 받아올 수도 있습니다.

    한 페이지당 10명의 데이터를 받아오는 거라면 이런식으로도 표현이 가능합니다.

    https://school.com/grade/2/students?page=2&count=10  

    {
    "results" : [
        {"idx": 11, "name": "신짱구", "gender": "male"},
        {"idx": 12, "name": "김지우", "gender": "female"},
        {"idx": 13, "name": "김화석", "gender": "male"},
        {"idx": 14, "name": "박수쳐", "gender": "male"},
        ...
        ]
    }

     

    이렇게 RESTful API는 이해하기 쉽고 사용하기 쉬운 REST API를 만드는 것을 목적으로.

    만약, 성능이 중요한 상황이라면 굳이 RESTful 한 API를 구현할 필요는 없습니다.


    REST API를 간단히 요약하면

    URI는 정보의 자원만 표현해야 하며, 자원의 행위는 HTTP Method에 명시한다는 것

     

     

     

    728x90

    댓글

Designed by Tistory.