REST API design
REST 구성
- 자원(RESOURCE) - URI
- 행위(Verb) - HTTP METHOD
- 표현(Representations)
REST 특징
Uniform Interface (유니폼 인터페이스)
- URI로 지정된 리소스를 통일되고 한정된 인터페이스로 조작합니다.
Stateless (무상태성)
- REST는 무상태성을 가지며, 상태 정보를 따로 저장하거나 관리하지 않습니다. 세션 정보나 쿠키를 별도로 저장하지 않기 때문에 API 서버는 각 요청을 독립적으로 처리할 수 있습니다. 이는 서비스의 자유도를 높이고 서버의 구현을 단순하게 만듭니다.
Cacheable (캐시 가능)
- REST는 HTTP의 기존 웹 표준을 사용하므로, HTTP의 캐싱 기능을 그대로 활용할 수 있습니다. HTTP 프로토콜에서 사용하는 Last-Modified 태그나 E-Tag를 통해 캐싱을 구현할 수 있습니다.
Self-descriptiveness (자체 표현 구조)
- REST API는 메시지만 보고도 쉽게 이해할 수 있는 자체 표현 구조를 가지고 있습니다.
Client-Server 구조
- REST 구조에서 서버는 API를 제공하고, 클라이언트는 사용자 인증이나 세션 정보를 관리합니다. 이러한 역할 분담으로 인해 클라이언트와 서버의 개발 내용이 명확해지고 상호 의존성이 줄어듭니다.
계층형 구조
- REST 서버는 다중 계층으로 구성될 수 있으며, 보안, 로드 밸런싱, 암호화 계층을 추가하여 구조의 유연성을 높일 수 있습니다. 또한, PROXY나 게이트웨이와 같은 네트워크 기반 중간 매체를 사용할 수 있습니다.
REST 중심 규칙
- 리소스는 URI로 표현합니다.
- 행위는 HTTP Method(GET, POST, PUT, DELETE)로 표현합니다.
리소스 원형
Document (문서)
- 설명: 특정 개체나 리소스를 나타내는 단일 리소스입니다. 문서는 주로 개체의 상세 정보를 포함하며, 개체의 상태나 속성을 나타냅니다.
- 예시: 사용자 프로필, 제품 정보, 블로그 게시글
- URI 예시:
/users/{userId}
,/products/{productId}
,/posts/{postId}
Collection (컬렉션)
- 설명: 관련된 리소스의 집합입니다. 컬렉션은 여러 개체를 포함하며, 새로운 개체를 추가하거나 기존 개체를 나열하는 데 사용됩니다.
- 예시: 사용자 목록, 제품 목록, 게시글 목록
- URI 예시:
/users
,/products
,/posts
Store (스토어)
- 설명: 클라이언트가 서버에 데이터를 저장할 수 있는 리소스입니다. 데이터의 저장과 검색을 관리합니다.
- 예시: 파일 저장소, 이미지 갤러리
- URI 예시:
/files
,/images
Controller (컨트롤러)
- 설명: 프로세스나 작업을 제어하는 리소스입니다. 상태 변경, 작업 실행 등을 관리합니다.
- 예시: 주문 처리, 결제 처리, 이메일 발송
- URI 예시:
/orders/{orderId}/process
,/payments/{paymentId}/execute
,/emails/send
Singleton (싱글톤)
- 설명: 시스템에서 하나만 존재하는 리소스입니다. 특정한 시스템 상태나 설정을 나타냅니다.
- 예시: 시스템 설정, 애플리케이션 상태
- URI 예시:
/config
,/status
URL 설계
-
리소스를 명사로 표현 (동사는 HTTP Method로 표현)
- 설명: URL은 리소스를 나타내야 하므로, 리소스 이름은 항상 명사로 표현해야 합니다.
- 예시:
- 사용자 목록:
/users
- 특정 사용자:
/users/{userId}
- 주문 목록:
/orders
- 특정 주문:
/orders/{orderId}
- 사용자 목록:
-
소문자 사용
- 설명: URL은 대소문자를 구분하기 때문에 일관성을 위해 소문자만 사용합니다.
- 예시:
- 올바른 예:
/users
,/orders
- 잘못된 예:
/Users
,/Orders
- 올바른 예:
-
하이픈(-)을 사용하여 단어 구분 (kebab case)
- 설명: 여러 단어로 이루어진 리소스 이름은 하이픈을 사용하여 구분합니다.
- 예시: 제품 카테고리:
/product-categories
, 사용자 설정:/user-settings
-
슬래시(/)로 계층 구조 표현하며 마지막에 슬래시를 포함하지 않는다.
- 설명: URL 경로는 슬래시를 사용하여 리소스 간의 계층 구조를 나타냅니다.
- 예시:
- 특정 사용자의 주문 목록:
/users/{userId}/orders
- 특정 주문의 아이템:
/orders/{orderId}/items
- 특정 사용자의 주문 목록:
-
HTTP 메서드를 통해 동작 지정
- 설명: 리소스에 대한 동작은 HTTP 메서드(GET, POST, PUT, DELETE)를 사용하여 지정합니다.
- 예시:
- GET
/users
: 사용자 목록 조회 - POST
/users
: 새 사용자 생성 - GET
/users/{userId}
: 특정 사용자 조회 - PUT
/users/{userId}
: 특정 사용자 정보 수정 - DELETE
/users/{userId}
: 특정 사용자 삭제
- GET
-
필터링, 정렬, 페이징에는 쿼리 파라미터 사용
- 설명: 리소스 목록을 필터링, 정렬, 페이징하는 데는 쿼리 파라미터를 사용합니다.
- 예시:
- 필터링:
/users?role=admin
- 정렬:
/users?sort=createdAt
- 페이징:
/users?page=2&pageSize=20
- 필터링:
-
상태를 나타내는 엔드포인트에는 명사를 사용
- 설명: 리소스의 상태를 나타내는 엔드포인트도 명사를 사용합니다.
- 예시:
- 특정 주문의 상태:
/orders/{orderId}/status
- 특정 사용자의 프로필 사진:
/users/{userId}/profile-picture
- 특정 주문의 상태:
-
버전 정보 포함
- 설명: API 버전을 URL에 포함시켜 호환성을 유지합니다.
- 예시:
/v1/users
/v2/users
-
CRUD 작업을 위한 엔드포인트 설계
- 설명: 기본적인 CRUD 작업(Create, Read, Update, Delete)을 위한 엔드포인트는 표준화된 형식을 따릅니다.
- 예시:
- 생성(Create): POST
/users
- 조회(Read): GET
/users
, GET/users/{userId}
- 수정(Update): PUT
/users/{userId}
- 삭제(Delete): DELETE
/users/{userId}
- 생성(Create): POST
-
명확하고 직관적인 엔드포인트
- 설명: 엔드포인트는 명확하고 직관적이어야 하며, 리소스와의 관계가 명확하게 드러나야 합니다.
- 예시:
- 특정 사용자의 특정 주문:
/users/{userId}/orders/{orderId}
- 특정 블로그의 특정 댓글:
/blogs/{blogId}/comments/{commentId}
- 특정 사용자의 특정 주문:
-
콘텐츠 협상 사용
- 설명: 파일 확장자를 URL에 포함하지 않고, 클라이언트가 요청 헤더(Accept)를 통해 원하는 데이터 형식을 지정하도록 합니다.
- 예시:
- JSON 형식 요청:
Accept: application/json
- XML 형식 요청:
Accept: application/xml
- JSON 형식 요청:
-
컨트롤 엔드포인트 사용
- 설명: 특정 작업이나 프로세스를 제어하는 컨트롤 엔드포인트는 동사 또는 동사구를 포함할 수 있습니다.
- 예시:
- 주문 처리 시작: POST
/orders/{orderId}/process
- 사용자의 비밀번호 재설정: POST
/users/{userId}/reset-password
- 이메일 발송: POST
/emails/send
- 주문 처리 시작: POST
-
URI에 API임을 표기
- 설명: API 경로의 시작 부분에 api를 포함시켜, 해당 경로가 API 요청을 위한 것임을 명확히 합니다.
- 예시:
- 사용자 목록:
/api/users
- 특정 사용자:
/api/users/{userId}
- 주문 목록:
/api/orders
- 특정 주문:
/api/orders/{orderId}
- 사용자 목록:
-
Parameter와 Body는 camelCase
- 설명: URL 파라미터와 HTTP 요청 Body의 필드명은 camelCase 표기법을 사용합니다.
- 예시:
{ "firstName": "John", "lastName": "Doe" }
HTTP Header
Request Headers
Content-Type
: HTTP 요청 바디의 내용 타입을 서버에 알려줍니다.Accept
: 클라이언트가 원하는 컨텐츠 타입을 서버에 전달합니다.Authorization
: 클라이언트가 자격 증명 정보를 서버에 전달할 때 사용됩니다.User-Agent
: 클라이언트의 소프트웨어나 브라우저 정보를 서버에 제공합니다.Cookie
: 클라이언트가 서버에 저장된 쿠키 정보를 전송합니다.
Response Headers
Content-Type
: 서버가 클라이언트에게 반환하는 컨텐츠의 타입을 명시합니다.application/json
을 주로 사용합니다.
Cache-Control
: 클라이언트와 프록시 캐시가 응답을 캐싱하는 방법을 제어합니다. 캐싱 시간, 캐시 유효 기간 등을 지정할 수 있습니다.Retry-After
: 클라이언트가 다시 요청을 보낼 수 있는 시간을 나타냅니다. 주로 서버가 과부하 상태일 때 사용됩니다.Location
: 리다이렉션 응답에서 새로운 리소스의 위치를 지정합니다. 클라이언트는 이 헤더의 값을 사용하여 새로운 위치로 이동합니다.Content-Location
: 해당 응답의 본문이 실제로 가져온 리소스의 위치를 나타냅니다.ETag
: 리소스의 엔터티 태그를 클라이언트에게 전달합니다. 클라이언트는 이를 사용하여 캐시 유효성을 검사하고 새로운 리소스를 요청할지 여부를 결정합니다.Set-Cookie
: 서버가 클라이언트에게 새로운 쿠키를 설정할 때 사용됩니다. 클라이언트는 이 쿠키를 다음 요청에 함께 전송합니다.
HTTP Status Code
1xx (정보) - Informational responses
100 Continue
: 서버가 요청의 초기 부분을 받았고, 나머지를 계속 보내도 좋다는 것을 클라이언트에게 알립니다.101 Switching Protocols
: 클라이언트가 HTTP를 통해 웹 소켓 연결을 요청하고, 서버가 웹 소켓 프로토콜로 변경되었음을 알리기 위해 이 상태 코드를 반환할 수 있습니다.
2xx (성공) - Successful responses
200 OK
: 요청이 성공적으로 처리되었습니다.201 Created
: 새로운 리소스가 성공적으로 생성되었습니다.202 Accepted
: 서버가 요청을 처리하기 시작했지만 완료되지 않았음을 의미합니다.203 Non-Authoritative Information
: 신뢰할 수 없는 정보입니다.204 No Content
: 요청은 성공적이었지만 전송할 콘텐츠(body)는 없습니다.205 Reset Content
: 서버가 요청을 성공적으로 처리했으나, 클라이언트에게 새롭게 콘텐츠를 확인하라는 의미합니다.206 Partial Content
: 요청의 일부분(리소스의 일부만을 가져왔음)만 성공하였음을 의미합니다.
3xx (리다이렉션) - Redirection messages
301 Moved Permanently
: 리소스의 URI가 영구적으로 변경되었습니다.302 Found
: 리소스의 URI가 일시적으로 변경되었습니다.303 See Other
: 클라이언트가 요청한 리소스가 다른 위치에 있을 때 사용됩니다. 클라이언트는 새로운 위치로 요청을 다시 보내야 하며, 이때는 GET 메서드를 사용해야 합니다.304 Not Modified
: 클라이언트가 캐시된 버전의 리소스를 요청했으며, 해당 리소스가 수정되지 않았음을 나타냅니다.307/308 Redirect
: 요청된 리소스가 다른 URI로 임시 또는 영구적으로 이동했습니다.
4xx (클라이언트 오류) - Client error responses
400 Bad Request
: 요청이 잘못되어 서버가 이해할 수 없습니다.401 Unauthorized
: 인증이 필요합니다.403 Forbidden
: 권한이 필요합니다.404 Not Found
: 요청한 리소스를 서버에서 찾을 수 없습니다.405 Method Not Allowed
: 요청된 메서드가 해당 리소스에서 허용되지 않습니다.406 Not Acceptable
: 클라이언트가 Accept 헤더를 사용하여 허용 가능한 미디어 타입을 지정하지 않았거나, 서버가 해당 요청에 대한 적절한 표현을 찾을 수 없을 때 사용됩니다.407 Proxy Authentication Required
: 요청된 리소스에 접근하기 위해 프록시 서버에서 사용자 인증이 필요할 때 반환됩니다.408 Request Timeout
: 서버가 클라이언트의 요청을 처리하는 동안 요청 시간 제한이 초과되었을 때 반환됩니다.409 Conflict
: 요청이 리소스 상태와 충돌하여 처리되지 않았습니다.410 Gone
: 요청한 리소스가 영구적으로 삭제되었거나 이동되었으며, 이후로는 사용할 수 없을 때 반환됩니다.411 Length Required
: 서버에서 필요로 하는 Content-Length 헤더 필드가 정의되지 않은 요청이 들어왔기 때문에 서버가 요청을 거절합니다.412 Precondition Failed
: 클라이언트의 헤더에 있는 전제조건은 서버의 전제조건에 적절하지 않습니다.413 Payload Too Large
: 서버가 요청을 처리하기 위한 허용 가능한 크기를 초과했을 때 발생합니다.414 URI Too Long
: URI가 너무 길어서 서버가 요청을 처리하지 못하는 경우에 발생합니다.415 Unsupported Media Type
: 서버는 클라이언트가 전송한 요청 본문의 미디어 타입을 처리할 수 없음을 나타냅니다.416 Range Not Satisfiable
: 클라이언트가 Range 헤더를 사용하여 요청한 범위가 서버에 있는 리소스의 범위를 벗어나거나 서버가 지정된 범위를 만족시키지 못할 때 반환됩니다.417 Expectation Failed
: 클라이언트가 “Expect” 헤더를 사용하여 요청한 기대를 만족시키지 못했을 때 반환됩니다.418 I'm a teapot
: ‘HTCPCP/1.0’ 프로토콜에 대한 장난으로 만들어졌습니다. 이는 “차 주전자가 커피를 내릴 수 없음”을 의미하며, HTTP/1.1에서는 사실상 사용되지 않습니다.421 Misdirected Request
: TLS 연결이 잘못된 호스트로 리디렉션되었을 때 발생할 수 있습니다.422 Unprocessable Entity
: 요청은 잘 만들어졌지만, 문법 오류로 인하여 따를 수 없습니다.423 Locked
: 리소스가 잠겨 있어 요청이 실패했을 때 반환됩니다.424 Failed Dependency
: 요청한 동작이 다른 동작에 의존하며 해당 동작이 실패한 경우에 해당 리소스에서 메서드를 수행할 수 없음을 나타냅니다.426 Upgrade Required
: 보안 상의 이유로 안전하지 않은 프로토콜에서 보다 안전한 프로토콜로 업그레이드할 때 사용됩니다.428 Precondition Required
: 클라이언트가 추가적인 조건을 전달해야 함을 나타냅니다.429 Too Many Requests
: 클라이언트가 일정 시간 동안 너무 많은 요청을 보냈습니다.431 Request Header Fields Too Large
: 클라이언트가 지나치게 큰 헤더를 포함한 경우에 발생합니다.451 Unavailable For Legal Reasons
: 사용자가 요청한 것은 정부에 의해 검열된 웹 페이지와 같은 불법적인 리소스입니다.
5xx (서버 오류) - Server error responses
500 Internal Server Error
: 서버 내부에 오류가 발생하여 요청을 수행할 수 없습니다.501 Not Implemented
: 서버가 요청 방법을 이해하지 못하거나 어떤 리소스를 지원하지 않은 경우입니다.502 Bad Gateway
: 게이트웨이나 프록시 서버가 업스트림 서버에서 유효한 응답을 받지 못했을 때 반환됩니다.503 Service Unavailable
: 서버가 일시적으로 요청을 처리할 준비가 되지 않았습니다.504 Gateway Timeout
: 게이트웨이나 프록시 서버가 일정 시간 내에 업스트림 서버로부터 응답을 받지 못했을 때 반환됩니다.505 HTTP Version Not Supported
: 서버가 클라이언트의 HTTP 프로토콜 버전을 지원하지 않을 때 반환됩니다.506 Variant Also Negotiates
: 클라이언트의 요청에 대해 선택한 리소스가 다른 형태의 리소스와 충돌할 때 반환됩니다.507 Insufficient Storage
: 서버가 요청을 처리하기 위해 필요한 저장 공간이 부족할 때 반환됩니다.508 Loop Detected
: 서버가 요청 처리 중에 무한 루프를 감지했을 때 반환됩니다.510 Not Extended
: 서버가 지원되지 않는 확장 요청을 수신했을 때 반환됩니다.511 Network Authentication Required
: 클라이언트가 네트워크로부터 인증을 받아야 할 때 반환됩니다.