Super Kawaii Cute Cat Kaoani
본문 바로가기
🏃‍♀️ 대외활동/Codeit Boost-Node.js

10주차 스터디 웹 API 디자인 [코드잇 부스트 백엔드 스터디 ]

by wonee1 2024. 8. 18.
728x90

 

 

 

REST 살펴보기

 

API 디자인과 REST

 

REST (Representational State Transfer)

🔹표현된 자원의 상태를 주고 받는 방법을 정리한 아키텍처 스타일

🔹  REST API는 REST를 준수하여 만든 API를 말한다

🔹web과 http의 장점을 최대한 활용할 수 있게 된다

 

REST를 잘 준수한 API를 RESTful하다고 한다 (RESTful API)

 

REST 제약 조건

🔹클라이언트 서버

🔹무상태성

🔹캐시

🔹일관화된 인터페이스 → 가장 큰 영향을 주는 제약 조건

🔹계층화된 시스템

🔹주문형 코드

 

 

일관화된 인터페이스

🔹자원에 대한 식별

🔹표현을 통한 자원에 대한 조작

🔹자기 서술적 메세지

🔹하이퍼미디어를 사용한 애플리케이션 상태표현

 

 

REST의 제약조건

 

첫 번째 제약 조건: Client-Server(클라이언트-서버)

  • API를 통해 정보를 교환하는 주체는 클라이언트와 서버 구조를 가져야 한다.
  • 클라이언트와 서버의 분리를 통해 서로 의존하지 않는 구조를 가져야 한다. (관심사의 분리)

두 번째 제약 조건: Stateless(무상태성)

  • 클라이언트는 상태를 저장하지 않는다.
  • 클라이언트의 각 리퀘스트는 서버가 리퀘스트를 이해하는 데에 필요한 모든 정보를 포함해야 한다.

세 번째 제약 조건: Cache(캐시)

  • 데이터 복사본을 임시 저장 위치에 저장하여 보다 빠르게 액세스할 수 있도록 하는 프로세스인 캐싱을 통해 네트워크 효율성을 높인다.
  • 리퀘스트에 대한 리스폰스에 캐시 가능 및 불가능 여부가 들어 있어야 한다.

네 번째 제약 조건: Uniform Interface(일관된 인터페이스)

  • 전체 시스템을 잘 파악할 수 있도록 일관된 인터페이스를 제공해야 한다.
  • 이를 통해 구현체가 서비스와 별도로 독립적으로 진화할 가능성을 얻게 된다. (낮은 결합도)
    • 예를 들어 클라이언트가 업데이트되어도 서버를 함께 업데이트할 필요가 없어진다. (반대의 경우에도 해당)

다섯 번째 제약 조건: Layered System(계층화된 시스템)

  • 클라이언트는 서버에 직접 연결되었는지, 중간 서버를 통해 연결되었는지 알 수 없어야 한다.

여섯 번째 제약 조건: Code on Demand(주문형 코드)

  • 서버에서 보낸 코드를 클라이언트에서 실행할 수 있어야 한다. (e.g. JavaScript)
  • 선택적 제약 조건이며 지키지 않아도 REST에는 문제가 없다.

 

 

URI

 

자원의 식별

→ 접근하고자 하는 자원을 명시하고, 그 자원을 식별할 수 있어야 한다

 

 

 

 

URI

🔹단수,복수, 식별자를 사용한다

 

 

URI 작성 규칙

 

 

명사형 사용

URI는 동작(동사)을 가리키는 대신에, 자원(명사)을 가리켜야 한다. 자원에는 속성이 있듯이, 명사는 동사가 가지지 않는 속성을 가지기 때문이다.

 

Bad ❌

/get-member-list
/create-new-member

Good ✅

/members
/articles

 

 

반환(응답)하는 자원의 종류에 따라 단수형/복수형 사용하기

여러 개의 자원을 반환한다면 복수형, 단 1개의 자원을 반환한다면 단수형을 사용한다.

/members         # 멤버 목록 (복수형)
/members/1       # 멤버 목록 중 (복수형), 1번 멤버 (단수형)
/key             # 1개의 키 (단수형)

 

 

계층 표현을 위하여, 슬래시(/) 사용

자원들 간의 계층 표현을 위해서 슬래시(/)를 사용한다.

/articles
/articles/1
/articles/1/comments
/articles/1/comments/2

 

마지막 슬래시(/) 붙이지 않기

마지막에 붙는 슬래시를 트레일링 슬래시 (Trailing Slash)라고 한다.마지막 슬래시는 REST에서 어떠한 의미도 가지지 않기 때문에 혼동을 줄 수 있다. 따라서 붙이지 않는다.

 

Bad ❌

/articles/1/comments/

Good ✅

/articles/1/comments

 

 

모두 소문자로 작성 & 띄어쓰기는 대시(``) 사용

언더스코어(_) 또는 카멜 케이스(CamelCase)는 가독성을 낮출 수 있기에 사용하지 않는다. 띄어쓰기를 위한 대시(-)와 함께 소문자를 사용한다.

 

Bad ❌

/articles/topVoted
/articles/top_voted

 

Good ✅

/articles/top-voted

 

 

파일 확장자 포함하지 않기

파일 확장자는 특정 파일을 가리키는지, 아니면 자원의 식별자인지 헷갈릴 수 있기에 넣지 않는다. 만약 HTML, JSON과 같은 미디어 타입을 강조하고 싶은 경우, Content-Type 헤더를 사용하여 전달한다.

 

Bad ❌

/articles.html
/members.json

Good ✅

/articles
/members

 

 

목록에 필터가 필요할 경우, 쿼리 문자열을 사용

/articles/1/comments?sort=latest

 

 

 

URI에 동사 사용하지 않기

HTTP 메소드만으로도 충분히 해당 내용을 표현할 수 있기 때문에, URI에 불필요한 동사를 사용하지 않는다.

 

 

Bad ❌

/members/1/delete
/members/2/update

Good ✅

DELETE /members/1
PUT /members/2

 

 

 

HTTP 메소드와 표현

 

HTTP Method

🔹자원을 다루는 행동

 

GET (자원 가져오기)

🔹가져오는 행동이므로 자원은 변화하지 않도록 해야한다

🔹여러 번 리퀘스트를 보내도 같은 리스폰스를 돌려준다

🔹 안전한(safe) 메소드

 

POST(자원 조작하기)

🔹자원에 대해 무언가를 수행하였기에 자원의 변화가 있다

🔹자원 목록에 데이터를 전송하여, 새로운 자원의 생성을 요청한다

 

PUT/PATCH (자원 수정하기)

🔹업데이트의 의미

 

DELETE (자원 삭제하기)

 

HTTP Method

🔹자원을 다루는 행동

 

GET (자원 가져오기)

🔹가져오는 행동이므로 자원은 변화하지 않도록 해야한다

🔹여러 번 리퀘스트를 보내도 같은 리스폰스를 돌려준다

🔹 안전한(safe) 메소드

 

POST(자원 조작하기)

🔹자원에 대해 무언가를 수행하였기에 자원의 변화가 있다

🔹자원 목록에 데이터를 전송하여, 새로운 자원의 생성을 요청한다

 

PUT/PATCH (자원 수정하기)

🔹업데이트의 의미

 

 

DELETE (자원 삭제하기)

 

 

 

 

POST vs PUT vs PATCH

 

 

PUT은 자원의 교체(replace), PATCH는 부분 수정(partial update)을 의미한다

id가 1인 멤버가 다음과 같은 속성을 가지고 있다고 가정한다.

{
    "username": "harry",
    "age": 30

 

PUT

  • 리퀘스트
PUT /members/1

{
    "username": "mike"
}

 

  • 리스폰스
200 OK

{
    "username": "mike",
    "age": null
}

 

☑️ id가 1인 멤버의 자원을 리퀘스트에 포함된 자원으로 교체(replace)하였기 때문에, 리퀘스트로 전달되지 않은 자원의 속성은 비어 있는 상태로 수정되며, 자원의 표현 시 null로 표시한다.

 

 

 

PATCH

  • 리퀘스트
PATCH /members/1

{
    "username": "mike"
}
  • 리스폰스
200 OK

{
    "username": "mike",
    "age": 30
}

 

 

☑️ id가 1인 멤버의 자원을 리퀘스트에 포함된 자원으로 **부분 수정(partial update)**하였기 때문에, 리퀘스트로 전달된 자원의 속성만 반영

 

 

미디어타입과 링크 헤더

 

리퀘스트와 리스폰스는 모두 문자로 주고 받는다

 

자기 서술적 메세지

🔹메세지는 보면 그 의미가 해석되어야한다

(따라서 메세지의 해석 방법을 같이 전달하는 경우가 많다)

 

 

 

Content-type: Media Type(미디어타입)

 

ex) json, html 등

🔹iana에서 미디어타입을 관리한다

 

 

 

HATEOAS

 

 

일관된 인터페이스엔 HATEOAS 제약 조건이 포함되어있다

 

링크 헤더

 

 

리스폰스 바디에 상태 변경을 위한 링크 포함

 

HAL을 사용한다 (JSON, XML등)

→ HAL은 리소스와 링크로 구성된다

 

 

 

캐싱

 

재사용을 위해 데이터를 저장하는 장소 → 캐싱

 

REST에는 캐싱이 가능해야한다는 조건이 있다

 

헤더

🔹캐싱할 자원을 판단

🔹클라이언트와 서버의 자원 정보를 전달

 

Cache-Control : 캐싱 방식

 

Last-Modified: 날짜

🔹데이터가 마지막으로 수정된 날짜를 가리킨다

 

 

 

Last-Modified의 한계

🔹날짜와 시간을 기반으로 하기에, 1초보다 작은 단위의 캐시 관리 불가능

🔹실제 자원의 변경 없이 수정된 시간만 변경된 경우에도 다른 데이로 인식

→ ETag 헤더를 사용하면 이러한 한계를 조금이라도 극복할 수 있다

 

 

ETag

 

 

 

API 버전 명시하기

 

 

추가와 삭제는 쉽게 되지만 변경은 그렇지 않다

 

 

현재 서비스에 영향을 주지 않도록 변경해야한다

→ 작은 변경 사항과 큰 변경사항으로 나눠짐

 

api의 큰 변경 사항

→ 새로운 엔드포인트를 만들어야할 수도 있다

  1. 새로운 엔드포인트 추가
  2. 클라이언트의 사용
  3. 기존 엔드포인트 제거

기존의 가리키는 자원은 같은데 새로운 엔드포인트로 너무 다른 url를 사용할 경우

 

버저닝

🔹웹 api에서의 버저닝은 엔드포인트에 붙인다

 

 

 

페이지네이션

 

🔹여러 자원들을 페이지로 묶어서 전달하는 것

 

728x90