sungyup's.

Web_Miscellaneous / 기초 개념 / 1.5 REST API

1.5REST API

REST API의 뜻

TL;DR

추억의 쪽지 시험

들어가며

REST API라는 용어는 개인적으로 참 자주 접하면서도, 개념을 들을때마다 '아, 우리가 맨날 쓰는 GET, POST 말하는거 아니야?'라면서 넘어가지만 '그래서 그게 뭔데?'라고 물어보면 정확히 뭐라고 설명하기가 참 어려웠던 개념이었다.

한번 이번 기회에 확실히 정리해보자.

REST와 REST API

RESTREpresentational State Transfer의 약자로, 2000년대 초반 Roy Fielding의 박사 논문에서 제안된 아키텍처 스타일이다.

그가 제안한 REST는 웹의 핵심적인 특징들을 따르면서 자원(Resource) 중심으로 API를 설계하자는 철학이다. 로이 필딩이 여기서 말하는 웹의 핵심적 특징들은 아래와 같다:

  • 클라이언트-서버 구조
  • 무상태(Stateless)
  • 캐시 처리 가능
  • 계층화 구조

REST API는 위의 REST 원칙을 따르는 API를 의미한다. 간단하게 한 줄로 표현하자면 웹사이트의 이미지, 텍스트, DB 내용 등 자원에 각각 URI를 부여해 구분하고, 이 자원들의 상태를 클라이언트가 원하는 방식으로 표현한 데이터GET, POST, DELETE 등의 HTTP 메소드로 주고 받는 방식을 의미한다.

각 요소를 보다 구체적으로 살펴보자.

1. 자원 중심

자원(Resource)은 API에서 다루는 대상으로, 예를 들면 사용자, 게시글, 댓글 등이다. 각 자원은 URI(Uniform Resource Identifier)로 표현된다.

HTTP
GET /users/1 POST /articles DELETE /comments/22

이는 기존의 다른 방식들과의 차별점인데, 예를 들어 RPC(Remote Procedure Call) 방식은 함수를 서버에서 원격 호출하듯 사용했기에, 뭘 받고 보내려는지를 표현하는 대신, 어떤 함수를 어떤 파라미터와 실행해야 하는지를 표현했다. 즉, 클라이언트에선 함수 이름과 파라미터를 보내면 서버는 함수를 실행해 결과를 돌려줬다.

HTTP
POST /getUser?id=1

RPC에서 URI는 자원이 아닌 함수명을 표현한다. 다시 말해, "뭘" 받고 보내려는지의 자원이 중심이 아니라 "어떤 행위를" 해야하는지의 행위가 중심이 된다.

이러면 아래의 문제들이 생긴다:

  • 클라이언트와 서버 간의 결합도가 높다. 즉, 서버에서 함수 이름이 바뀌면 클라이언트도 바꿔야 한다.
  • HTTP 메소드의 의미가 무시되고 늘 POST만 쓰인다. 이는 복잡한 인자를 전달할 때 POST는 본문에 JSON 등 복잡한 구조도 전달할 수 있지만 GET은 데이터의 URL만 쿼리스트링에 전달할 수 있기 때문이다.

다양한 표현 형식(REpresentational)

REST는 자원 중심이긴 하지만, 자원을 직접 주고 받는게 아니라 자원의 상태를 표현한 것(Representation)을 주고 받는다.

HTTP
GET /users/1 Accpet: application/json Accept: text/html

클라이언트는 Accept 헤더를 통해 원하는 형식을 지정할 수 있고, 서버는 클라이언트의 요청에 따라 JSON, XML, HTML 등으로 응답할 수 있다.

REST는 단순한 JSON API가 아니라, 표현을 유연하게 정의하는 아키텍처 스타일이고, 이에 REpresentational이라는 표현을 쓴다. 'Representation'은 자원의 상태를 전달하는 표현 형식 전반을 의미하고, REST는 이 표현을 전송(Transfer)하는 아키텍처인 것이다.

2. 행위를 HTTP 메소드로 표현

REST는 행위를 URI에 담지 않고, HTTP 메소드를 통해 자원을 조작한다.

HTTP Method기능
GET조회(Read)
POST생성(Create)
PUT전체 수정(Update)
PATCH부분 수정(Update)
DELETE삭제(Delete)

3. 무상태(Stateless)

HTTP 프로토콜은 Stateless Protocol로, 무상태성이라는 특징이자 제약 조건이 있다. 즉, 서버쪽에선 클라이언트의 이전 요청 상태를 기억하지 않고 각각의 요청을 별개로 인식하고 처리한다. 서버는 해당 요청만 보고서도 처리할 수 있어야 한다.

HTTP
GET /orders/1001 Authorization: Bearer <access_token>

서버는 이 요청만 보고도 1001번 주문이 누구 것인지 확인하고, 권한을 확인하고 응답할 수 있어야 한다.

이 방법은 장/단점이 있다:

  • 장점1: 서버 구현이 단순해진다.
  • 장점2: 서버가 클라이언트 상태를 저장하지 않으므로 확장성이 좋다.
  • 단점1: 매 요청마다 인증 정보 및 필요한 데이터를 같이 보내야 한다.(불필요한 오버헤드)
  • 단점2: 여러 요청이 연결된 복잡한 트랜잭션 처리에 불리하다. 예를 들어, 장바구니처럼 얹고 얹고...하는 상태 변화에 불리하다.

REST에 있는 S가 State잖아?

여기서 잠깐, "무상태? REST의 S가 상태고 자원의 상태를 주고 받는다며?"라고 생각할 수 있다. 무상태성의 상태와 REST의 상태는 다르다.

무상태성의 상태는 클라이언트-서버 간의 관계에서 서버가 클라이언트의 상태를 저장하지 않는다는 맥락에서 나온 단어다.

반면, REST의 상태는 자원의 상태로, 클라이언트가 요청한 자원의 현재 상태를 의미하고 REST API로 전송받는 데이터는 자원의 상태를 표현한 것이다.

javascript
{ "id": 1, "name": "Sungyup", "email": "chickenjuicyham@gmail.com" }

4. 캐시 처리 가능

REST의 제약 중 하나는 응답이 명확해 캐싱이 가능해야 한다는 것이다. 즉, 클라이언트나 중간 서버(프록시, CDN 등)가 데이터를 재사용할 수 있도록 명시해야 한다.

HTTP
Cache-Control: max-age=3600

이런 헤더가 있으면, 클라이언트는 1시간 동안 캐시된 데이터로 응답할 수 있다. 이 때문에 트래픽을 낮추고 성능을 향상 시킬수 있지만, 캐시 타이밍이 어긋나면 최신 데이터가 반영되지 않을 수도 있다.

5. 계층화 구조(Layered System)

클라이언트는 데이터를 실제로 제공하는 서버와 직접 통신할 수도 있고, 중간 계층(프록시, 로드 밸런서, 게이트웨이)을 통해 요청할 수도 있다.

클라이언트는 중간 계층이 존재하더라도 이를 알지 못하고, 관심도 없어야 한다. 이것이 계층화 구조다.