본가에서 회사로 출근해야 하는 경우가 종종 있다. 광역 버스를 통하면 그럭저럭 빠르게 갈 수 있지만 사람이 너무 몰려 버스를 못 타는 경우가 많아 지하철을 이용해서 가는 경우를 택하고 있다.
생각해보면 모든 시간대에서 버스에 자리가 없는 것을 아닐 것이고 아마 출근 시간대에 자리가 없는 것이 아닐까? 하는 생각을 하곤 했다. 이 때, 공공데이터포털에서 제공하는 API를 통해 시간대별로 자리가 얼마나 있는지를 파악하면 좀 더 효율적으로 출근할 수 있지 않을까? 하는 생각이 들어 이를 조사해보기로 했다.
우선 가능한 API들을 찾아보았다. 찾아보니 지역별(경기도, 부산, 서울 등등)로 API를 제공해주는 것과 국토교통부에서 전체적인 경로를 제공해주는 것. 두 가지가 있었다.
이용하게 된 API는 경기도의 API였다. 정류소에 도착 예정인 버스들에 대한 정보를 반환해주는 버스도착정보 조회
API를 사용했는데, remain_seat
라는 변수로 남은 좌석수를 알려주어 요구사항에 맞았다.
: 경기도_버스도착정보 조회 | 공공데이터포털
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,수영오거리.방송통신대입구
와 같은 데이터를 얻을 수 있었고
다만, 조건을 필터링 했을 때 높은 확률로 아무 데이터가 저장되지 않아서 코드가 잘 돌아가는건지 아닌건지 헷갈렸고 로그를 위한 데이터 저장을 추가했다.
2025-01-26 11:19:32 | Count: 1 | Status: success
이와 같이 저장되는데,
배치를 매일매일 실행하기 위해 다양한 인프라 기술들을 살펴봤다.
AWS Function 에서 실행 --> S3에서 저장
과 같은 기술들이 있었고 (AWS, Google Cloud 등) 요금은 거의 나오지 않았다. 다만, 회원가입 or 계좌 설정 등을 진행해야 해서 시간적인 비용이 많이 들 것이라는 생각이 들었다.
사실 필요한 데이터는 즉각적으로 필요한 것이 아니기도 해서, 일단 로컬 맥북에서 한 달 정도 돌려본 다음에 불편한 경우 클라우드 기술을 쓰기로 결정했다. (단, PC를 끄지 않아야 한다.)
crontab을 이용해서
평일 07~11시에 실행되고 저장되게 하였다. (*/10 7-11 * * 1-5
)
분석은 별도 프로세스가 필요해보였다. 데이터가 충분히 쌓이면, 평일 데이터를 대상으로 시간대별로 평균을 내봤을 때 몇 시가 가장 자리가 많은지를 확인해보면 될 것 같다.
오랜만에 실생활에 필요한 코딩을 했던 것 같아 유익했다. 이번엔 코딩하기 귀찮은 부분, 사용해보지 않은 라이브러리들을 AI를 활용해 많은 도움을 받았는데, 이제는 AI 활용하는 게 많이 익숙해진 것 같다.