오픈API 상태 페이지 개발기 feat. Statuspage + 깃헙 액션

Atlassian Statuspage와 깃헙 액션을 활용하여 최소한의 노력으로 API 서비스 상태 페이지를 개발한 이야기입니다.

오픈API 상태 페이지 개발기 feat. Statuspage + 깃헙 액션

인덴트의 브이리뷰 서비스는 서비스 방식에 따라 크게 두 가지 상품으로 나뉩니다. 바로 카페24, 메이크샵, 고도몰 같은 커머스 플랫폼에 연동되는 형태와 자체 구축한 쇼핑몰들과 연동되는 오픈 API형입니다.

오픈 API를 서비스하다보니 커머스 플랫폼 연동 시절에는 생각지 못했던 부분들이 발견되기 시작했는데요. 그 중 하나가 오픈 API 문서 페이지오픈API 상태 페이지였습니다. 둘 중 오늘은 오픈 API 상태 페이지를 개발했던 과정을 정리해보려 합니다.

API 상태 페이지?

해외의 API 서비스를 사용해 본 분이라면 다음과 같은 페이지를 더러 보셨을 겁니다.

트위터 API의 현황을 알려주는 서비스 상태 페이지

이렇게, API 상태 페이지에는 해당 API에서 발생한 사건이나 사고 그리고 현재 작동 상황이 일목요연하게 나타나는데요. 인덴트에서도 오픈API를 사용하는 파트너사들을 위해 API 상태 페이지를 하나 구비해놓고 싶었죠.

하지만 제품 개발이 우선인 상황에서는 이런 페이지를 위해 별도로 시간을 들이기가 어려웠습니다. 그러다 팀원 한 분이 Atlassian의 Statuspage로 큰 힘 들이지 않고 제작할 수 있다고 알려주셨어요.

Statuspage 서비스

어떤 서비스인지 궁금해져서 알아보니 DigitalOcean이나 Dropbox 등에서 이미 사용 중이더군요. 제작 방법도 꽤 간단해보여서 시도해보기로 했죠. 지라의 배포(deployments) 기능을 사용해볼까요? 글에서도 언급했듯 인덴트에서는 지라를 열심히 쓰고 있기도 해서 Atlassian 제품에 거부감이 낮았던 것도 한몫 했습니다.

Statuspage 제품의 설명 페이지

연결 방식은 다음과 같습니다. 매 시간 브이리뷰 오픈 API들의 상태를 확인한 후, 문제가 보이면 Statuspage에 알려줍니다. 문제가 없으면 알려주지 않고, 받은 알림이 없으면 API 서비스는 정상 작동 중으로 나타납니다.

Statuspage의 데이터 흐름

API에 상태 확인용 엔드포인트 추가하기

상태 확인용 엔드포인트는 대개 /health 같은 형태입니다. API 버전도 관리하는 경우 /v1/health 같은 형태가 되겠죠. 단순히 200 OK를 응답하기만 해도 되고, 서버 상태를 좀더 검토한 후 적절한 오류 코드를 응답하게 해도 무방합니다.

Statuspage에서 컴포넌트 만들기

이제 API에 문제가 발생했을 때 알림을 받을 컴포넌트를 만들어야 합니다. 다음 화면의 아래쪽에 보면 Component API ID가 보이는데요. Statuspage의 API를 호출할 때 이 ID를 사용하게 됩니다. (회사마다 다르겠으나 저희는 한 API의 운영서버와 Sandbox 서버를 별도 Component로 구성했습니다.)

문제 발생시 호출해야 하는 API의 형태는 다음과 같은 모습입니다.

def report_incident(component_api_id: str) -> None:
    body = {
        "incident": {
            "name": "API Health check가 실패합니다.",
            "impact": "critical",
            "impact_override": "critical",
            "created_at": datetime.now().isoformat(),
            "body": "Health Check API 요청이 실패하였습니다. 개발팀이 조사하고 있습니다.",
            "component_ids": [component_api_id],
            "components": {
                component_api_id: "partial_outage"
            }
        }
    }
    session.post(
        headers={'Authorization': f'OAuth {STATUSPAGE_API_TOKEN}'},
        json=body,
        url=f'https://api.statuspage.io/v1/pages/{PAGE_ID}/incidents'
    )

Statuspage의 API 토큰(STATUSPAGE_API_TOKEN)과 Page ID(PAGE_ID)는 화면 좌하단의 프로필 사진을 눌러 나타나는 API info 메뉴를 통해 확인할 수 있습니다.

API 토큰과 Page ID를 확인하려면 API info 메뉴를 누르세요

주기적으로 API 상태 알려주기

이제 주기적으로 API의 상태를 확인하는 코드를 작성하고 실행해야 합니다. 주기적으로 상태를 확인하는 코드는 다음과 같습니다.

# main.py
def health_check(url: str, component_api_id: str) -> bool:
    response: Response = session.get(url=url, timeout=3)

    if not response.ok:
        report_incident(component_api_id=component_api_id)

이 코드를 주기적으로 작동시켜야 하는데요. 이 코드조각을 관리할 깃헙 저장소를 만드는 김에 이 저장소에서 깃헙 액션으로 반복 실행하기로 했습니다. 다음은 깃헙 액션용 yml 파일의 내용입니다.

name: "Status check"
on:
  schedule:
    - cron:  "*/60 * * * *"
  workflow_dispatch:

jobs:
  status_check:
    name: Run Status check
    runs-on: ubuntu-latest
    steps:
      ... (중략) ...
      - name: RUN HEALTHCHECK
        run: python main.py
        env:
          STATUSPAGE_API_TOKEN : ${{ secrets.STATUSPAGE_API_TOKEN }}

결과

이렇게 해서 다음과 같은 멋진 API 상태 페이지를 만들었습니다.

인덴트코퍼레이션의 오픈API와 내부 API 서비스의 상태를 한 눈에 알 수 있는 상태 페이지

더 해볼 수 있는 것

저희는 아직 구성하지 않고 있지만 Statuspage의 기능은 다음과 같이 다양합니다.

  • 슬랙과 연동하여 오류 발생시 특정 채널에 경고 메시지 발송하기
  • pageduty와 연동하여 오류 발생시 전화 걸기
  • API 응답 속도 등의 메트릭을 쌓아서 보여주기

시간을 틈틈이 할애하여 이런 기능들도 사용해보고 싶네요.

결론

오픈 API를 운영하기란 꽤나 복잡합니다. API 개발과 유지보수만으로도 시간이 금새 지나가 버리는데요. 따라서 API 상태 페이지에 시간과 노력을 들여야할지 고민이 많았습니다.

다행히 깃헙 액션과 Statuspage 덕에 최소 비용으로 서비스 상태 페이지를 만들 수 있었습니다. (Statuspage API 연동과 코드 작동 여부를 파악하기 위해 테스트해보고, 테스트했던 컴포넌트를 삭제하는 과정이 있어서 예상보다 이틀 정도 더 걸리긴 했지만요.)

만약 여러분의 회사에서도 API 서비스를 공개하였고, (비용 효율적으로) API 상태 페이지를 구축해야 한다면 고려해 봄 직한 방식이라고 생각합니다.