스파르타의 자바 단기심화 훈련에서 첫 번째 프로젝트를 시작했다.
첫 프로젝트의 리더를 맡았고 첫 번째 날 과제는 API Document, Table Document, ERD 작성, System Architecture를 작성하는 것이었다. 거즘 20시간밖에 남지 않았고 팀원분들은 일정이 있어 요구사항을 전반적으로 혼자 봐야하는 상황이 생겼다.
이 과정에서 내가 튜터님에게 듣고 공부한 것들을 정리해볼텐데 오늘은 Restful API를 어떻게 작성하는가를 실제 현업자 튜터님들에게 들은 내용과 이론 기반으로 정리하려고 한다.
Restful란?
REST(Representational State Transfer)는 클라이언트와 서버 사이에서 HTTP 프로토콜을 활용하여 웹의 장점을 활용할 수 있는 하나의 프로토콜이다.
자원, 행위, 표현을 통해 통신할 수 있고 각각의 표기를 통해 표현이 가능하다.
REST 장점
- HTTP 프로토콜의 인프라를 그대로 사용하므로 별도의 인프라를 구축할 필요가 없다.
- HTTP 프로토콜에 따르는 모든 다른 플랫폼과도 통신이 가능하다.
- REST API 메시지를 통해 의도를 충분히 전달할 수 있으며 쉽게 파악이 가능하다.
- 여러가지 서비스 디자인에서 생길 수 있는 문제를 최소화 할 수 있다.
- 서버와 클라이언트간의 역할을 분명하게 분리할 수 있다.
REST 단점
- 표현에 대한 표준이 회사마다 다를 수 있다. 어떠한 회사는 전부 다 POST로 통신하기도 한다.
- HTTP Method의 종류가 제한적이다. GET , POST, PATCH, PUT, DELETE라는 행위로만 표현이 가능하다.
RESTful API의 필요성
- 여러 클라이언트(웹, 앱, 기타 서비스)와 서버가 효율적으로 통신하기 위한 일관된 인터페이스가 필요하고, 이를 Restful API로 표준화 하였다.
자원
- REST에서 “자원(Resource)“은 서버에서 관리하는 데이터의 개별 항목을 의미하며, 일반적으로 URL을 통해 식별된다.
- 자원은 명사 형태로 표현하는 것이 원칙이다.
- 만약 자원을 통해 기능을 표현하게 된다면 POST 메서드와 함께 동사를 쓸 수 있다.
자원의 예시
자원을 표시할 때
GET https://api.test.com/users -> users와 GET을 통해 유저의 정보를 가져오는 API임을 알 수 있다.
GET https://api.test.com/users/1 -> ID가 1인 사용자를 조회하는 API를 알 수 있다.
기능을 표시할 때
POST https://api.test.com/api/v1/orders/{orderId}/accept -> 마지막이 동사로 끝나고 POST를 통해 주문의 수락하는 API임을 알 수 있다.
행위
아래 메서드를 통해 행위를 표현할 수 있으며, POST,PATCH를 제외하고 모두 멱등성을 가지고 있다.
멱등성이란
첫 번째 수행을 여러번 수행해도 결과를 변경시키지 않는 작업의 기능 또는 속성을 말한다. PATCH,POST를 통해 좋아요 API를 처음 실행시킨경우 좋아요가 1개 올라가지만, 다시 동일한 API를 수행하면 좋아요를 취소하여 1개 내려간상태로 첫 행위와 결과값이 달라지기 때문에 멱등성이 보장되지 않는다고 한다.
- GET
- 자원의 조회시 사용된다.
- POST
- 새로운 자원을 생성하거나 기능의 수행을 표현할 때 사용된다.
- PATCH
- 사용자의 일부 정보를 수정할 때 사용된다.
- 멱등성이 보장되지 않는다.
- /api/v1/orders/{orderId}/quantity -> order의 수량(일부 정보)를 수정한다는 표현
- PUT
- 사용자의 전체 정보를 수정할 때 사용된다.
- /api/v1/orders/{orderId} -> order의 전체 정보를 수정한다는 표현
- DELETE
- 사용자의 자원을 삭제할 때 사용된다.
- /api/v1/orders/{orderId} -> order의 전체 정보를 삭제한다는 표현
위와 같이 PUT과 DELETE의 메서드가 하나만 존재하는 경우 /api/v1/orders/{orderId}
로 주소가 겹쳐도 상관없다. 왜냐하면 각 메서드에 하나씩만 존재하기에 충분히 유추가 가능하기 때문이다. 이는 REST API의 성숙도 모델을 참고하면 더 자세히 알 수 있다.
성숙도는 가장 아래에 설명해두겠다.
하지만 이게 정답은 아니기에 더 자세히 자원을 표시해줘도 된다! 완전 표준화된 규칙은 없기때문이다.
표현
자원의 표현은 클라이언트가 서버로부터 응답받는 데이터의 형식을 말한다. RESTful API에서는 주로 JSON, XML을 사용한다.
하지만 주로 json을 사용하는데 경량 데이터 포맷으로 용량이 작아 전송 속도가 비교적 빠르다는 장점이 있다. 또한 다양한 언어에서 parsing이 가능하다.
{
"id": 1,
"name": "홍길동",
"email": "gildong@example.com"
}
통상적인 규칙
- / 는 계층의 구분을 나타낸다.
- URI의 마지막에는 /을 표시하지 않는다.
- 불가피하게 경로가 길다면 하이폰(-)을 사용하여 표현한다. 언더바(_)는 사용하지 않도록 한다.
- URI는 소문자로만 표현한다.
- 파일확장자는 자원에 표기하지 않는다. 이때는 acceptHeader를 통해 표현할 수 있다.
GET / members/soccer/345/photo HTTP/1.1 Host: restapi.example.com Accept: image/jpg
예시
기본적인 예시 외에 실제 데이터에서 고민했던 자원들을 예시로 들고자 한다.
아래에서 명시하는 API를 보고 어떤 행위와 자원을 표현했는지 한 번 맞춰보기 바란다.
- POST /api/admin/v1/sign-in
- GET /api/v1/restaurants?search={search}&size={size}&sort={sort}&page={page}
- PUT /api/menus/v1/{restaurantsId}/restaraunt/{menuId}
1번은 관리자의 로그인 요청
2번은 매장 검색 조회
3번은 매장의 menu 정보 수정
만약 모두 맞췄다면 합리적인 설계를 통해 자원으로 통신할 준비가 되었다는 것이고, 의미가 모호했다면 다시 API 구성을 고민해봐야 할 것이다.
성숙도 표현에는 여러 단계가 존재한다.
API 성숙도 모델
0 단계 : HTTP 사용
- RPC 형태로 리소스 구분 없이 설계된 HTTP API이다.
- 하나의 endpoint를 사용하고, 전달되는 서로 다른 매개변수를 하나의 엔드포인트에서 여러 동작을 하게 된다.
- 오직 POST만을 사용하여 body에 매개변수를 담는다.
CREATE : POST /api/user
READ : POST /api/user
UPDATE : POST /api/user
DELETE : POST /api/user
1단계 : 개별 리소스의 도입
- 모든 요청을 단일 서비스의 엔드 포인트로 보내는 것이 아니라, 개별적인 리소스와 통신하게 된다.
- 리소스별 고유한 URI를 갖고 있다.
- GET과 POST를 사용하여 통신한다.
- Error시에도 코드 200번과 메시지를 반환한다.
- 헤더에 Content Type과 Cache에 대해 표시하지 않는다.
CREATE : POST /api/users/create
READ : GET /api/users/1
UPDATE : POST /api/users/update
DELETE : POST /api/users/remove/1
2단계 : HTTP 메소드 원칙 준수
- GET, POST, PUT, DELETE를 사용하여 CRUD를 표현한다.
- URI에는 행위가 표시되지 않고 HTTP Method를 통해서 표현한다.
- GET은 멱등성을 보장하며 Cache에 저장된다.
- 현재 가장 많이 쓰이는 방식이다.
CREATE : POST /api/users
READ : GET /api/users/1
UPDATE : PUT /api/users/1
DELETE : DELETE /api/users/1
3단계 : HATEAOS 원칙 준수
이 원칙은 많이 생소한 개념일 텐데 Hypermedia(링크)를 통해서 다음 가능한 행동(action)에 대한 정보를 응답 본문에 넣어주어야 한다.
GET https://api.test.com/board/1
위 API를 통해 board의 1번 글을 조회할 수 있다. 그리고 댓글 달기, 목록으로 돌아가기, 신고하기
등의 행위를 할 수 있다.
HTTP/1.1 200 OK
Content-Type: application/json
{
"result" {
"id": "1",
"title": "멜 너프좀",
"content": "처형에 무적은 너무한거 아니냐",
"_links": {
"self" : {
"href" : "https:/api.test.com/board/1"
},
"comment" : {
"href" : "https:/api.test.com/board/1/comment/1"
},
"list" : {
"href" : "https:/api.test.com/board/"
},
}
}
이렇게 하이퍼링크를 넣어서 해당 API에서 이동할 수 있는 경로를 함께 표시해주는 것이다.
'Spring' 카테고리의 다른 글
[Spring / Swagger] Cors , Fail to Fetch 해결방법 (0) | 2025.01.24 |
---|---|
[Spring / IoC, DI] Ioc Container와 Bean (0) | 2025.01.15 |
[Elastic Search] Elastic Search 개념 (1) | 2024.12.24 |
테스트 코드의 기본 이론 (1) | 2024.11.16 |
[Spring/ 환경변수 설정] 로컬에서 IntelliJ 환경변수 설정하기 (0) | 2024.08.12 |