본문 바로가기
CS/네트워크

REST API란?

by 컴쏘 2023. 7. 5.
728x90

1. REST API의 탄생

REST : Representational State Transfer (대표적인 상태 이전?)

로이 필딩이 웹(HTTP) 설계의 우수성에 비해 제대로 사용되어지지 않는 모습이 안타까워 웹의 장점을 최대한 활용할 수 있는 아키텍처로써 REST를 발표

2. REST 구성

  • 자원(RESOURCE) - URI
  • 행위(Verb) - HTTP METHOD
  • 표현(Representations)

3. REST 특징

1. Uniform (유니폼 인터페이스)

Uniform InterfaceURI로 지정한 리소스에 대한 조작으로 통일되고 한정적인 인터페이스로 수행하는 아키텍처 스타일

 

2. Stateless(무상태성)

REST는 무상태성 성격. 다시 말해 작업을 위한 상태정보를 따로 저장하고 관리하지 않음. 세션 정보나 쿠키 정보를 별도로 저장하고 관리하지 않기 때문에 API 서버는 들어오는 요청만을 단순히 처리하면 됨. 때문에 서비스의 자유도가 높아지고 서버에서 불필요한 정보를 관리하지 않음으로서 구현이 단순해짐.

 

3. Cacheable(캐시 가능)

REST의 가장 큰 특징 중 하나는 HTTP라는 기존 웹표준을 그대로 사용. 웹에서 사용하는 기존 인프라를 그대로 활용이 가능. 따라서 HTTP가 가진 캐싱 기능이 적용 가능. HTTP 프로토콜 표준에서 사용하는 Last-Modified 태그나 E-Tag를 이용하면 캐싱 구현이 가능.

 

4. Self-descriptiveness(자체 표현 구조)

REST의 또 다른 큰 특징 중 하나는 REST API 메시지만 보고도 이를 쉽게 이해할 수 있는 자체 표현 구조로 되어있음.

 

5. Client-Server 구조

REST 서버는 API 제공, 클라이언트는 사용자 인증이나 컨텍스트(세션, 로그인 정보)등을 직접 관리하는 구조로 각각의 역할이 확실히 구분되기 때문에 클라이언트와 서버에서 개발해야 할 내용이 명확해지고 서로 간 의존성이 줄어들게 됨.

 

6. 계층형 구조

REST 서버는 다중 계층으로 구성될 수 있으며, 보안, 로드 밸런싱, 암호화 계층을 추가구조상의 유연성을 둘 수 있고 PROXY, 게이트웨이 같은 네트워크 기반의 중간매체를 사용할 수 있게 함.

4. REST API 디자인 가이드

REST API 설계 중심 규칙 2가지

 

1. URI는 정보의 자원을 표현해야 한다. (리소스명은 동사보다는 명사를 사용)

REST를 제대로 적용하지 않은 URI (URI는 자원을 표현하는데 중점을 두어야 한다.)

GET /members/delete/1

delete와 같은 행위에 대한 표현이 들어가서는 안된다.

 

2. 자원에 대한 행위 HTTP Method(GET, POST, PUT, DELETE)로 표현 

1번의 잘못 된 URI를 HTTP Method를 통해 수정해 보면

DELETE /members/1 

회원 정보를 가져올 때는 GET, 회원 추가 시의 행위를 표현하고자 할 때는 POST METHOD를 사용하여 표현한다.

 

예시)

회원 정보를 가져오는 URI

GET /members/show/1  (x) 
GET /members/1       (o)

 

회원을 추가할 때

GET /members/insert/2 (x)
POST /members/2       (o)

 

동사를 허용하는 예외) 컨트롤 자원을 의미하는 URI 는 예외적으로 동사를 허용

함수처럼, 컨트롤 리소스를 나타내는 URI는 동작을 포함하는 이름을 짓는다.

<http://api.test.com/posts/duplicating> (x)
<http://api.test.com/posts/duplicate>   (o) 

 

[참고]HTTP METHOD의 알맞은 역할

POST, GET, PUT, DELETE이 4가지의 Method를 가지고 CRUD를 할 수 있다.

METHOD 역할
POST POST를 통해 해당 URI를 요청하면 리소스를 생성
GET GET를 통해 해당 리소스를 조회함. 리소스를 조회하고 해당 document에 대한 자세한 정보를 가져옴
PUT PUT을 통해 해당 리소스를 수정
DELETE DELETE를 통해 리소스를 삭제

다음과 같은 식으로 URI는 자원을 표현하는 데에 집중하고 행위에 대한 정의는 HTTP METHOD를 통해 하는 것이 REST한 API를 설계하는 중심 규칙

 

REST는 HTTP/1.1 스펙과 동시에 만들어짐. HTTP 프로토콜을 정확히 의도에 맞게 활용하여 디자인하게 유도하고 있기 때문에 디자인 기준이 명확해지며, 의미적인 범용성을 지니므로 중간 계층의 컴포넌트들이 서비스를 최적화하는 데 도움이 된다. REST의 기본 원칙을 성실히 지킨 서비스 디자인은 “RESTful하다.”라고 흔히 표현한다.

무엇보다 이렇게 잘 디자인된 API는 서비스가 여러 플랫폼을 지원해야 할 때, 혹은 API로서 공개되어야 할 때, 설명을 간결하게 해주며 여러 가지 문제 상황을 지혜롭게 해결하기 때문에 (버전, 포맷/언어 선택과 같은) REST는 최근의 모바일, 웹 서비스 아키텍처로서 아주 중요한 역할을 하고 있다.


URI 설계 시 주의할 점

 

1) 슬래시 구분자(/)는 계층 관계를 나타내는 데 사용

<http://restapi.example.com/animals/mammals/whales>

 

2) URI 마지막 문자로 슬래시(/)를 포함하지 않음

URI에 포함되는 모든 글자는 리소스의 유일한 식별자로 사용되어야 하며 URI가 다르다는 것은 리소스가 다르다는 것이고, 역으로 리소스가 다르면 URI도 달라져야 함. REST API는 분명한 URI를 만들어 통신을 해야 하기 때문에 혼동을 주기 않도록 URI 경로의 마지막에는 슬래시(/)를 사용하지 않음.

<http://restapi.example.com/houses/apartments/> (x)
<http://restapi.example.com/houses/apartments>  (o)

 

3) 하이픈(-)은 URI 가독성을 높이는 데 사용

URI를 쉽게 읽고 해석하기 위해, 불가피하게 긴 URI 경로를 사용하게 된다면, 하이픈을 사용해 가독성을 높일 수 있음

 

4) 밑줄(_)은 URI에 사용하지 않음

글꼴에 따라 다르긴 하지만, 밑줄은 보기 어렵거나 밑줄 때문에 문자가 가려지기도 함. 이런 문제를 피하기 위해 밑줄 대신 하이픈(-)을 사용하는 것이 좋음 (가독성)

<http://api.test.com/users/post_comments> (x)
<http://api.test.com/users/post-comments> (o) 

 

5) URI 경로에는 소문자가 적합

URI 경로에 대문자 사용은 피하도록 해야 함. 대소문자에 따라 다른 리소스로 인식하게 되기 때문임. RFC 3986(URI 문법 형식)은 URI 스키마와 호스트를 제외하고는 대소문자를 구별하도록 규정하기 때문

<http://api.test.com/users/postComments>  (x)
<http://api.test.com/users/post-comments> (o)

 

6) 파일 확장자는 URI에 포함시키지 않는다.

<http://restapi.example.com/members/soccer/345/photo.jpg> (X)

REST API에서는 메시지 바디 내용의 포맷을 나타내기 위한 파일 확장자를 URI 안에 포함시키지 않는다. Accept header를 사용

GET / members/soccer/345/photo HTTP/1.1 Host: restapi.example.com Accept: image/jpg

 

리소스 간의 관계를 표현하는 방법

REST 리소스 간에는 연관 관계가 있을 수 있고, 이런 경우 다음과 같은 표현 방법으로 사용함

/리소스명/리소스 ID/관계가 있는 다른 리소스명 
ex) GET : /users/{userid}/devices (일반적으로 소유 'has'의 관계를 표현할 때) 

만약에 관계명이 복잡하다면? 이를 서브 리소스에 명시적으로 표현하는 방법

ex) 사용자가 ‘좋아하는’ 디바이스 목록을 표현해야 할 경우

GET : /users/{userid}/likes/devices (관계명이 애매하거나 구체적 표현이 필요할 때)

 

자원을 표현하는 Collection과 Document

Collection과 Document에 대해 알면 URI 설계가 한층 더 쉬워진다. Document는 단순히 문서로 이해해도 되고, 한 객체라고 이해해도 된다. 컬렉션은 문서들의 집합, 객체들의 집합이라고 생각하면 이해하는데 좀 더 편할 것이다. Collection과 Document는 모두 리소스라고 표현할 수 있으며, URI에 표현된다.

 

예시) 객체들의 집합 - collection, 하나의 객체 - document

<http://restapi.example.com/sports/soccer>

위 URI를 보시면 sports라는 컬렉션과 soccer라는 document로 표현되고 있다고 생각하면 된다.

 

예시)

<http://restapi.example.com/sports/soccer/players/13>

5. HTTP 상태 코드 (REST API 관점)

HTTP (Hyper Text Transfer Protocol) : 웹 환경에서 정보를 주고 받기 위한 프로토콜

REST는 소프트웨어 아키텍처(설계 지침, 원리 등등)고 REST에서 클라이언트-서버 간 통신 시 HTTP를 사용하는 것


Q. REST에서의 HTTP는?

A. REST에서 HTTP는 필수가 아니라고 했지만, 웹 환경 통신의 대부분이 HTTP를 사용

만약, 어떤 API의 요청-응답 포맷이 YAML이라면 YAML이 JSON 포맷의 데이터를 대체하여 표현할 수 있고 JSON이 갖는 한계를 보완한 부분도 있지만, 일반적이지 않음

일반적인 것은 불편함을 야기하기 때문에 이러한 불편함을 감수하면서 일반적이지 않은 것을 사용하려면 매우 설득력 있는 근거가 필요하다.

REST는 HTTP를 사용하는 것이 일반적이다. 필수가 아니라고 했지만, 거의 필수다.

REST의 개념과 원리에는 HTTP가 필수가 아니지만, 그 사용에 있어 필수적으로 변한 경우라 생각하면 좋을 것 같다.


HTTP 상태 코드 : HTTP 요청이 성공했는지 실패했는지를 서버에서 알려주는 코드

기능과 목적

  • 기능 : 사물이 갖는 일정한 구실
  • 목적 : 어떤 일을 통해 이루려고 하거나 하고자 하는 것

ex. 펜은 그리는 기능을 갖고, 어떤 이는 글을 쓰고(목적) 어떤 이는 그림을 그린다. (목적)

상태 코드의 기능 : HTTP 요청이 성공했는지 실패했는지를 서버에서 알려주는 코드

상태 코드의 목적 : 정보 제공자와 소비자가 선택한 약속에 의해 다르게 적용

 

ex. 상태 코드 200

  • 기능 : 요청이 성공적으로 완료가 되었다.
  • 목적 : 이것을 이용해 클라이언트에 다음 작업을 이어 나가도 좋다는 신호의 목적

따라서, 각 상태 코드는 제공자에 따라 다른 목적으로 클라이언트에 제공될 수 있다.

 

예제

Methods POST GET PUT DELETE
/users 사용자 추가 사용자 전체 조회 사용자 추가 or 사용자 수정 사용자 전체 삭제
/users/1 405 ERROR ID 1 사용자 조회 ID 1 사용자 수정 ID 1 사용자 삭제
  • Collection : /users/1 에서 users, 집합
  • Document : /users/1 에서 1, 집합에 속한 자원

2XX Success

2xx 번대 상태 코드들은 서버가 클라이언트의 요청을 성공적으로 처리했다는 의미다.

📝 200 OK : 클라이언트의 요청을 서버가 정상적으로 처리했다.

성공에 대한 모든 상태 코드를 200으로 응답해도 크게 상관 없다. (200 상태 코드는 클라이언트에게 요청이 성공했다는 것을 응답하는 기능을 갖기 때문에)

많은 REST API에서 2xx 상태 코드를 세분화하여 사용하지 않는다.

하지만, 클라이언트에게 더 정확하고 자세한 정보를 제공하기 위해선 적절한 상태코드를 보내는 것이 좋다. (2xx 상태 코드들은 각각 세분화된 목적을 갖는다.)

 

하지만, 아래 설계는 무조건 잘못된 것이니 수정!!

HTTP/1.1 200 OK
{ // body의 내용이 잘못됨 
	"result" : false
	"status" : 400 
}
  • 상태 코드는 200으로 성공인데, body 내용엔 실패에 관한 내용을 리턴
  • 모든 응답을 200으로 처리하고 body 내용으로 성공, 실패를 판단하는 구조에서 사용됨
📝 201 Created : 클라이언트의 요청을 서버가 정상적으로 처리했고 새로운 리소스가 생겼다.

201 상태 코드는 POST, PUT 요청에 대한 응답에 주로 사용된다.

클라이언트의 요청이 성공적으로 이루어졌다는 의미까지는 200과 동일, 성공과 동시에 새로운 리소스가 생성되었다는 의미를 포함

 

예시)

// 요청
POST /users HTTP/1.1
Content-Type: application/json
{
	"name" : "hak"
}
// 응답 
HTTP/1.1 201 Created 
{
	"id" : 1,
	"name" : "hak"
}

물론 새로운 리소스를 생성하는 POST, PUT 요청의 응답으로 200을 보내줘도 된다. 또한, 아직 많은 API의 상태 코드가 이렇게 응답한다.

하지만, 더 정확한 의미를 전달하기 위해 201상태 코드를 쓸 것을 추천한다.

HTTP/1.1 201 Created 
Content-Location; /users/1
{
	"id" : 1, 
	"name" : "hak"
}

Tip) HTTP 헤더의 Content-Location를 이용하여 만들어진 리소스 생성된 위치를 알려주면 더할 나위 없이 좋다.

 

 

📝 202 Accepted : 클라이언트의 요청은 정상적이나, 서버가 아직 요청을 완료하지 못했다.

202 상태 코드는 비동기에 대한 개념이 없다면 생소할 수 있다.

클라이언트의 요청이 정상적이면, 서버에선 작업의 성공/실패 응답하는 게 일반적이나, 작업 완료를 위한 일련의 작업들이 오래 걸리기 때문에 나중에 알려주겠다는 의미이다.

202 상태 코드에서 중요한 것은 작업의 확인이다. 비동기 작업은 해당 요청이 언제 완료되는 지 알 수 없다.

클라이언트가 요청의 완료 여부를 확인할 수 있는 방법을 제공해야 한다.

  1. Callback : 서버가 작업이 완료되면 클라이언트에게 알려주는 것 
  2. Polling : 클라이언트가 주기적으로 해당 작업의 상태를 조회하는 것

비동기 요청(202 상태 코드)은 콜백이든 폴링이든 클라이언트가 요청의 완료 여부를 확인할 수 있는 방법을 제공해야 한다는 것

둘 다 제공하는 것이 좋다.

 

📝 204 No Content : 클라이언트의 요청은 정상적이다. 하지만 컨텐츠를 제공하지 않는다.

204 상태 코드와 유사하게 이상한 응답이라 생각할 수 있다. 자원을 제공하지 않는 경우가 뭘까?

204 상태 코드는 자원의 삭제 요청에 응답할 수 있다.

DELETE /users/1 HTTP/1.1
HTTP/1.1 204 No Content 

자원 삭제 요청을 했고 이 요청이 유효하니 서버는 해당 자원을 삭제했다. 더 이상 응답할 컨텐츠가 없기 때문에 컨텐츠가 없는 204로 응답한다.

여기서 주의할 점은 200으로 응답하고 응답 body에 null, {}, [], false 등으로 응답하는 것과 다르다는 것이다.

204의 경우 HTTP Response body가 아예 존재하지 않는 경우다.

사실 204를 응답하는 API는 흔하지 않다.

204로 응답하는 예시다. 절대적이진 않다. 

PUT
- 자원 수정 요청의 결과가 기존의 자원 내용과 동일하여 변경된 내용이 없을 때 204로 응답할 수 있다. 
- 만약 수정 요청으로 자원의 내용이 변경된다면 201로 응답할 것이다. 

DELETE
- 삭제 요청으로 자원을 삭제하여 더 이상 존재하지 않고 그 자원을 참조하는 모든 자원도 삭제되어 
더 이상 HTTP body를 응답하는 것이 무의미해졌을 때 사용한다.

4xx Client errors

4xx의 상태 코드들은 클라이언트의 요청이 유효하지 않아 서버가 해당 요청을 수행하지 않았다는 의미

📝 400 Bad Request : 클라이언트의 요청이 유효하지 않아 더 이상 작업을 진행하지 않는 경우

API 서버는 클라이언트 요청이 들어오면 바로 작업을 진행하지 않고 요청이 서버가 정의한 유효성에 맞는지 확인 후 진행한다.

다음과 같은 사전 유효성 검증 작업을 진행할 수 있다.

  • 필수 여부
  • 유효 여부
    • 범위
    • 패턴

대부분의 API는 사전에 유효성 검증을 통해 400 상태 코드로 클라이언트에게 유효하지 않은 요청임을 응답 (유효성 검증 없이 진행하면 5xx 서버 오류가 발생할 수 있기 때문에 대부분 사전에 막는 로직을 추가)

그러나, 400 상태 코드로 응답하는 것만으로는 부족하다.

오류 발생 시 파라미터의 위치(path, query, body), 사용자 입력 값, 에러 이유를 꼭 명시하는 것이 좋다.

 

Bad

HTTP/1.1 400 Bad Request 

 

Good case 1

HTTP/1.1 400 Bad Request 
{
	"message" : "'name'(body) must be String, input 'name' : 123"
}

 

Good case 2

HTTP/1.1 400 Bad Request 
{
	"errors" : [
		{
			"location" : "body",
			"param" : "name",
			"value" : 123,
			"error" : "TypeError",
			"msg" : "must be String"
		}
	]
}

 

Good case 3

HTTP/1.1 400 Bad Request
{
	"errors" : {
		"message" : "'name'(body) must be String, input 'name' : 123",
		"detail" : [
			{
				"location" : "body",
				"param" : "name",
				"value" : 123,
				"error" : "TypeError",
				"msg" : "must be String"
			}
		]	
	}
}

 

📝 401 Unauthorized : 클라이언트가 권한이 없기 때문에 작업을 진행할 수 없는 경우

un-authorized

un

authorized : 인정받은, 권한을 부여받은

상태 코드 이름만 보면 권한(authorized)에 대한 내용처럼 보이지만, 사실 인증(authenticated)에 대한 이야기다.

401비인증이다.

  • 비인증 : Not (비인증은 아니다의 뜻이 강하다. 즉, 인증이 안된 상태)
  • 미인증 : Not enough (미인증은 부족하다의 뜻이 강하다. 즉, 권한이 부족한 상태)

결론적으로, 401인증이 안돼 자원을 이용할 수 없는 상태고, 의미상 unauthenticated가 더 정확

 

📝 403 Forbidden : 클라이언트가 권한이 없기 때문에 작업을 진행할 수 없는 경우

forbidden : 금지된

403권한(authorized)에 대한 내용

401의 상태 코드 명이 Unauthorized라 혼동의 여지가 있으나, 권한에 대한 내용이다.

인증된 클라이언트가 권한이 없는 자원에 접근할 때 응답하는 상태 코드

 

📝 404 Not Found : 클라이언트가 요청한 자원이 존재하지 않는다.

존재하지 않은 페이지를 방문하면 자주 만나게 되는 오류 : 404

브라우저(클라이언트) 입장에선 자원이 웹 페이지 경로고 존재하지 않는 경로(자원)를 요청했기 때문에 404 상태 코드를 응답했다.

REST API에선 크게 두 가지 경우에서 404 상태 코드를 응답한다.

  1. 경로가 존재하지 않음
  2. 자원이 존재하지 않음

사실 위에서 설명한 경로, 자원이 정확한 용어와 의미는 아니다.

REST에선 URI가 자원이기 때문에 경로가 곧 자원이다.

404 오류의 경우 두 가지 모두 확인을 해야 한다는 설명을 위한 표현이다.

 

📝 405 Method Not Allowed : 클라이언트의 요청이 허용되지 않는 메소드인 경우

메소드란 POST, GET, PUT, DELETEHTTP Method를 말한다.

즉, 자원(URI)은 존재하지만 해당 자원이 지원하지 않는 메소드일 때 응답하는 상태 코드

 

405 상태 코드는 OPTIONS 메소드와 HTTP header의 Allow와 연관되어있다.

OPTIONS는 API가 허용하는 메소드가 어떤 것들이 있는지 확인하는 메소드

405 오류를 사전에 방지하기 위한 용도에 주로 쓰인다.

이 때 응답 HTTP headerAllow에 지원하는 메소드를 나열하여 응답한다.

RESTful API 설계 가이드에서도 말한 내용이지만 완성도 높은 API를 위해 제공하길 추천한다. (최근 몇몇 API 프레임워크에선 자동으로 허용되지 않는 메소드에 대해 405 상태 코드와 Allow 헤더를 응답하기도 한다.)

OPTIONS /users/1 HTTP/1.1
HTTP/1.1 200 OK
Allow : GET, PUT, DELETE, OPTIONS, HEAD 

/users/1 자원은 POST 메소드를 제공하지 않는다는 정보를 확인할 수 있다.

405 상태 코드는 404 상태 코드와 혼동될 수 있기 때문에 규칙을 잘 정해야 한다.

 

POST /users/1의 경우 API 설계에 따라 404, 405로 응답할 수 있다.

/users/:id 은 GET, PATCH, DELETE 메소드는 허용되고 POST는 불가한 URI이다.

 

GET, PATCH, DELETE의 경우, 1 사용자가 없는 경우엔 404로 응답한다.

GET /users/1 HTTP/1.1
HTTP/1.1 404 Not Found 

 

그러나, POST 요청의 경우 제공하지 않는 메소드이기 때문에 405로 응답하는 것이 옳다.

POST /users/1 HTTP/1.1
HTTP/1.1 405 Method Not Allowed 
Allow: GET, PUT, DELETE, OPTIONS, HEAD

 

📝 409 Conflict : 클라이언트의 요청이 서버의 상태와 충돌이 발생한 경우

충돌이라는 것은 매우 추상적이다. 앞에서 알아본 400, 401, 403, 404, 405 상태 코드들은 사용이 꽤 명확하다.

하지만, 충돌이라는 것은 정의하기 나름이다.

그렇기 때문에 400, 201, 403, 404, 405 상태 코드에 속하기 애매한 오류의 상황들을 409로 응답하는 것도 하나의 예시이다.

 

예시를 들어보자면, 해당 요청의 처리 중 비지니스 로직상 불가능하거나 모순이 생긴 경우

DELETE /users/1 HTTP/1.1 
X-TOKEN: password 
  • 자원(URI) /users/1 에 존재하는 메소드고 Not 405
  • /users/:id에서 :id가 유효한 형식이고 Not 400
  • 1 사용자도 존재하고 Not 404
  • 헤더의 인증(X-TOKEN)도 정확하고 Not 401
  • 삭제 권한도 있는 경우 Not 403

클라이언트의 삭제 요청은 받아들여져서 200 혹은 204로 응답해야 하지만, 사용자의 게시물이 존재하는 경우 사용자를 삭제할 수 없다는 비지니스 로직이 있을 수 있다.

이렇게 API 사용에 있어 비지니스 로직상 모순이 발생하여 처리가 불가능한 경우 응답하는 상태 코드다.

HTTP/1.1 409 Conflict 

400 오류 상황과 마찬가지로 응답 시 오류의 원인을 알려야 한다.

 

추가적으로 HATEOAS를 이용해 클라이언트가 다음 상태로 전이될 수 있는 링크를 함께 응답하면 좋다.

HTTP/1.1 409 Conflict
{
	"message" : "First, delete posts"
	"links":[
		{
			"rel" : "posts.delete",
			"method" : "DELETE",
			"href" : "<https://api.rest.com/v1/users/1/posts>"
		},
	]
}

 

📝 429 Too Many Requests : 클라이언트가 일정 시간 동안 너무 많은 요청을 보낸 경우

비정상적인(DoS attack, Brute-force attack) 방법으로 자원을 요청하는 경우 응답한다.

 

DoS는 가용성에 대한 공격이고 Brute-force기밀성에 대한 공격이다. 하지만, 서버 입장에서 두 공격 모두 가용성에 피해를 입을 수 있다.

서버가 감당하기 힘든 요청이 지속적으로 들어오면 서버는 해당 요청을 처리하기 위해 다른 작업을 처리하지 못할 수 있다.

429 상태 코드는 이러한 경우 일정 시간 뒤 요청할 것을 나타내는 것이다. 따라서 다음과 같이 HTTP header Retry-After을 이용한다.

HTTP/1.1 429 Too Many Requests
Retry-After: 3600
  • 클라이언트는 3600초 후에 다시 해당 자원에 대한 작업을 요청할 수 있다.

Brute-force 기밀성에 대한 공격

POST /login HTTP/1.1 
{
	"name" : "hak"
	"password" : "iwillhackU"
}

무차별적인 대입으로 요청 가능

이렇게 무차별 요청으로 서버 입장에선 자원의 기밀성에 피해를 입을 수 있고, 다른 요청을 처리할 수 없거나 처리가 늦을 수 있는 가용성에 피해를 입을 수 있다.

서버는 이러한 공격에 대비해 인증 API의 경우 각 클라이언트n 시간 동안 n 회만 요청 가능 하다는 룰을 정하고 이것을 초과하면 429 상태 코드를 응답해야 한다.

 

Dos 가용성에 대한 공격

GET /users HTTP/1.1

해커는 시스템에 과부하를 주기 위해 특정 API에 지속적으로 요청을 보낼 수 있다.

해커의 비정상적인 요청으로 인해 실제로 서비스를 받아야 할 정상적인 사용자가 서비스를 받지 못하는 가용성에 피해를 입을 수 있다. 서버는 이러한 공격에 대비해 클라이언트의 요청에 대해 n 시간 동안 n 회 이상 요청 한다면 그 이후의 요청은 429 상태 코드로 응답해야 한다.

  • 사실 429 상태 코드로 DoS, DDoS 같은 가용성에 대한 공격을 막을 수 있는 것은 아니다.
    • 일단, 서버로 지속적인 공격이 오기 때문에 가용성에 피해를 입는 것은 막을 수 없다.
    • API 서버는 계속 429로 응답하겠지만, 서버 자체에 요청이 계속 오는 것을 막을 순 없다는 뜻이다.
    • 네트워크 상단에서 해당 IP를 차단하는 등의 조치가 필요
  • 개발자는 API 서버의 관점에서 생각해야 한다. API 서버가 정의한 범위에서 너무 과도한 요청이라고 생각하면 그러한 작업까지 가기 전에 429 상태 코드로 응답하고 끝내야 한다.

5xx Server errors

5xx 상태 코드들은 서버 오류로 인해 요청을 수행할 수 없다는 의미다.

 

클라이언트의 요청은 유효하여 작업을 진행했는데 도중에 오류가 발생한 경우

404 오류와 마찬가지로 인터넷을 하다 보면 500, 502, 503 등의 오류를 만나봤을 것

 

API 서버의 응답에서 5xx 오류가 발생해서는 안된다.

보통 개발 과정에서 유효하지 않은 요청을 사전에 처리하지 않은 경우(400)에 많이 발생한다.

특히, 500 오류는 개발자의 실수로 발생할 여지가 크다.

POST /users HTTP/1.1
{
	"name" : 123
}

요청에 대해 4xx 오류를 발생시킬 가능성이 있는데 사전에 확인 작업을 하지 않은 경우

  • 파라미터 필수 값, 유효성 확인 없이 비지니스 로직 진행하는 경우
  • 외부 API에서 받은 객체를 확인하지 않고 비지니스 로직 진행하는 경우

API를 사용하는 클라이언트에게 5xx 상태 코드는 나타내지 말아야 한다.

  • 최신의 웹 애플리케이션 프레임워크는 자체 웹 서버를 내장하고 있어서 웹 서버 (Apache, Nginx) 없이 운영할 수 있다.
  • 그러나, 보통 운영 레벨에서 이렇게 하는 경우는 드물고 앞에 웹 서버를 두고 웹 애플리케이션을 연결해서 운영한다.
  • 따라서, 상단의 웹서버 (Apache, Nginx)에서 발생하는 어쩔 수 없는 오류를 제외하고 API에선 5xx 상태 코드가 응답되선 안된다.

따라서, API 레벨에선 완벽한 예외처리를 통해 5xx 서버 오류 상태 코드를 방지해야 한다.


RESTful API 설계 가이드

REST API 제대로 알고 사용하기 : NHN Cloud Meetup

REST API 관점에서 바라보는 HTTP 상태 코드(HTTP status code)

REST 아키텍처를 훌륭하게 적용하기 위한 몇 가지 디자인 팁

본 글은 위의 자료를 참고하여 쓴 글입니다. 
728x90