Skip to main content

Posts

Let thine heart retain my words: Keep my commandments, and live.

오래걸리는 API 설계

· 4 min read
Jeongwon Her

api
오래걸리는 API 설계

문제점

API를 개발하다 보면, 백그라운드에서 오랜 시간이 걸리는 것들이 있습니다. 특히, 학습이나 추론같은 AI를 API로 제공할때 많이 발생하게 됩니다. (가장 크게 실패했다고 느낀 점입니다)

REST는 요청이 수초 안에 끝나기 때문에, 동기적(synchronous)인 API에 적합한 부분이 있습니다. 작업에 시간이 더 걸린다면, 애플리케이션이 연결 상태를 유지한채 작업이 끝날때가지 멈춰(block)있는 것은 좋은 해결방법이 아닙니다. 연결이 지속되면 전체 서비스와 로드벨런서 자원을 계속 사용하게 되고, 네트워크 환경에 따라 연결이 끊길 가능성이 높아집니다. (연결이 끊기면 사용자는 같은 요청을 또 보내겠죠!)

타이크(Tyk)라는 API 관리 플랫폼 회사에 좋은 글이 있어 각색하였습니다.

예제

타이크 社의 예제를 각색했습니다
벌크 인퍼런스 API 요청을 가정해봅시다.

[POST] /v1/inference/bulk
[
{...},
{...},
{...},
]

API 서버는 빨리(수초 이내에) 끝나지 않을 것을 압니다. 따라서, 202 Accepted 상태를 반환합니다.

HTTP/1.1 202 Accepted
Location: https://api.example.com/v1/inference/jobs/3971

202 Accepted는 사용자의 요청이 정상적이였으나, 서버가 즉시 응답할 수 없다는 것을 의미합니다. 여기에 Location 헤더가 추가되어 GET 요청으로 결과를 확일할 수 있는 URL을 제공합니다.



사용자는 제공된 URL을 폴링하여 작업이 끝났는지 확인합니다.

[GET] /v1/inference/jobs/3971

작업이 진행중이라면 사용자는 status가 InProgress(또는 정의된 status값)인 응답을 받습니다.

HTTP/1.1 200 OK

{
"jobId": "3971",
"status": "InProgress",
"percentComplete": "25",
"suggestedNextPollTime": "2018-10-02T11:00:00.00Z",
"estimatedCompletionTime": "2018-10-02T14:00:00.00Z"
}

작업이 완료되었다면 사용자는 status가 Completed인 응답을 받습니다.

HTTP/1.1 200 OK

{
"jobId": "3971",
"status": "Completed",
"completionTime": "2018-10-02T14:00:00.00Z",
"_links": {
{ "rel":"results", "https://api.example.com/v1/inference/jobs/3971/results" },
...
}
}

폴링을 사용하지 않는 방법

  • 작업이 완료되었을때 알려줄(POST) 웹훅을 사용합니다
    • 사용자의 부담이 커질 수 있지만, 작업이 끝날때까지 폴링하는 것을 방지할 수 있습니다
  • Server Sent Event(SSE)웹소켓을 사용합니다

결론?

이전까지는 오래걸리는 작업에 대한 반응형 웹을 백엔드에서 지원해주려면 SSE나 웹소켓을 사용해야 한다고 생각했습니다.

하지만 FE개발자에게 좋은 방법만은 아니였다는(특히 웹소켓을 IE같은 구형 브라우저까지 고민해야 했다면!) 것을 경험적으로 느끼고 있었습니다.

폴링을 포함한 다양한 상태 모니터링 방법을 제공해 천사같은 백엔드 개발자가 되어보는건 어떨까요?

물론 그런건 세상에 없습니다


References

API design guidance: long running background jobs