몇시에 출근하는 게 좋을까? | 자리 많은 버스 시간대 분석해보기

Hansu Park·2025년 2월 2일
11
post-thumbnail

도입

본가에서 회사로 출근해야 하는 경우가 종종 있다. 광역 버스를 통하면 그럭저럭 빠르게 갈 수 있지만 사람이 너무 몰려 버스를 못 타는 경우가 많아 지하철을 이용해서 가는 경우를 택하고 있다.

생각해보면 모든 시간대에서 버스에 자리가 없는 것을 아닐 것이고 아마 출근 시간대에 자리가 없는 것이 아닐까? 하는 생각을 하곤 했다. 이 때, 공공데이터포털에서 제공하는 API를 통해 시간대별로 자리가 얼마나 있는지를 파악하면 좀 더 효율적으로 출근할 수 있지 않을까? 하는 생각이 들어 이를 조사해보기로 했다.

API 탐색하기

우선 가능한 API들을 찾아보았다. 찾아보니 지역별(경기도, 부산, 서울 등등)로 API를 제공해주는 것과 국토교통부에서 전체적인 경로를 제공해주는 것. 두 가지가 있었다.

이용하게 된 API는 경기도의 API였다. 정류소에 도착 예정인 버스들에 대한 정보를 반환해주는 버스도착정보 조회 API를 사용했는데, remain_seat라는 변수로 남은 좌석수를 알려주어 요구사항에 맞았다.
: 경기도_버스도착정보 조회 | 공공데이터포털

API 스펙 살펴보기

API 스펙을 살펴보았는데 stationID라는 변수가 있었다. 찾아보니 정류장을 나타내는 ID인데 어디서 찾아야할지 몰라 당황했다. 이를 찾기 위해 다양한 방식을 시도했다. 정류장 번호라는 게 어디서든 일관적으로 사용하고 있진 않을까? 해서 네이버 버스 API를 살펴보고, 국토교통부 API도 살펴보았다. 결론적으로는 stationID는 경기도에서만 사용하는 ID라고 알게되었다.

다행히도 경기도_BMS 정류소 정보 | 데이터셋 상세 Sheet | 경기데이터드림 에서 정류장ID를 획득할 수 있었다. 설명 한 줄만 더 있었으면 쉽게 알 수 있었는데, 공공데이터포털의 불편함을 느꼈다.

개발 시작하기

테스트 API를 날려볼 수 있어 이를 활용해 날려봤고 API Response를 알 수 있었다.


  "response": {
    "comMsgHeader": "",
    "msgHeader": {
      "queryTime": "2025-02-02 21:44:08.592",
      "resultCode": 0,
      "resultMessage": "정상적으로 처리되었습니다."
    },
    "msgBody": {
      "busArrivalList": [
        {
          "remainSeatCnt1": 37,
          "remainSeatCnt2": 47,
          "routeName": 2007,
          "predictTimeSec1": 84,
          "predictTimeSec2": 908,
          "stateCd1": 2,
          "stateCd2": 1
        },

(필요한 데이터만 남겨놓았다.)

버스 번호가 routeNumber로 들어오고 남은 좌석 수가 빠른 버스 2개에 대한 데이터를 확인할 수 있었다. GoLang에서는 이를 structure로 매핑해주어야 하는 어려움이 있지만, GPT를 사용해서 빠르게 변환하여 API 결과를 받아올 수 있었다.

그러나, API 결과를 structure로 매핑하는 과정에서 에러가 빈번히 났다. 매핑해줄 변수인 routeName이 spec 상에서는 string이었지만 number로 들어오는 경우가 있었기 때문이다. ("G1857", 1009 이런식이다.) 이를 해결하기 위해서 일단 모든 타입을 표현할 수 있는 any 타입으로 받은 후, type에 따라 변환하는 함수를 만들어 해결하였다. (interface{}를 사용했는데 내가 마주한 케이스에는 any를 사용하는 게 더 적합하다고 하여 변경했다.)

데이터 추출하기

다시 문제(좌석이 널널한 시간대 고르기)로 돌아와 보면, 모든 데이터가 아니라 특정한 조건에 해당하는 데이터만 추출해야 한다.

조건은 다음과 같다.
1. 출근 시간대(07~11시)인 데이터
2. 원하는 버스인 데이터(1009번)
3. 가까운 데이터 (10분을 벗어나지 않는 경우)
(2), (3)은 이를 추출하여 원하는 데이터만 저장하도록 하였고, (1)은 배치 시간을 조정하여 해결하기로 했다.

테스트를 위해 조건을 배제한 채 배치 코드를 돌려보았다.

time,predict_time,remain_seat,station_name
2025-01-26 11:29:36,54,39,수영오거리.방송통신대입구

와 같은 데이터를 얻을 수 있었고

  • 방통대 입구에서
  • 11:29분 기준으로
  • 54분이 남았을 때
  • 39개의 자리가 있다
    는 정보를 얻을 수 있었다.

다만, 조건을 필터링 했을 때 높은 확률로 아무 데이터가 저장되지 않아서 코드가 잘 돌아가는건지 아닌건지 헷갈렸고 로그를 위한 데이터 저장을 추가했다.

2025-01-26 11:19:32 | Count: 1 | Status: success

이와 같이 저장되는데,

  • Count는 배치를 통해 저장된 데이터의 수
  • Status는 배치가 에러없이 돌아갔는지 여부
    를 나타냈다.

배치 스케줄링 하기

배치를 매일매일 실행하기 위해 다양한 인프라 기술들을 살펴봤다.

AWS Function 에서 실행 --> S3에서 저장 과 같은 기술들이 있었고 (AWS, Google Cloud 등) 요금은 거의 나오지 않았다. 다만, 회원가입 or 계좌 설정 등을 진행해야 해서 시간적인 비용이 많이 들 것이라는 생각이 들었다.

사실 필요한 데이터는 즉각적으로 필요한 것이 아니기도 해서, 일단 로컬 맥북에서 한 달 정도 돌려본 다음에 불편한 경우 클라우드 기술을 쓰기로 결정했다. (단, PC를 끄지 않아야 한다.)

crontab을 이용해서

평일 07~11시에 실행되고 저장되게 하였다. (*/10 7-11 * * 1-5 )

배치 결과 분석하기

분석은 별도 프로세스가 필요해보였다. 데이터가 충분히 쌓이면, 평일 데이터를 대상으로 시간대별로 평균을 내봤을 때 몇 시가 가장 자리가 많은지를 확인해보면 될 것 같다.

마치며

오랜만에 실생활에 필요한 코딩을 했던 것 같아 유익했다. 이번엔 코딩하기 귀찮은 부분, 사용해보지 않은 라이브러리들을 AI를 활용해 많은 도움을 받았는데, 이제는 AI 활용하는 게 많이 익숙해진 것 같다.

0개의 댓글

관련 채용 정보