공공 데이터 포털 단기예보 api 에러 처리

공병주(Chris)·2023년 5월 18일
5
post-thumbnail

해당 방식은 현재 사용중이지 않고, Batch를 통해 주기적으로 API Call을 하여 날씨를 받아오고 있습니다.
글로벌미디어학부 20203 졸업작품 Dandi에서

공공 데이터 포털 단기예보 API를 통해 사용자에게 아래와 같은 형태로 날씨 알림 메시지를 전송해야하는 요구 사항이 있었습니다.

오늘 날씨는 최저 10 / 최고 21 입니다. 단디에서 옷차림을 확인해보세요!

따라서, FeignClient를 통해 공공 데이터 포털 데이터를 요청하고 날씨 데이터를 받아와서 알림을 보내는 기능을 구현했습니다.(API 사용 방법은 공공 데이터 포털 API 문서와 많은 블로그들에 잘 나와있기 때문에 따로 소개하지 않겠습니다.)

하지만, 여기서 알림을 보내는 기능을 구현하는 것만큼이나 중요한 것이 있습니다. 공공 데이터 포털에서 날씨 정보를 정상적으로 받아오지 못했을 때의 처리입니다.

(참고 코드) 계속 고민 하면서 에러 처리를 구현해서, 구현하면서도 로직이 바뀌어 작업 단위가 조금 큰 점 양해 부탁드립니다!

참고) 공공 데이터 포털 단기예보 요청 형식

http://apis.data.go.kr/1360000/VilageFcstInfoService_2.0/getUltraSrtNcst?serviceKey=인증키&numOfRows=10&pageNo=1&base_date=20210628&base_time=0600&nx=55&ny=127

참고) 공공 데이터 포털 API 동작 방식

공공 데이터 포털 QnA의 여러 질문에 답변을 읽어보니, 모든 데이터를 공공 데이터 포털에서 관리하는 것이 아니라 공공 데이터 포털이 요청을 받으면 적절한 공공기관(기상청, 행정안전부 등)으로 HTTP 요청을 통해 데이터를 받아오고 이를 다시 전달해주는 방식인 것을 알 수 있었습니다. 아래 그림과 같은 형태입니다.

클라이언트 ↔ 공공 데이터 포털 ↔ 공공기관

에러 알아보기

기상청에서 제공하는 응답코드는 아래와 같습니다.

출처 : 공공 데이터 포털 - 기상청 **단기예보 **조회서비스 Open API 활용가이드

NORMAL_SERVICE(00)을 제외하고는 모두 ERROR 상황이기 때문에 API 요청의 결과로 ERROR들이 응답된다면 이에 대한 에러 처리를 해줘야합니다.

에러에 대한 내용이 공공 데이터 포털 QnA 게시판에 흩어져있습니다. 저처럼 공공 데이터 포털에 대한 에러 대응 로직을 구현해야할 수도 있으니, 아래에 정리해두었습니다.

에러들은 공공 데이터 포털의 QnA 게시판을 찾아보고 제가 직접 에러에 대한 테스트 코드를 작성하면서 확인해보고 정리한 글입니다.

01) APPLICATION_ERROR(어플리케이션 에러)

BaseDate와 BaseTime 요청 파라미터가 잘못되었을 때 응답받는 에러입니다. 개발하는 시점에 BaseTime와 BaseDate에 대해 이해하고 적절한 값이 할당되도록 구현해두었습니다. 실제 api call을 통해 테스트도 진행해보았습니다.

따라서, BaseDate와 BaseTime이 잘못된다면 구현해둔 BaseTime과 BaseDate 구현에 문제가 있거나 공공 데이터 포털 API의 변경이 있어서 빠르게 수정을 해야하는 상황이라고 생각합니다.

02) DB_ERROR

공공 데이터 포탈의 DB의 에러와 공공기관(기상청)의 DB의 에러 중에 공공기관의 DB 에러라는 생각이 들었는데요. 공공 데이터 포탈의 QnA 게시판을 찾아보니 공공기관의 DB 에러임을 확인할 수 있었습니다.

03) NODATA_ERROR

현재, 사용자가 지정해서 DB에 저장된 위치 정보(위도, 경도)를 기상청 nx, ny 값으로 변환하여 요청을 하는 방식인데요. 사용자의 위치 정보에 해당하는 데이터가 기상청에서 제공하지 않는 경우에 발생합니다.

04) HTTP_ERROR

HTTP ERROR는 제공기관으로부터 잘못된 결과를 받았을 경우 공공데이터포털에서 출력되는 메세지로

제공기관의 endPoint의 서버 응답이 없을 경우나 연계 오류가 있을 경우등에 발생됩니다.

05) SERVICETIME_OUT

사실, SERVICETIME_OUT의 경우는 정확히 파악하지 못했습니다. 추측으로는 위에서 설명했듯이, 공공 데이터 포털에서 각 공공기관에 HTTP 요청을 하는데, 공공기관에서 요청을 처리하지 못하는 것으로 보입니다.

이것은 사견이기 때문에 확실히 하기 위해 공공 데이터 포털에 질문을 한 결과, 아래와 같은 답변을 얻을 수 있었습니다.

제공기관(기상청)으로부터 데이터가 불러와지지 않을 경우 보여지는 오류입니다.

10) INVALID_REQUEST_PARAMETER_ERROR

nx, ny를 천만 등의 값으로 하는 것과 같이 요청 파라미터가 유효하지 않은 값일 경우에 발생하는 경우입니다.

11) NO_MANDATORY_REQUEST_PARAMETERS_ERROR

기상청 명세에 있는 필수 요청 파라미터를 누락해서 요청을 할 시에 응답되는 에러입니다.

필수 파라미터에는 serviceKey, base_date, base_time, nx, ny가 있습니다.

12) NO_OPENAPI_SERVICE_ERROR

오픈 API URL이 잘못되었거나 해당 URL의 오픈 API가 폐기된 경우입니다.

20) SERVICE_ACCESS_DENIED_ERROR

해당 오류는 서비스키와 동기화 관련된 오류입니다. 공공 데이터 포털에서 서비스키를 발급했지만, 해당 서비스키가 제공기관(기상청)에는 동기화되지 않았기 때문에 발생하는 에러입니다.

21) TEMPORARILY_DISABLE_THE_SERVICEKEY_ERROR

SERVICE_ACCESS_DENIED_ERROR와 동일합니다.

22) LIMITED_NUMBER_OF_SERVICE_REQUESTS_EXCEEDS_ERROR

공공 데이터 포털에는 일일 요청 횟수 제한이 있는데요. 제가 사용하고 있는 계정은 일일 요청 횟수 제한이 1만회입니다. 해당 푸시 알림은 사용자 당 하루에 1번 전송됩니다. 따라서, 하루 단기 예보 요청 횟수는 에러가 발생하지 않는다면 사용자 횟수와 거의 동일하다고 할 수 있습니다. 따라서, 아직은 문제가 되지 않을 것이라고 생각합니다.

30) SERVICE_KEY_IS_NOT_REGISTERED_ERROR

SERVICE_ACCESS_DENIED_ERROR와 동일합니다.

31) DEADLINE_HAS_EXPIRED_ERROR

서비스키의 기한이 만료된 경우입니다. 서비스키의 유효기간은 2년입니다. 당장 문제가 되지 않을 것으로 판단했습니다.

32) UNREGISTERED_IP_ERROR

공공데이터 포털의 API 활용 신청시에 서버 유형으로 등록한다면 해당 서버의 IP에서만 데이터를 요청할 수 있습니다. 따라서, 다른 IP에서 데이터를 요청했을 때 응답되는 ERROR입니다.

하지만, 저는 서버 유형이 아닌 일반 유형으로 API 활용을 신청했기 때문에 만날 일이 없는 ERROR입니다.

33) UNSIGNED_CALL_ERROR

공공데이터 포털에 문의한 결과 사용하지 않는 에러 메시지라는 답변을 받았습니다.

39) UNKNOWN_ERROR

알 수 없는 에러입니다.

에러를 어떻게 처리할 것인가?

일단 위 에러들을 4가지 성격으로 구분하고 각각의 처리 방식을 채택했습니다.

1. 위치 정보에 의한 에러

  • NODATA_ERROR

이 경우에는 사용자의 위치 정보 기반이 아닌, 서울시의 nx ny 값을 통해 재요청을 하고 사용자에게 서울시의 날씨와 위치 정보를 수정해서 날씨 정확도를 높여주세요! 라는 문구로 알림을 전송하도록 했습니다.

2. 일시적 에러

  • SERVICE_TIME_OUT
  • DB_ERROR
  • HTTP_ERROR

공공 데이터 포털에서 데이터를 제공하는 공공기관(기상청)으로 요청을 보내서 날씨 정보를 받아오는데, 공공기관의 자원에 문제가 생긴 경우입니다. 해당 경우는 공공기관의 자원이 복구된다면 정상 응답을 받아올 수 있습니다.

  • SERVICE_ACCESS_DENIED_ERROR
  • TEMPORARILY_DISABLE_THE_SERVICE_KEY_ERROR
  • SERVICE_KEY_IS_NOT_REGISTERED_ERROR

공공 데이터 포털에 등록된 서비스키(인증키)이 공공기관(기상청)에 동기화되지 않은 경우입니다. 동기화가 이뤄진다면 정상 응답을 받아올 수 있습니다.

위 6가지 에러의 경우에 1번의 재시도 후, 실패한다면 로그를 남기고 성공한다면 정상 흐름의 로직이 실행되도록 처리했습니다.

현재 에러 응답을 받고 바로 재시도 하도록 구현해두었습니다. 에러를 응답한 서버는 가까운 시간 내에 동일한 에러를 응답할 확률이 높습니다. 바로 재시도 하는 것보다는, 에러가 발생해서 실패한 요청들은 푸시 알림 스케쥴링이 끝나는 시점에 한번 더 재시도하는 방식으로 진행했습니다. 푸시 알림 스케쥴링 로직은 푸시 알림을 허용해둔 사용자의 정보를 위치 정보를 DB에서 조회하고 위치 정보에 대한 날씨를 API를 통해서 받아와야 하기 때문에 모든 사용자에 대해 실행되려면 꽤 오랜 시간이 걸릴 것으로 예상됩니다. 따라서, 실패한 지점부터 재시도하는 시점까지 어느 정도 시간의 간격을 둘 수 있을 것으로 기대합니다.

3. 코드 수정이 필요하거나 동작하는 Application에서 대응이 불가능한 에러

  • APPLICATION_ERROR
  • INVALID_REQUEST_PARAMETER_ERROR
  • NO_MANDATORY_REQUEST_PARAMETERS_ERROR

위 두 에러의 경우에는, 테스트를 통해서 Parameter에 대한 검증을 했습니다. 따라서, 발생한다면 공공데이터 포털의 API 명세가 바뀐 것일 것으로 예상되기 때문에 Hotfix로 빠르게 대응해야할 것으로 생각합니다.

  • NO_OPENAPI_SERVICE_ERROR

폐기 예정될 것이라는 안내를 받으면, 빠르게 다른 API를 찾아서 대응해야할 것으로 생각합니다.

4. 발생 가능성이 적고 사전 대응이 가능한 에러

  • LIMITED_NUMBER_OF_SERVICE_REQUESTS_EXCEEDS_ERROR

공공 데이터 포털의 단기예보 서비스는 일일 요청횟수가 1만건입니다. 사용자가 5천 이상이 되면 공공데이터의 계정을 개발 계정에서 운영 계정으로 변경해서 일일 요청횟수를 10만건으로 증가시키면 대응 가능할 것이라 생각합니다.

  • DEADLINE_HAS_EXPIRED_ERROR

서비스키가 2년이 되어 만료되기 전에 서비스키를 최신화하면 대응 가능할 것이라 생각합니다.

  • UNREGISTERED_IP_ERROR

발생할 가능성이 없습니다.

모든 최종 실패의 경우에 Slack을 통해 회원 정보와 에러 발생 원인 함께 알림이 발송되는 환경을 구축해두었습니다.

날씨 API 성공/실패에 따른 푸시 알림 메시지 가공

iOS의 푸시 알림은 APNS입니다. APNS 방식은 푸시 알림 서버에서 받은 값을 클라이언트 개발자가 제어할 수 없다고 해서 서버에서 푸시 알림 메시지를 가공해서 푸시 알림 서버로 전송하기로 했습니다.

위에서 날씨 API 성공/실패에 따라 아래와 같은 메시지 가공 전략을 세웠습니다.

1. 요청 성공 및 재시도에서의 성공

첫 API 요청에 정상적으로 혹은 재시도를 통해서 날씨 정보를 받아오는 경우에는 사용자에게 날씨 정보를 포함한 푸시 알림 메시지를 가공해서 전송하면 됩니다.

2. 위치 정보 오류로 인한 서울시의 날씨 정보를 통한 날씨 조회

공공 데이터 포털의 API의 경우, 한국에 한정한 날씨 정보를 제공합니다. 이 경우에는 사용자에게 서울의 날씨를 알려주면서, 위치 정보가 국내가 아니니 정확도를 위해 위치 정보를 다시 설정해달라는 푸시 알림을 가공합니다.

3. 에러로 인한 날씨 정보 조회 실패

하지만,

3. 코드 수정이 필요하거나 동작하는 Application에서 대응이 불가능한 에러, 4. 발생 가능성이 적고 사전 대응이 가능한 에러의 경우에는 날씨 정보를 당장 받아올 수 없습니다. 또한, 2. 일시적 에러도 재시도에 실패하면 결과적으로 실패한 것입니다.

그렇다면, 날씨를 받아오는 것에 실패한다면 사용자에게 푸시 알림을 보내지 못하는 것일까요?

날씨 정보를 받아오지 못했기 때문에, 100% 의도한 대로 메시지를 가공할 수 없기 때문에 그렇게 생각할 수 있습니다.

[푸시 알림의 목적]

여기서, 푸시 알림의 목적에 대해 생각해보았습니다. 푸시 알림은 서비스에서 이탈중인 사용자가 서비스로 다시 들어오게끔 하는 것이 가장 크다고 생각합니다.

그렇다면, 날씨 정보를 포함하지 않은 푸시 알림 메시지를 보내는 것과 날씨 정보를 포함하지 않았기 때문에 푸시 알림 메시지를 보내는 것 중 당연히 전자가 푸시 알림의 목적을 더 잘 달성한다고 생각합니다.

[푸시 알림 전송 시간과 사용자가 실제로 서비스에 진입하는 시간의 차이]

현재, 클라이언트(iOS)에서도 따로 동일한 공공 데이터 포털 API를 통해 날씨 정보를 받아오고 있습니다.

사용자들은 휴대폰을 24시간 사용하는 것이 아니기 때문에, 푸시 알림 전송 시간과 사용자가 실제로 서비스에 진입하는 시간의 차이가 존재할 것입니다. 따라서, 공공기관(기상청)의 자원으로 인한 일시적인 오류로 날씨 정보가 포함되지 않는 푸시 알림을 통해 앱에 진입했어도, 해당 시점엔 공공기관의 자원 복구이 되었다면 사용자는 앱에서 클라이언트(iOS)에서 받아온 날씨 정보를 확인할 수 있습니다.

위처럼 공공 데이터 포털을 통해 날씨 정보를 받아올 경우 발생할 수 있는 에러와 제가 해당 에러들을 처리한 방식에 대해

0개의 댓글