ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • REST API 에서의 HTTP 상태 코드 (HTTP Status Code)
    Spring 2024. 6. 20. 11:08

    이번에 프로젝트를 하면서 rest api 설계에서 상태 코드를 정확히 어떤 것을 해줘야 하는지 알아보았다

     

    HTTP Status Code

    • HTTP 요청이 성공했는지 실패했는지 서버에 알려주는 코드 이다

     

    2XX Success

     

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

     

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

     

    ex) 데이터 조회 성공

     

    • 성공에 대한 모든 상태 코드를 200으로 응답해도 크게 상관없다. (200 상태 코드는 클라이언트에게 요청이 성공했다는 것을 응답하는 기능을 갖기 때문에) 많은 REST API에서 2xx 상태 코드를 세분화하여 사용하지 않는다.
    • 하지만, 클라이언트에게 더 정확하고 자세한 정보를 제공하기 위해선 적절한 상태 코드를 보내는 것이 좋다. (2xx 상태 코드들은 각각 세분화된 목적을 갖는다.)

    가장 많이 하는 실수

    HTTP/1.1 200 OK
    {
        "result" : false
        "status" : 400
    }
    • 상태 코드는 200 OK로 성공이라고 되어 있는데 body의 내용에서는 실패에 관한 내용을 반환하고 있다
    • 이 문서는 모든 응답을 200 OK로 처리하고 body 내용으로 성공 및 실패를 판단하는 구조이다
    • API가 아닌 HTML 웹 프로젝트에서 대부분 이렇게 사용한다 -> 웹프로젝트에서는 크게 문제가 되진 않지만 API에서 많이 이상한 구조이다
    • 웹의 설계를 그대로 사용하는 경우 많이 하는 실수이다

     

     

    201 Created : 클라이언트의 요청을 서버가 정상적으로 처리했고 새로운 리소스가 생겼다.

     

    ex) 데이터 등록 성공

     

    • POST, PUT 요청에 대한 응답에 주로 사용한다
    • 클라이언트의 요청이 성공적으로 이뤄졌다는 의미까지는 200과 동일한데,
    • 성공과 동시에 새로운 리소스가 생성되었다는 의미를 포함한다

    예시 

    POST /users HTTP/1.1
    Content-Type: application/json
    {
    	"name": "jaehyeon"
    }
    HTTP/1.1 201 Created
    {
    	"id" : 1,
    	"name" : "jaehyeon"
    }

     

    • 위의 첫번째 문서처럼 POST나 PUT 요청의 응답으로 200을 보내줘도 된다 
    • 하지만 좀 더 정확한 의미를 전달하기 위해 2번째 문서처럼 Created 같은 상태 코드를 쓰는게 좋을 것 같다

    그리고 HTTP 헤더의 Content-Location 를 이용하여 만들어진 리소스의 생성된 위치를 알려주면 더 좋다고 한다

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

     

     

     

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

     

    202 상태코드는 비동기에 대한 개념이 있어야 한다

     

    한마디로 말 하자면

     

    202 상태 코드는 

    클라이언트의 요청이 정상적이면 서버에선 성공이거나 실패를 응답하는게 일반적이지만 

    작업 완료를 위한 다른 작업들이 오래 걸리기 때문에 나중에 알려주겠다는 의미이다.

     

    좀 쉽게 예를 들자면,

     

    카페를 갔다고 생각해보자

    1. 고객(클라이언트)가 카운터(API)의 직원에게 음료 주문(request)을 한다
    2. 그러면 주문을 받고 계산을 한다 -> 여기서 계산에 실패 하게 되면 에러 처리가 되고 성공하게 된다면 음료를 만드는 직원에게 전달된다
    3. 카운터 직원은 번호표를 뽑고 고객에게 완료되면 알려주겠다고한다(response) 

    이 예시에서 커피를 만드는데 시간이 걸리기 때문에 요청은 정상적이지만 아직 완료하지 않았다는 것이다 

     

    202 상태코드에서 핵심은 비동기 작업은 해당 요청이 언제 완료되는지 알수 없다

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

    -> 여기에서 2가지 방법이 있다

     

    1. Callback

    • 서버가 작업이 완료되면 클라이언트에게 알려주는 것
    • ex) 커피가 만들어지면 직원은 주문 번호를 부르고 고객이 커피를 받아가는 것

    2. Polling

    • 클라이언트가 주기적으로 해당 작업의 상태를 조회하는 것
    • ex) 급한 고객은 번호표를 가져가서 직원에게 커피 언제 나오는지 물어보고 나오면 받아 가는 것

     

    이렇게 두가지 방법이 있는데 결론은, 둘다 제공하는 것이 좋다

     

     

     

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

     

    ex) 데이터 삭제 성공, 데이터 수정 성공

    • 204 상태 코드는 자원의 삭제 요청에 응답할 수 있다
    • 하지만 204 상태 코드는 데이터와 같이 응답할 수 없다
    • 왜냐하면 자원을 삭제하기 때문에 삭제된 데이터를 응답할 수 없다는 것이다

    예시

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

     

    그렇다면 수정 성공에서도 쓰이는 이유가 무엇일까?

    • 자원 수정 요청의 결과가 기존의 자원 내용과 동일하여 변경 내용이 없을때 204 로 응답할 수 있다
    • 하지만 자원의 내용이 수정이 된다면 201 로 응답한다

     

     

    4XX Client errors

     

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

     

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

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

    사전 유효성 검증 작업 

    • 필수 여부
    • 유효 여부
    • 범위
    • 패턴
    • 문법 오류
    • 잘못된 형식의 요청
    • 전달 인자가 잘못되어 구문을 인식하지 못하는 경우
    • 문서에서 지정한 구문을 충족시키지 않은 경우

    만약 유효성 검증을 하지 않는다면?

     

    -> 5xx 서버 오류가 발생할 수 있다 그래서 대부분 사전에 막는 로직을 추가한다

     

    하지만!

    400 상태 코드로 응답하는 것만으로는 부족하다.
    오류 발생 시 파라미터의 위치(path, query, body), 사용자 입력 값, 에러 이유를 꼭 명시하는 것이 좋다.

     

     

     

    401 Unauthorized : 클라이언트가 권한이 없어 작업을 진행할 수 없는 경우

     

    ex) 로그인하지 않아 접근할 수 없는 상태

     

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

     

    인증이 안되어서 자원을 이용할 수 없는 상태이다

     

     

    403 Forbidden : 클라이언트가 인증은 됐으나 권한이 없기 때문에 작업을 진행 할 수 없는 경우

     

    ex) 로그인을 해서 인증은 됐지만 관리자 권한이 없어 접근할 수 없음

     

     

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

     

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

     

    1. 경로가 존재하지 않는 경우

    2. 자원이 존재하지 않는 경우

     

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

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

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

     

     

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

     

    여기에서 메소드란 POST, GET, PUT, DELETE 등의 HTTP Method를 말한다

     

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

     

     

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

     

    ex) 주로 POST 요청으로 이미 존재하는 자원에 대한 응답으로 사용한다

     

    충돌이란 것은 매우 추상적인데 

    앞서 말한 400, 401, 403, 404, 405 상태들은 명확하다 

     

    여기에서 충돌이라는 것은 정의하기 나름이라고 생각하여 작자는 위의 상태 코드에 속하기 애매한 오류들의 상황을 409로 구분하여 응답한다

     

     

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

     

    이 상태 코드는 주로 비정상적인 방법으로 자원을 요청하는 경우에 응답한다 

    ex) Dos attack, Brute-force attack 등등

     

    Dos attack 같은 경우에는 가용성에 대한 공격, Brute-force attack은 기밀성에 대한 공격이다

     

    이런 공격으로 인해 서버가 감당하기 힘든 요청이 지속적으로 들어오게 되면 해당 요청을 처리하기 위해 다른 작업을 처리하지 못하게 된다

     

    그러하여 429 상태코드는 이러한 경우에 일정 시간 뒤 요청할 것을 나타낸다

    HTTP/1.1 429 Too Many Requests
    Retry-After: 3600

    위 처럼 HTTP header 에 Retry-After을 이용한다

    -> 위 문서는 클라이언트는 3600초 후에 다시 해당 자원에 대한 작업을 요청할 수 있다는 것이다

     

     

     

     

    5XX Server Errors

    • 서버 오류로 인하여 요청을 수행할 수 없다는 의미
    • 개발자의 실수로 발생하는 경우가 많다
    • 개발자는 API를 사용하는 클라이언트에게 5xx 상태 코드를 나타내지 말아야 한다

     

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

    'Spring' 카테고리의 다른 글

    [Spring] DTO의 모든 것  (0) 2024.06.25
Designed by Tistory.