REST API
REST API(Representational State Transfer)
- 자원을 이름(자원의 표현)으로 구분하여 해당 자원의 상태(정보)를 주고 받는 모든것을 의미
- 분산 하이퍼미디어 시스템을 위한 소프트웨어 개발 아키텍쳐의 한 형식
- REST는기본적으로 웹의 기존 기술과 HTTP 프로토콜을 그대로 활용하기 때문에 웹의 장점을 최대한 활용할 수 있는 아키텍쳐 스타일
REST의 개념
- HTTP URI를 통해 자원을 명시하고,
Http Method (POST, GET, PUT, DELETE)
를 통해 해당 자원에 대한 CRUD Operation을 적용하는 것을 의미
- REST는 자원 기반의 구조(Resource Oriented Architecture) 설계의 중심에 Resource가 있고 HTTP Method를 통해 Resource를 처리하도록 설계된 아키텍쳐를 의미
- 웹의 모든 자원에 고유한 ID인 HTTP URI를 부여함
URI와 URL의 차이점
URI
URI는 특정 리소스를 식별하는 통합 자원 식별자(Uniform Resource Identifier)를 의미한다. 웹 기술에서 사용하는 논리적 또는 물리적 리소스를 식별하는 고유한 문자열 시퀀스다.
URL
URL은 흔히 유일 자원 식별자(Uniform Resource Locator) 혹은 웹 주소(Address), 컴퓨터 네트워크 상에서 리소스가 어디있는지 알려주기 위한 규칙이다. URI의 서브셋이기도 하다.
http://www.location.com/index
http://www.location.com/index.html
두 주소는 모두 index.html을 가리키고 있다.
첫번째 주소는 웹 서버의 실제 파일 위치를 나타내는 주소이므로 URI면서 URL이다.
두번째 주소는 실제로 index라는 파일이 웹서버에 존재하지 않으므로 URL은 아니다.
하지만 서버 내부에서 이를 처리하여 index.html을가리키므로 URI라고 볼 수 있다.
URI 구조
scheme:[/[user[:password]@]host[:port]][/path][?query][#fragment]
1. scheme : 사용할 프로토콜을 뜻하며 웹에서는 http
, https
를 사용
2. User와 password: (서버에 있는) 데이터에 접근하기 위한 사용자의 이름과 비밀번호
3. Host와 port: 접근할 대상(서버)의 호스트명과 포트번호
4. Path: 접근할 대상(서버)의 경로에 대한 상세정보
5. Query: 접근할 대상에 전달하는 추가적인 정보 (파라미터)
6. Fragment: 메인 리소스 내에 존재하는 서브 리소스에 접근할 때 이를 식별하기 위한 정보
멀티 플랫폼, 멀티 디바이스 시대에서 단순히 하나의 여러 플랫폼만 지원하면 되었던 예전과 달리, 최근의 서버 프로그램은 여러 웹 브라우저, 그리고 iOS, 안드로이드, PC 등 어떤 앱과의 통신에도 대응 할 수 있어야 한다.
따라서 플랫폼에 맞추어 새로운 서버를 만들지 않고 범용적으로 사용성을 보장하는 서버 디자인이 RESTful API다.
Client Side를 정형화된 플랫폼이 아닌 모바일, PC, 어플리케이션 등 플랫폼에 제약을 두지 않기 때문에 XML
, JSON
과 같은 Client에서 바로 객체로 치환 가능한 형태의 데이터 통신을 지향하게 되면서 Server와 Client의 역할을 분리하게 되었다.
이런 변화를 겪으면서 필요해진 것은 HTTP 표준규약*을 지키면서 API를 만드는 것이다.
REST API를 개발하다보면 HTTP Response 규약을 지키지 않고 본인들이 만들어 낸 JSON 컨벤션으로 응답하는 경우를 볼 수 있는데, 이것은 옳지 않은 개발 방향으로
Client Side가 정형화 되어있지 않은 환경에서 개발 속도를 저하하는 가장 큰 이유는 표준을 지키지 않았기 때문이다.
REST의 구성
- 자원 (Resource) - URL
- 모든 자원에 고유한 ID가 존재하고, 이 자원은 Server에 존재한다.
- 자원을 구별하는 ID는
/orders/order_id/1
과 같은 HTTP URI이다.
- 행위 (Verb) - HTTP Method
- HTTP 프로토콜의 Method를 사용한다.
- HTTP 프로토콜은
GET
, POST
, PUT
, DELETE
와 같은 메서드를 제공한다.
- 표현 (Representation of Resource)
- Client가 자원의 상태(정보)에 대한 조작을 요청하면 Server는 이에 적절한 응답(Representation)을 보낸다.
- REST에서 하나의 자원은 JSON, XML, TEXT, RSS 등 여러 형태의 Representation으로 나타낼 수 있다.
- 현재는 JSON으로 주고 받는 것이 대부분이다.
METHOD | 역할 |
---|
POST | POST를 통해 해당 URI를 요청하면 리소스를 생성 |
GET | GET을 통해 해당 리소스를 조회, 리소스를 조회하고 해당 Document에 대한 자세한 정보를 가져옴 |
PUT | PUT을 통해 해당 리소스를 수정 |
DELETE | DELETE를 통해 리소스를 삭제 |
REST 특징
- 클라이언트/서버 구조
- 클라이언트는 유저와 관련된 처리를, 서버는 REST API를 제공함으로써 각각의 역할이 확실하게 구분되고 일괄적인 인터페이스로 분리되어 작동할 수 있게 함
- REST 서버는 API를 제공하고 비즈니스 로직 처리 및 저장을 책임진다
- 클라이언트는 사용자 인증이나 Context(세션, 로그인 정보) 등을 직접 관리하고 책임진다
- 서로 간 의존성이 줄어든다.
- 무상태성 (Stateless)
- REST는 HTTP의 특성을 이용하기 때문에 무상태성을 가짐
- 서버에서 어떤 작업을 하기 위해 상태 정보를 기억할 필요가 없고 들어온 요청에 대해서만 처리를 해주면 되기 때문에 구현이 쉽고 단순해진다.
- 캐시 처리 가능 (Cacheable)
- HTTP라는 기존 웹 표준을 사용하는 REST의 특징 덕분에 기본 웹에서 사용하는 인프라를 그대로 사용 가능
- 대량의 요청을 효율적으로 처리하기 위해 캐시가 요구됨
- 캐시 사용을 통해 응답시간이 빨라지고 REST Server 트랜잭션이 발생하지 않기 때문에 전체 응답시간, 성능, 서버의 자원 이용률을 향상 시킬 수 있음
- 자체 표현 구조 (Self-Descriptiveness)
- JSON을 이용한 메시지 포맷을 이용하여 직관적으로 이해할 수 있고 REST API 메시지만으로 그 요청이 어떤 행위를 하는지 알 수 있다.
- 계층화 (Layered System)
- 클라이언트와 서버가 분리되어 있기 때문에 중간에 프록시 서버, 암호화 계층 등 중간 매체를 사용할 수 있어 자유도가 높음
- 유니폼 인터페이스 (Uniform)
- Uniform Interface는 HTTP 표준에만 따른다면 모든 플랫폼에서 사용이 가능하며, URI로 지정한 리소스에 대한 조작을 가능하게 하는 아키텍쳐 스타일
- URI로 지정한 Resource에 대한 조작을 통일되고 한정적인 인터페이스로 수행
- 즉, 특정 언어나 기술에 종속되지 않는다
REST에서 가장 중요하고 기본적인 규칙은 두가지다.
- URI는 정보의 자원을 표현해야 한다
- 자원에 대한 행위는 HTTP Method (GET, POST, PUT, DELETE)로 표현한다.
개발 원칙
- 자원을 식별할 수 있어야 한다.
- URL만으로 내가 어떤 자원을 제어하려고 하는지 알 수 있어야 한다.
자원을 제어하기 위해서, 자원의 위치는 물론 자원의 종류까지 알 수 있어야 한다는 의미다.
- Server가 제공하는 정보는 JSON 이나 XML 형태로 HTTP Body에 포함되어 전송시킨다.
- 행위는 명시적이어야 한다.
- REST는 아키텍쳐, 혹은 방법론과 비슷하다. 따라서 이런 방식을 사용해야 한다고 강제적이지 않다. 기존의 웹서비스처럼, GET을 이용해서 UPDATE와 DELETE가 가능하다.
- 다만 REST 아키텍쳐에는 부합하지 않으므로 REST를 따른다고 할 수는 없다.
- 자기 서술적이어야 한다.
- 데이터에 대한 메타정보만 가지고도 어떤 종류의 데이터인지, 데이터를 위해서 어떤 어플리케이션을 실행해야 하는지를 알 수 있어야 한다.
- 즉, 데이터 처리를 위한 정보를 얻기 위해서, 데이터 원본을 읽어야 한다면 자기서술적이지 못하다.
- HATEOAS (Hypermedia as the Engine of Application State)
- 클라이언트 요청에 대해 응답을 할 때, 추가적인 정보를 제공하는 링크를 포함할 수 있어야 한다.
- REST는 독립적으로 컴포넌트들을 손쉽게 연결하기 위한 목적으로도 사용된다. 따라서 다른 컴포넌트들을 유연하게 연결하기 위해선, 느슨한 연결을 만들어줄 것이 필요하다.
- 이때 사용되는 것이 바로 링크다. 서버는 클라이언트 응용 어플리케이션 하이퍼링크를 제공한다.
- 클라이언트는 이 하이퍼링크를 통해서 전체 네트워크와 연결되며 HATEOAS는 서버가 독립적으로 진화할 수 있도록 서버와 서버, 서버와 클라이언트를 분리할 수 있게 한다.
세부 규칙
- 슬래시 구분자(\/)는 계층 관계를 나타내는데 사용한다.
- URI의 마지막 문자로 슬래시(\/)를 포함하지 않는다.
- 즉 URI에 포함되는 모든 글자는 리소스의 유일한 식별자로 사용되어야 하며 URI가 다르다는 것은 리소스가 다르다는 것
- 역으로 리소스가 다르면 URI도 달라져야 한다.
- 하이픈 (-)은 URI 가독성을 높이는데 사용한다.
- 밑줄 (_)은 URI에 사용하지 않는다.
- URI 경로에는 소문자가 적합하다.
- 파일 확장자는 URI에 포함하지 않는다.
- REST API에서는 메시지 바디 내용의 포맷을 나타내기 위한 파일 확장자를 URI에 포함시키지 않는다.
- 대신 Accept Header를 사용한다.
ex) GET: http://restapi.com/orders/2/ Accept: image/jpg
- 리소스 간에 연관 관계가 있는 경우
- /리소스명/리소스ID/관계가 있는 다른 리소스명
ex) GET: /users/2/orders
(일반적으로 소유의 관계를 표현할 때 사용)
예시)
Protocol | URI | |
---|
GET | /movies/:id | ID값으로 영화를 찾음 |
GET | /movies | 영화의 목록을 가져옴 |
POST | /movies | 새 영화를 만듦 |
PUT | /moves | 존재하는 영화를 수정 |
DELETE | /movies | 존재하는 영화를 삭제 |
설계 목표
REST의 핵심 설계 목표는 다음과 같다.
- 컴포넌트 간의 유연한 (쉽게 확장 가능한) 상호 연동성 확보
- 범용 인터페이스
- 각 컴포넌트들의 독립적인 배포
- 지연 감소, 보안 강화, 레거시 시스템을 인캡슐레이션하는 중간 컴포넌트로의 역할
인캡슐레이션
데이터에 헤더가 추가되는 과정.
즉, OS Lv7 → Lv1으로 내려 가는 과정을 뜻하며 간단하게 말하면 PC에서 다른 PC로 데이터를 전송할 때 데이터를 패키지화 하는 과정을 말한다.
- 상호연동성 확보
- 상호연동성은 "서로 상이한 컴포넌트"들을 쉽게 연결할 수 있는 성질을 의미
- 2개 이상의 컴포넌트들을 결합하여 작업을 더 효율적으로 수행하도록 하는데 목적이 있다
- 표준인 HTTP와 URI를 기반으로 한 REST는 직관적이고 사용이 간단하며 어디에서든 동일하게 작동하는 것을 보장할 수 있다.
- 범용 인터페이스
- 상호연동성과 비슷한 개념으로 REST 모델을 위한 HTTP와 URI는 어디서든 사용가능한 범용 인터페이스를 제공한다.
- 따라서 개발자는 비즈니스 로직만 고민하면 된다.
- 각 컴포넌트들의 독립적인 배포
- 각 컴포넌트들과의 독립적인 배포의 의미는 다른 컴포넌트들과 독립적으로 개발할 수 있다는 것을 의미한다.
- 규격에 맞게 개발이 되었다면 다른 컴포넌트가 추가되어도 연동에 걱정할 것이 없다.
- 컴포넌트를 중계하는 역할
- 클라이언트는 엔드 서버에 직접 연결할 필요 없이 서비스를 이용할 수 있다. 그 이유는 REST 서버가 클라이언트와 엔드 서버 중간에서 중계 역할을 할 수 있기 때문이다.
- 중계 서버로 이용하면 로드 밸런싱, 공유 메모리 등을 이용해서 확장성/성능을 향상 시킬 수 있으며 보안 정책을 적용하기도 용이하다.
참조
https://velog.io/@somday/RESTful-API-%EC%9D%B4%EB%9E%80