SW개발/개발이야기

외부 API 오류가 발생한다면, 서버는 어떤 status code를 전달해야 할까?

최근에 개발하면서 곰곰히 생각해보아도 마땅한 결론이 나지 않았던 경험에 대해서 이야기해보려고 합니다.

 

외부 API의 오류 그리고 HTTP Status Code

외부 API 에서 오류가 발생한다면 내 서버는 클라이언트에게 어떤 status code를 전달해야 할까요?

이 글을 쓰기 전까지 저는 위 내용에 대해서 잠깐 고민해본적은 있지만 심각하게 고민해본적은 없었습니다. 그저 습관적으로 400 Bad Request를 리턴하고 있었죠. 

 

400 Bad Request 란?

400 에러는 과연 적절한 status code 일까요? MDN의 정의를 살펴봅시다.

The HyperText Transfer Protocol (HTTP) 400 Bad Request response status code indicates that the server cannot or will not process the request due to something that is perceived to be a client error (for example, malformed request syntax, invalid request message framing, or deceptive request routing).

위 내용에 따르면 400 Bad Request는 클라이언트의 잘못된 요청으로 인해서 서버가 더이상 request를 진행할 수 없다는 의미를 내포하고 있습니다.

 

하지만 어느 방면으로 따지고봐도 외부(서드파티) API의 오류는 클라이언트의 잘못된 요청이라는 기준에 부합하지 않았습니다. 클라이언트가 올바르게 요청했어도 외부 API가 동작하지 않는다면 서버는 엉뚱한 status code를 리턴하는 꼴이 됩니다.

 

그러면 에러와 조금 더 연관이 깊은 5XX번대 status code중에는 적합한 것이 있을까요? 여러가지를 살펴봅시다.

 

500 Internal Server Error 란?

The HyperText Transfer Protocol (HTTP) 500 Internal Server Error server error response code indicates that the server encountered an unexpected condition that prevented it from fulfilling the request.

This error response is a generic "catch-all" response. Usually, this indicates the server cannot find a better 5xx error code to response. Sometimes, server administrators log error responses like the 500 status code with more details about the request to prevent the error from happening again in the future.

위 내용에 따르면 500 Internal Server Error는 서버가 리퀘스트를 수행하는데 예기치 못한 상황이 발생한 경우입니다. 또한, 5XX번대의 구체적인 에러 코드를 찾을 수 없는 일반적인 상황에서 사용된다고 합니다.

 

502 Bad Gateway, 504 Gateway Timeout 같은 경우는 네이밍으로만 보아도 위의 상황과는 적절하지 않아 보입니다. 특히 이런 특정한 오류 코드의 경우 클라이언트는 Gateway에 문제가 있다는 잘못된 가정을 하게 됩니다.

 

503 Service Unavailable 란?

조금 더 적절해보이는 에러 코드를 찾은 것 같습니다. 마찬가지로 MDN 정의를 살펴볼까요?

The HyperText Transfer Protocol (HTTP) 503 Service Unavailable server error response code indicates that the server is not ready to handle the request.

Common causes are a server that is down for maintenance or that is overloaded. This response should be used for temporary conditions and the Retry-After HTTP header should, if possible, contain the estimated time for the recovery of the service.

위 내용에 따르면 503 Service Unavailable은 일시적으로 서버가 리퀘스트를 처리할 수 없는 상황을 가정한 상태입니다. 그와 함께 retry에 대한 내용도 언급이 되어 있습니다.

 

현재까지 살펴본 status code 중에서는 가장 적합해 보입니다. 그러나 여기도 한가지 아쉬운 점은 존재하는 것 같습니다.

바로 retry에 대한 부분인데요. 우리는 외부 API가 어느 순간에 장애가 발생할지 전혀 예측할 수 없고 복구시간은 더더욱 예측할 수 없습니다.(물론 외부 API의 장애는 자주 발생하는 일이 아닙니다)

 

이러한 내용들 때문에 위의 상황에 정말 적절한 status code를 찾는 것은 조금 어려웠습니다. 무언가 오해할 소지가 있다고 생각이 드는 부분들은 여전히 찜찜한 채로 남아 있었습니다.

 

저와 같은 상황에 놓이신 분들이 많을 것이라고 생각이 들었고, Stackoverflow에서 리서치를 해보다가 좋은 인사이트를 발견하게 되었습니다.

 

근본적인 해결책

저는 단순하게 어떤 status code를 리턴해야 하지? 라는 질문에만 꽂혀 있었습니다. 그래서 정보도 그 위주로만 검색했던 것 같습니다. 하지만, 아래의 링크에 달린 답변들을 보고서 조금 더 근본적인 해결책에 대해서 깨닫게 되었습니다.

 

https://stackoverflow.com/questions/58994293/rest-api-status-when-external-apis-are-down-best-practices

 

REST API status when external APIs are down - Best Practices

I'm looking for guidance on good practices when it comes to returning errors from a REST API. I'm working on a new API so I can take it any direction. In my case client invokes my API which inter...

stackoverflow.com

 

"어떤 상태코드를 사용해야 하고, 그 근거는 무엇이다" 와 같은 내용들은 이미 수차례 본 뒤였습니다. 하지만 댓글 중에서 근본적으로 문제를 타파하기위해 고도화된 해결책이 제시된 내용이 있었습니다. 다음과 같습니다.

 

  1. 외부 API는 매우 드물게 중단된다. 그러나 외부 API를 사용할 수 없다면 너의 서버도 정상적으로 동작하지 않는 것이다. 이런 경우에는 외부 API 호출을 재시도하는 것을 고려할 수 있다.
    하지만 여전히 운이 좋지 않다면 오류 상태를 반환하면 된다. 5XX 정도일 것이다.
  2. 외부 API에서 제공해주는 데이터는 실제로 중요하지 않다. 하지만, 클라이언트가 너의 서버 API를 호출한다면 최신 정보가 아니더라도 무언가를 제공해주는 것이 좋다. 즉, 외부 API에 장애가 난 경우 사전에 캐싱해둔 최신 데이터를 돌려주는 방법도 있다.
  3. 더 고도화된 아키텍쳐에서는, 메시징 시스템을 활용하는 것이다. 일단 202 Accepted를 리턴하고, 실제로 처리가 가능해지는 시점에 클라이언트에게 푸시와 같은 형태로 알림을 보내줄 수 있다. (단 이 경우는 더이상 REST API가 아니다) 

 

저는 이 댓글을 읽고 꽤나 놀라웠습니다. 그저 "status code"라는 틀에 갇혀서 무엇을 리턴하는 것이 올바른가에 대해서만 생각하고 있었습니다. 외부 API의 장애가 빈번하지 않은 특성과 재시도에 대해서는 생각하지 못했던 것 같습니다.

 

가끔은 해결하고자 하는 문제자체를 잘못 정의하는 상황이 생깁니다. 하지만 깨닫기는 굉장히 어렵지요. 이번 경험에서는 문제가 잘 풀리지 않는다면 조금 더 근본적인, 그리고 상위 레벨에서 다시 내려다 보는 것도 좋은 방법인 것을 깨달을 수 있었습니다.

 

가장 적절한 Status code 는?

그래서 가장 적절한 Status Code는 무엇일까요?

 

제 주관적으로는 503 Service Unavailable, 500 Internal Server Error 중 한가지를 선택해서 사용하면 될 것 같습니다. 이 선택은 속한 조직내의 클라이언트 개발팀과 같이 논의하고 결정한다면 좋을 것입니다.

 

예를 들면, 500 에러 같은 경우에는 실제로 우리 시스템이 에러인 경우로만 한정을 짓고 503을 외부 API 오류로 인해 우리 시스템이 사용 불가능한 상황에 사용하는 규칙을 정의할 수 도 있겠네요.

 

당장 적절한 status code를 선택하는 것도 중요하지만, 위에서 언급한 외부 API 재시도 정책에 대해서는 한번쯤 고려해보는 것이 여러모로 좋은 해결책이 될 것이라고 생각합니다.

 

 

읽어주셔서 감사합니다 :)

 

728x90