RESTful API: 원리, 디자인 및 최고의 기술
Min-jun Kim
Dev Intern · Leapcell

RESTful API (Representational State Transfer API)는 네트워크 애플리케이션 간의 상호 작용에 사용되는 네트워크 인터페이스 설계 스타일입니다. REST는 표준이나 프로토콜이라기보다는 일련의 아키텍처 원칙과 제약 조건입니다. 웹 서비스가 "RESTful"하다는 것은 REST 원칙을 따르고 효율적이고 안정적이며 확장 가능한 네트워크 서비스를 제공한다는 의미입니다.
RESTful 서비스에서 각 요청은 요청을 처리하는 데 필요한 모든 정보를 포함해야 합니다. 서버는 클라이언트 요청에 대한 상태 정보를 유지하지 않아야 합니다.
RESTful 아키텍처는 여러 계층으로 구성될 수 있으며, 각 계층은 특정 기능을 수행합니다. 이 구조는 더 복잡하고 강력한 애플리케이션 개발을 가능하게 합니다.
URI 디자인
RESTful API 설계에서 URL(Uniform Resource Locator)은 일반적으로 리소스(객체)를 나타내고, HTTP 메서드(예: GET, POST, PUT, DELETE 등)는 이러한 리소스에 대한 작업(동사)을 나타냅니다. 이 설계 스타일은 작업보다는 리소스의 상태와 표현을 강조합니다.
동사 + 객체
RESTful API의 동사는 일반적으로 CRUD 작업에 해당하는 다섯 가지 HTTP 메서드입니다.
- GET: 읽기
- POST: 생성
- PUT: 업데이트
- PATCH: 업데이트 (일반적으로 부분 업데이트용)
- DELETE: 삭제
HTTP 사양에 따르면 동사는 항상 대문자여야 합니다.
객체는 명사여야 함
API를 설계할 때 URL(Uniform Resource Locator)은 일반적으로 HTTP 동사의 객체 역할을 하는 리소스를 나타냅니다. RESTful 설계 원칙에 따르면 URL은 작업이 아닌 명사여야 합니다. 왜냐하면 URL은 작업이 아닌 "리소스" 컬렉션 또는 단일 인스턴스를 나타내기 때문입니다.
잘못된 예:
/getAllCars
/createNewCar
/deleteAllRedCars
이러한 URL에는 동사(예: get, create, delete)가 포함되어 있으며, 이는 리소스 자체보다는 작업을 설명합니다. 이 설계는 RESTful 의미론적 표준을 준수하지 않습니다.
올바른 접근 방식:
URL은 작업보다는 리소스를 설명하는 데 집중해야 합니다. 다음은 규정을 준수하는 URL 설계의 예입니다.
/users
: 사용자 컬렉션을 나타냅니다./users/123
: 특정 ID(123)를 가진 단일 사용자를 나타냅니다.
위의 예에서 /users
와 /users/123
은 모두 명사이며, 사용자 컬렉션과 특정 사용자 리소스를 각각 나타냅니다. 이러한 URL 디자인은 API를 이해하기 쉽게 만들고 RESTful 리소스 중심 원칙에 부합합니다.
이 명명 규칙을 따르면 API 경로가 명확하고 일관되며 이해하고 유지 관리하기 쉬운지 확인할 수 있습니다.
복수 URL
URL에서 복수형을 사용하는 것은 일반적으로 일관성과 명확성을 위해 권장됩니다. 왜냐하면 복수형은 일반적으로 리소스 컬렉션을 나타내기 때문입니다.
URL이 리소스 컬렉션을 가리키는 경우 복수 명사를 사용하십시오. 예를 들어 모든 사용자 컬렉션을 나타내려면 /user
대신 /users
를 사용하십시오.
단일 리소스를 가리키는 경우에도 복수형을 사용하는 것이 좋습니다. 예를 들어 /users/123
은 ID 123을 가진 사용자를 나타냅니다. 이 접근 방식은 URL 일관성을 유지합니다.
리소스에 계층적 관계가 있는 경우 URL은 이 구조를 반영해야 합니다. 예를 들어 /users/123/posts
는 사용자 123의 게시물 컬렉션을 나타낼 수 있습니다.
깊이 중첩된 URL 피하기
일반적인 시나리오는 리소스가 여러 수준의 분류를 필요로 할 때 발생하며, 특정 작성자의 특정 범주 기사를 검색하는 것과 같이 깊이 중첩된 URL로 이어집니다.
GET /authors/12/categories/2
이러한 URL은 확장하기 어렵고 의미 체계가 불분명하여 이해하는 데 추가 노력이 필요한 경우가 많습니다. 더 나은 방법은 첫 번째 수준을 넘어 쿼리 매개변수를 사용하는 것입니다.
GET /authors/12?categories=2
또 다른 예는 게시된 기사를 쿼리하는 것입니다. 다음과 같이 URL을 디자인할 수 있습니다.
GET /articles/published
그러나 쿼리 매개변수를 사용하는 것이 훨씬 더 나은 접근 방식입니다.
GET /articles?published=true
상태 코드
상태 코드는 정확해야 함
모든 클라이언트 요청에 대해 서버는 HTTP 상태 코드와 데이터를 응답해야 합니다.
HTTP 상태 코드는 다섯 가지 범주로 나뉘는 세 자리 숫자입니다.
- 1xx: 정보 제공
- 2xx: 성공
- 3xx: 리디렉션
- 4xx: 클라이언트 오류
- 5xx: 서버 오류
이러한 다섯 가지 범주에는 가능한 대부분의 상황을 다루는 100개 이상의 상태 코드가 포함되어 있습니다. 각 상태 코드에는 표준(또는 관례적으로 허용되는) 의미가 있으므로 클라이언트는 상태 코드를 확인하는 것만으로도 무슨 일이 발생했는지 확인할 수 있습니다. 따라서 서버는 가능한 가장 정확한 상태 코드를 반환해야 합니다.
API는 1xx 상태 코드가 필요하지 않습니다. 아래는 다른 네 가지 범주에 대한 설명입니다.
2xx 상태 코드
서로 다른 HTTP 요청 메서드는 요청 결과를 나타내기 위해 해당 상태 코드를 반환해야 합니다. 200 OK는 일반적인 성공 응답이지만 메서드에 따라 더 정확한 상태 코드를 사용해야 합니다.
- GET: 200 OK – 요청이 성공했고 리소스가 반환되었습니다.
- POST: 201 Created – 새 리소스가 성공적으로 생성되었으며 응답에는 일반적으로 리소스의 URI가 포함됩니다.
- PUT: 200 OK 또는 204 No Content – 전체 리소스 업데이트에 사용됩니다. 콘텐츠가 반환되면 200을 사용하고 그렇지 않으면 204를 사용합니다.
- PATCH: 200 OK 또는 204 No Content – PUT과 유사하게 부분 업데이트에 사용됩니다. 204는 반환된 콘텐츠가 없음을 나타냅니다.
- DELETE: 204 No Content – 리소스가 성공적으로 삭제되었음을 나타내며 일반적으로 응답에 콘텐츠가 없습니다.
- 202 Accepted – 요청이 수락되었지만 아직 처리되지 않았으며 비동기 작업에 유용합니다.
- 206 Partial Content – 부분 응답을 나타내며 일반적으로 클라이언트가 Range 헤더를 사용하여 대용량 파일의 일부를 요청할 때 사용됩니다.
3xx 상태 코드
API는 브라우저 수준 탐색과 관련이 있기 때문에 일반적으로 301 (Permanent Redirect) 또는 **302 (Temporary Redirect, 307 포함)**를 사용하지 않습니다. API는 대신 애플리케이션 수준에서 이러한 시나리오를 처리할 수 있습니다.
그러나 API는 다른 URL을 참조하는 303 See Other를 사용할 수 있습니다. 302 및 307과 마찬가지로 "임시 리디렉션"을 의미하지만 303은 특히 POST, PUT 및 DELETE 요청에 사용됩니다. 302와 달리 브라우저는 303 리디렉션을 자동으로 따르지 않고 대신 사용자에게 다음 단계를 결정하도록 허용합니다.
응답 예시:
HTTP/1.1 303 See Other
Location: /api/orders/12345
4xx 상태 코드
4xx 상태 코드는 클라이언트 오류를 나타냅니다. 일반적인 오류는 다음과 같습니다.
- 400 Bad Request – 서버가 클라이언트의 요청을 이해하지 못하고 처리하지 않습니다.
- 401 Unauthorized – 사용자가 인증 자격 증명을 제공하지 않았거나 인증에 실패했습니다.
- 403 Forbidden – 사용자가 인증에 성공했지만 리소스에 액세스할 권한이 없습니다.
- 404 Not Found – 요청된 리소스가 존재하지 않거나 사용할 수 없습니다.
- 405 Method Not Allowed – 사용자가 인증에 성공했지만 허용되지 않는 HTTP 메서드를 사용하고 있습니다.
- 410 Gone – 요청된 리소스가 영구적으로 제거되었습니다.
- 415 Unsupported Media Type – 요청된 형식이 지원되지 않습니다. 예를 들어 API가 JSON만 반환하지만 클라이언트가 XML을 요청하는 경우 이 상태를 반환해야 합니다.
- 422 Unprocessable Entity – 클라이언트가 처리할 수 없는 첨부 파일을 제공하여 요청이 실패했습니다.
- 429 Too Many Requests – 클라이언트가 허용된 요청 횟수를 초과했습니다.
5xx 상태 코드
5xx 상태 코드는 서버 오류를 나타냅니다. API는 일반적으로 내부 서버 세부 정보를 사용자에게 노출하지 않으므로 두 가지 상태 코드만 일반적으로 사용됩니다.
- 500 Internal Server Error – 클라이언트 요청이 유효했지만 서버가 처리하는 동안 예기치 않은 문제가 발생했습니다.
- 503 Service Unavailable – 서버가 일시적으로 요청을 처리할 수 없으며 유지 관리 기간 동안 자주 사용됩니다.
서버 응답
일반 텍스트를 반환하지 마십시오
API 응답은 일반 텍스트가 아니라 표준 형식을 보장하기 위해 구조화된 JSON 객체여야 합니다. 서버의 Content-Type 헤더는 application/json으로 설정해야 합니다.
클라이언트는 요청에서 Accept 헤더를 설정하여 JSON 응답을 허용한다고 지정해야 합니다.
GET /orders/2 HTTP/1.1
Accept: application/json
오류에 대해 200 상태 코드를 반환하지 마십시오.
잘못된 접근 방식은 오류가 발생한 경우에도 항상 200 OK를 반환하고 응답 본문에 오류 세부 정보를 포함하는 것입니다. 이렇게 하면 클라이언트가 응답 본문을 구문 분석하여 요청이 실패했는지 여부를 확인해야 하므로 상태 코드의 목적이 훼손됩니다.
나쁜 예:
HTTP/1.1 200 OK
Content-Type: application/json
{
"status": "failure",
"data": {
"error": "Expected at least two items in list."
}
}
이 경우 요청이 실패했지만 서버는 여전히 200 OK를 반환했습니다. 클라이언트는 응답 본문에서 "status": "failure"
필드를 확인하여 오류를 감지해야 합니다. 이 접근 방식은 RESTful하지 않으며 오류 처리를 더 복잡하고 오류가 발생하기 쉽게 만듭니다.
올바른 예:
상태 코드는 요청 결과를 나타내야 합니다. 오류는 적절한 상태 코드를 사용하여 전달하고 응답 본문은 더 자세한 정보를 제공해야 합니다.
예를 들어 요청이 유효하지 않은 경우 서버는 JSON 형식으로 오류 세부 정보와 함께 400 Bad Request를 반환해야 합니다.
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": "Invalid payload.",
"detail": {
"surname": "This field is required."
}
}
여기서 400은 유효하지 않은 요청을 명확하게 나타내고 응답 본문은 클라이언트가 문제를 이해하는 데 도움이 되는 특정 오류 세부 정보를 제공합니다.
링크 제공
RESTful API에서 응답에 링크를 포함하는 것은 일반적인 방식입니다. 이는 API 검색 가능성과 자체 설명성을 향상시키는 HATEOAS(Hypermedia as the Engine of Application State) 원칙을 따릅니다.
다음은 링크를 포함하는 두 가지 일반적인 방법입니다.
HAL(Hypertext Application Language) 사용
HAL은 리소스 간의 관계를 나타내는 널리 사용되는 하이퍼미디어 형식입니다. HAL은 JSON 응답에서 _links 필드를 사용합니다.
{ "id": 1, "name": "Example", "_links": { "self": { "href": "http://api.example.com/resource/1" }, "related": { "href": "http://api.example.com/resource/2" } } }
JSON에 직접 링크 삽입
{ "id": 1, "name": "Example", "links": { "self": "http://api.example.com/resource/1", "related": "http://api.example.com/resource/2" } }
콘텐츠 반환 정책
RESTful API 설계에서 POST 요청은 새 리소스를 만드는 데 사용됩니다. 응답에 새로 생성된 리소스를 포함할지 여부는 구현 요구 사항에 따라 다릅니다. 두 가지 일반적인 접근 방식이 있습니다.
1. 생성된 리소스 반환
이 접근 방식에는 201 Created 상태 코드와 응답에 새 리소스의 전체 세부 정보가 포함됩니다. 또한 리소스의 URI를 가리키는 Location 헤더도 포함됩니다.
HTTP/1.1 201 Created
Location: /resources/123
Content-Type: application/json
{
"id": 123,
"name": "New Resource"
}
2. 콘텐츠를 반환하지 않음
또는 서버는 리소스 세부 정보를 생략하고 Location 헤더와 함께 201 Created 또는 204 No Content 응답만 반환하도록 선택할 수 있습니다. 이렇게 하면 데이터 전송이 최소화되고 클라이언트가 나중에 리소스를 검색할지 여부를 결정할 수 있습니다.
HTTP/1.1 201 Created
Location: /resources/123
결론
RESTful API는 리소스 표현과 상태 비저장 상호 작용을 강조하는 HTTP 프로토콜을 따릅니다. 표준 HTTP 메서드(GET, POST, PUT, DELETE)와 정확한 상태 코드를 사용함으로써 RESTful 아키텍처는 네트워크 애플리케이션을 구축하는 간단하고 효율적이며 유지 관리하기 쉬운 방법을 제공합니다. 이 접근 방식은 웹 서비스의 확장성, 유연성 및 유지 관리성을 향상시킵니다.
저희 Leapcell은 백엔드 프로젝트 호스팅을 위한 최고의 선택입니다.
Leapcell은 웹 호스팅, 비동기 작업 및 Redis를 위한 차세대 서버리스 플랫폼입니다.
다국어 지원
- Node.js, Python, Go 또는 Rust로 개발하십시오.
무료로 무제한 프로젝트 배포
- 사용량에 대해서만 지불하십시오. 요청도 없고 요금도 없습니다.
탁월한 비용 효율성
- 유휴 요금 없이 사용량에 따라 지불하십시오.
- 예: $25는 평균 응답 시간 60ms에서 694만 건의 요청을 지원합니다.
간소화된 개발자 경험
- 간편한 설정을 위한 직관적인 UI입니다.
- 완전 자동화된 CI/CD 파이프라인 및 GitOps 통합입니다.
- 실행 가능한 통찰력을 위한 실시간 지표 및 로깅입니다.
손쉬운 확장성 및 고성능
- 쉬운 동시성 처리를 위한 자동 크기 조정입니다.
- 운영 오버헤드가 없으므로 구축에만 집중하십시오.
설명서에서 자세히 알아보십시오!
X에서 팔로우하세요: @LeapcellHQ