RestAPI의 탄생 일화

REST는 Representational State Transfer라는 용어의 약자로서

2000년도에 로이 필딩 (Roy Fielding)의 박사학위 논문에서 최초로 소개되었다

로이 필딩은 HTTP의 주요 저자 중 한 사람으로 그 당시 웹(HTTP) 설계의 우수성에 비해

제대로 사용되어지지 못하는 모습에 안타까워하며 웹의 장점을 최대한 활용할 수 있는

아키텍처로써 REST를 발표했다고 한다

 

Rest의 구성

- 자원(RESOURCE) : URI

- 행위(Verb) : HTTP METHOD

- 표현(Representations)

 

Rest의 특징

유니폼 인터페이스 (Uniform Interface)

Uniform Interface는 URI로 지정한 리소스에 대한 조작을 통일되고 한정적인 인터페이스로

수행하는 아키텍처 스타일을 말한다

 

무상태성 (Stateless)

REST는 무상태성 성격을 갖는다

다시 말해 작업을 위한 상태정보를 따로 저장하고 관리하지 않는다

세션 정보나 쿠키정보를 별도로 저장하고 관리하지 않기 때문에 API 서버는 들어오는 요청만을

단순히 처리하면 된다

때문에 서비스의 자유도가 높아지고 서버에서 불필요한 정보를 관리하지 않음으로써 구현이 단순해진다

 

캐시 가능 (Cacheable)

REST의 가장 큰 특징 중 하나는 HTTP라는 기존 웹표준을 그대로 사용하기 때문에

웹에서 사용하는 기존 인프라를 그대로 활용이 가능하다

따라서 HTTP가 가진 캐싱 기능이 적용 가능하다

HTTP 프로토콜 표준에서 사용하는 Last-Modified태그나 E-Tag를 이용하면 캐싱 구현이 가능하다

 

자체 표현 구조 (Self-descriptiveness)

REST의 또 다른 큰 특징 중 하나는 REST API 메시지만 보고도 이를 쉽게 이해 할 수 있는

자체 표현 구조로 되어 있다는 것이다

 

Client - Server 구조

REST 서버는 API 제공, 클라이언트는 사용자 인증이나 컨텍스트(세션, 로그인 정보)등을

직접 관리하는 구조로 각각의 역할이 확실히 구분되기 때문에

클라이언트와 서버에서 개발해야 할 내용이 명확해지고 서로간 의존성이 줄어들게 된다

 

계층형 구조 (Hierarchical Structure)

REST 서버는 다중 계층으로 구성될 수 있으며 보안, 로드 밸런싱, 암호화 계층을 추가해

구조상의 유연성을 둘 수 있고 PROXY, 게이트웨이 같은 네트워크 기반의 중간매체를 사용할 수 있게 한다

 

RestAPI 작성법

- URI는 정보의 자원을 표현해야 한다
- 자원에 대한 행위는 HTTP Method(GET, POST, PUT, DELETE)로 표현한다

 

HTTP (Hyper Text Transfer Protocol)

인터넷에서 데이터를 주고받을 수 있는 프로토콜(규칙)

서버간 네트워크 통신시 어떠한 형식으로 통신할지에 대해 정해둔 통신규약

 

HTTP Method

GET : 서버로 부터 데이터를 취득 (조회)
POST : 서버에 데이터를 추가, 작성 등 (등록)
PUT : 서버의 데이터를 갱신, 작성 / 리소스의 모든 것을 수정 (수정)
DELETE : 서버의 데이터를 삭제 (삭제)
HEAD : 서버 리소스의 헤더 (메타 데이터의 취득)
OPTIONS : 리소스가 지원하고 있는 메소드의 취득
PATCH : 리소스의 일부분을 수정
CONNECT : 프록시 동작의 터널 접속을 변경

 

멱등성 (Idempotence)

여러번 수행해도 결과가 같다

즉 호출로 인해 데이터가 변형되지 않는다

 

대표 메서드 자세히 알기

GET

GET 메소드는 주로 데이터를 읽거나(Read) 검색(Retrieve)할 때에 사용되는 메소드이다

만약에 GET요청이 성공적으로 이루어진다면 XML이나 JSON과 함께 200 (Ok) HTTP 응답 코드를 리턴한다 에러가 발생하면 주로 404 (Not found) 에러나 400 (Bad request) 에러가 발생한다

 

- HTTP 명세에 의하면 GET 요청은 오로지 데이터를 읽을 때만 사용되고 수정할 때는 사용하지 않는다

- GET 요청은 idempotent 하다

- 같은 요청을 여러 번 하더라도 변함없이 항상 같은 응답을 받을 수 있다

- 데이터를 변경하는 연산에 사용하면 안된다

 

GET /user/1

 

데이터를 조회하는 것이기 때문에 요청시에 Body 값과 Content-Type 가 비워져있다

조회할 데이터에 대한 정보는 URL을 통해서 파라메터를 받고 있는 모습을 볼 수 있다

데이터 조회에 성공한다면 Body 값에 데이터 값을 저장하여 성공 응답을 보낸다

GET은 캐싱이 가능하여 같은 데이터를 한번 더 조회할 경우에 저장한 값을 사용하여 조회 속도가 빨라진다

 

POST

POST 메소드는 주로 새로운 리소스를 생성(create)할 때 사용된다

조금 더 구체적으로 POST는 하위 리소스(부모 리소스의 하위 리소스)들을 생성하는데 사용된다

성공적으로 creation을 완료하면 201 (Created) HTTP 응답을 반환한다

 

- POST 요청은 idempotent 하지 않다

- 같은 POST 요청을 반복해서 했을 때 항상 같은 결과물이 나오는 것을 보장하지 않는다

- 두 개의 같은 POST 요청을 보내면 같은 정보를 담은 두 개의 다른 resource를 반환할 가능성이 높다

 

아래 예시는 JSON을 통해서 작성된 예시이다

POST /user
body : {date : "example"}
Content-Type : "application/json"

 

데이터를 생성하는 것이기 때문에 요청시에 Body 값과 Content-Type 값을 작성해야한다

URL을 통해서 데이터를 받지 않고, Body 값을 통해서 받는다

데이터 조회에 성공한다면 Body 값에 저장한 데이터 값을 저장하여 성공 응답을 보낸다

 

PUT

PUT는 리소스를 생성 / 업데이트하기 위해 서버로 데이터를 보내는 데 사용된다

 

- PUT 요청은 idempotent 합니다

- 동일한 PUT 요청을 여러 번 호출하면 항상 동일한 결과가 생성된다

 

아래 예시는 JSON을 통해서 작성된 예시이다

PUT /user/1
body : {date : "update example"}
Content-Type : "application/json"

 

데이터를 수정하는 것이기 때문에 요청시에 Body 값과 Content-Type 값을 작성해야한다

URL을 통해서 어떠한 데이터를 수정할지 파라메터를 받는다

그리고 수정할 데이터 값을 Body 값을 통해서 받는다

데이터 조회에 성공한다면 Body 값에 저장한 데이터 값을 저장하여 성공 응답을 보낸다

 

DELETE

DELETE 메서드는 지정된 리소스를 삭제한다

 

DELETE /user/1

 

데이터를 삭제하는 것이기 때문에 요청시에 Body 값과 Content-Type 값이 비워져있다

URL을 통해서 어떠한 데이터를 삭제할지 파라메터를 받는다

데이터 삭제에 성공한다면 Body 값 없이 성공 응답만 보내게 된다

 

PUT VS PATCH

PUT

리소스의 모든 것을 업데이트 한다

자원의 전체 교체, 자원 교체시 모든 필드 필요하다

 

만약 전체가 아닌 일부만 전달할 경우 전달한 필드외에

모두 null 또는 초기값으로 처리되니 주의해야한다

 

PATCH

리소스의 일부를 업데이트 한다

자원의 부분 교체, 자원 교체시 일부 필드 필요하다

 

예시 리소스

회원 (member) 1000
이름 (name) 펭귄
나이 (age) 10
성별 (gender) M

 

PUT을 이용하면 바꾸고자 하는 age도 넣고 바꾸지 않을 값도 기존의 값으로 작성하면

문제 없이 바뀌는것을 볼 수 있다

하지만 바꾸고자 하는 age만 작성했을시 나머지 값들은 null 또는 초기값으로 바뀌게 된다

 

  요청 결과
전체 수정 PUT /user/1000
{
    "name" : "펭귄",
    "age" : 20,
    "gender" : "M"
}
PUT /user/1000
{
    "name" : "펭귄",
    "age" : 19,
    "gender" : "M"
}
일부 수정 PUT /user/1000
{
    "age" : 20
}
PUT /user/1000
{
    "name" : null,
    "age" : 20,
    "gender" : null
}

 

이때 바꾸고자 하는 내용만 바꾸기 위해서는 PATCH를 이용하면 된다

 

  요청 결과
일부 수정 PATCH /user/1000
{
    "age" : 20
}
PATCH /user/1000
{
    "name" : "펭귄",
    "age" : 20,
    "gender" : "M"
}