Representational State Transfer Application Programming Interface
웹 통신을 위한 아키텍처 스타일이에요.
협업 생산성과 성능을 동시에 챙길 수 있어요. 간결성과 독립성 그리고 시퀀스 비용을 우선순위로 개발하면 가독성과 확장성이 좋아지고 유지보수하기 편해져요.
특히 HATEOAS를 사용하면 프론트엔드 수정 없이 동적으로 버전 업데이트가 가능해요.
좋은 아키텍처이지만 대신 잃어버리는 단점도 있어요.
자원마다 트랜젝션을 별도로 호출하기 때문에 하나의 웹 페이지에서 호출하는 API수에 비례해서 트렌젝션이 늘어나요.
캐싱으로 어느정도 커버가 가능하지만 분명한 한계가 있어요.
대표적으로 HATEOAS를 사용하면 상태 전이가 쉬운 장점도 있지만 그만큼 response에 들어가는 페이로드도 증가해요.
예를 들어 10개의 엔드포인트를 가진 자원을 10만명이 호출하면 100만개의 주소 값이 트래픽에 들어가요.
실제로 카카오같은 큰 트래픽을 다루는 대기업들은 HATEOAS를 넣지 않고 설계하기도 해요.
유저를 실시간으로 관리해야 할 때 Session을 사용하면 무상태를 위배하게 돼요.
그래서 로그인 인가가 필요한 서비스는 JWT를 사용하게 돼요.
로그인 정보가 담긴 JWT는 일반적으로 재발급 할 때 까지 값이 변경되지 않아요.
결국 서비스 요구사항과 성능 최적화가 우선이에요.
요구사항을 위해서 완벽한 REST API를 포기할 수도 있기에 RESTful API라고도 불러요.
서버와 클라이언트간에 독립성을 가지고 이전 통신을 기억하지 않아요.
예시로 식당 서빙하는 사람을 '서버'로 손님을 '클라이언트'로 비유하면 아래와 같아요.
Stateless (무상태) : 떡볶이 1인분, 순대 1인분 주세요!
Stateful (상태 유지) : 늘 먹던걸로!
명사 > 동사 && 복수표기 > 단수 && 하이픈 > 언더바
outside -> inside
example.com서버의 A번째 방의 B번째 컴퓨터의 C번째 저장소
example.com/rooms/{room_num}/pcs/{pc_num}/repositories/{repo_num}
API를 직관적으로 이해하고 처리할 수 있어야 해요.
JSON 또는 XML로 반환.
이유는 표준 형식으로 플랫폼간 호환성이 좋고 key-value형식으로 가독성이 높아 유지보수에 유리해요.
서버와 사용자가 서로 스트레스를 줄이기 위한 약속이에요.
다음 4가지 조건을 요구 해요.
자원은 고유한 uri로 식별되어야 해요.
다음은 RPG게임에서 아이템A를 다루는 uri 사용 예시에요.
GET /items/a
POST /items/a
PATCH /items/a
DELETE /items/a
GET /get_item_a
POST /item/creat_a
PATCH /convert/a_to_b
DELETE /remove/a
메서드로 자원 조작이 가능해야 해요.
GET /items/a
POST /items/a
PATCH /items/a
DELETE /items/a
POST /items/a/get
GET /items/a/post
GET /items/a/update
POST /items/a/delete
요청과 응답에 충분한 정보가 담겨야 해요. 대표적으로 클라이언트는
json인지 xml인지 html인지 원하는 자원의 타입을 알려줘야 해요.
GET /users/13 HTTP/1.1
Host: example.com
Accept: application/json << 이렇게
서버도 응답에 자원의 타입과 상태코드 등등 자원에 대한 정보를 충분히 제공해요.
자세한 response 예시는 포스트 하단에 "그 외 /HTTP response"를 참고해 주세요.
HTTP/1.1 200 OK
Content-Type: application/json << 이렇게{
"id": 13,
"name": "Jay Jeong",
"email": "Jay13@example.com"
}
처음에 언급한 "HATEOAS"에요. (발음 : https://www.youtube.com/watch?v=8xNQhDR8yRw)
API가 반환하는 JSON값에 가져온 자원으로 무엇을 할 수 있는지 알려줘요.
다음은 '/api/users/13' 요청의 반환 값이에요. "_links"로 묶여 있어요.
{
"user": {
"id": 13,
"name": "Jay Jeong",
"_links": {
"self": {
"href": "/api/users/13"
},
"profile": {
"href": "/api/users/13/profile"
},
"posts": {
"href": "/api/users/13/posts"
}
}
}
}
API는 캐싱이 가능해야 해요.
클라이언트와 서버의 반복 작업을 최소화 하기 위해 사용해요.
주로 Redis같은 메모리 저장소나 304와 412 상태코드를 사용하는 방식이 있어요.
헤더를 사용한 캐싱 방법은 포스트 하단에 "캐싱할 때 사용하는 헤더"를 봐주세요.
계층 구조를 허용 해요.
요청부터 자원까지 도달하는 과정에서 모든 계층은 독립적으로 개발해야 해요.
구체적인 예시로 API를 개발할 때 "웹서버, WAS, ORM, DB"를 확장성을 고려하면서 개발해야 해요.
REST API에 대한 직접적인 내용은 아니지만 응답 방식에 대한 내용이에요.
각 메서드 별로 response가 다르게 표현 돼요.
각 응답을 다음 작업에 사용해도 되고 필요에 맞게 사용하지 않아도 돼요.
HTTP/1.1 200 OK
Content-Type: application/json
{
"user": {
"id": 13,
"name": "Jay Jeong",
"_links": {
"self": {
"href": "/api/users/13"
},
"profile": {
"href": "/api/users/13/profile"
},
"posts": {
"href": "/api/users/13/posts"
}
}
},
"message": "User details processed successfully."
}
HTTP/1.1 201 Created
Content-Type: application/json{
"user": {
"id": 13,
"name": "Jay Jeong",
"_links": {
"self": {
"href": "/api/users/13"
},
"profile": {
"href": "/api/users/13/profile"
},
"posts": {
"href": "/api/users/13/posts"
}
}
},
"message": "User created successfully."
}
삭제의 응답은 response body가 없어요.
PATCH도 업데이트 된 자원 확인이 필요없다면 선택적으로 업데이트의 응답도 204처리 해요.
HTTP/1.1 204 No Content
HTTP/1.1 200 OK
Content-Type: text/plain
Last-Modified: Wed, 09 Feb 2024 14:00:00 GMT << 이렇게Hello, this is the content of example.txt.
Cache-Control: max-age=3600, public << 중간 캐시 서버가 캐싱 해서 다른 클라이언트에게 공유한다.
또는
Cache-Control: max-age=3600, private << 이렇게하면 다른 클라이언트는 새로 받아야 한다.
HTTP/1.1 200 OK
Expires: Wed, 13 Feb 2024 15:30:00 GMT << 이렇게
Content-Length: 27
Content-Type: text/plain;charset=UTF-8
Date: Wed, 13 Feb 2024 14:30:00 GMTThis is a protected resource.
Cache-Control: public, max-age=3600, must-revalidate
GET /example/resource HTTP/1.1
Host: example.com
If-Modified-Since: Mon, 01 Feb 2024 12:00:00 GMT << 이렇게