지하철 노선 전체 정보 오픈 API
1. API 신청하기
오픈API를 여러 방면으로 찾아봤는데 내가 원하는 데이터는 지하철 노선 전체 정보와 노선에 따른 역 정보였기 때문에 하단 링크에 있는 API를 사용하게 되었다.
https://data.kric.go.kr/rips/M_01_02/detail.do?id=431&service=trainUseInfo&operation=subwayRouteInfo
활용 신청 버튼을 클릭하고 요청하는 정보를 입력한 후 등록 버튼을 누르면 그냥 그대로 창이 닫힌다.
처음에 당황해서 고객센터에 메일도 보내고 그랬는데 알고보니 다음날 입력한 이메일 주소로 필요한 서비스키와 1년 동안 이용할 수 있다는 안내문이 메일로 온다.
이 메일을 받았다면 일단 신청에 성공했으며 서비스를 바로 사용할 수 있다.
2. API 사용법
2-1. 파라미터 관련 정보 다운받기
요청하는 방법을 확인하면 링크에 몇가지 파라미터를 넣어 요청해야하는데, 필요한 정보는 아래와 같다. 이메일로 받은 서비스키와 format 정보, 그리고 선코드(노선코드), 권역 코드 를 파라미터로 넣어야 한다. 선코드는 그럼 어디서 얻어올까?
철도 데이터 포털에서 정보공유 -> 자료실을 가보면 최신 노선 정보에 대한 코드 정보 리스트를 다운 받을 수 있다.
https://data.kric.go.kr/rips/M_04_02/intro.do
excel 파일로 제공되는 정보들은 그대로 DB에 가공하여 넣을 수도 있지만 언제 업데이트될지 모르기 때문에 추후 Python으로 크롤링을 만들어 다운받을 예정이다. 그러나 역정보는 노선코드만 알면 다운받기가 가능한데, 권역코드는 위에 나온대로 (01:수도권, 02:부산, 03:대구, 04:광주, 05:대전) 으로 고정되어있으므로 DB에 그대로 입력했다.
권역에 따른 노선 정보는 Excel에 나와있으며 각 노선에 대한 색상 코드도 넣기 위해 아래 링크를 참조해서 노선 코드/노선명/노선 컬러 에 대한 정보를 테이블에 저장했다.
여기까지가 노선 정보를 세팅하는 방법이고 다음으로는 이 정보들을 이용해 역 정보를 가져온다.
2-2. 노선별 역 정보 가져오기
Node 모듈 중 axios를 이용해 api request를 날린다. GET 방식으로 파라미터를 아래와 같이 넣어 날리면 완전 실시간은 아니지만 정보가 날아온다.
const url = `https://openapi.kric.go.kr/openapi/trainUseInfo/subwayRouteInfo`;
const { data } = await axios.get(url, {
params : {
serviceKey : process.env.SUBWAY_SERVICE_KEY,
format : 'json',
mreaWideCd : area.area_code,
lnCd : line.line_code
}
});
JSON 방식으로 받아 내가 원하는 노선별 Station Code, Station Name을 받고 가공하여 만들어 놓은 테이블에 집어 넣는 로직을 짰다.
Subway Area(권역정보) - Line(노선정보) - Station(역정보) 이런 식으로 연결되어 있으며 1 : N, 1 : N 부모와 자식 관계는 1:N으로 되어있다.
아래 코드를 살펴보자.
const fetchAllStationInfo = async () => {
const url = `https://openapi.kric.go.kr/openapi/trainUseInfo/subwayRouteInfo`;
const subwayArea = await SubwayArea.findAll({include : [{ as : 'lines', model : SubwayLine}]});
if (subwayArea) {
subwayArea.forEach(area => {
area.lines.forEach(async (line) => {
const { data } = await axios.get(url, {
params : {
serviceKey : process.env.SUBWAY_SERVICE_KEY,
format : 'json',
mreaWideCd : area.area_code,
lnCd : line.line_code
}
});
if (data) {
if (data.body) {
const filtered_data = data.body.filter((x: { lnCd: string; }) => x.lnCd == line.line_code);
const station_list = filtered_data.map((element : any) => {
const station : SubwayNameDto = {
subway_line_id : line.subway_line_id,
station_code : element.stinCd,
station_name : element.stinNm,
}
return station;
});
const result = await ORM.getInstance().transaction(async (t) => {
const subwayNames = await SubwayName.bulkCreate(station_list, {transaction : t});
return subwayNames.length > 0 ? true : false;
});
}
}
});
});
}
}
기존에 등록된 SubwayArea-SubwayLine 정보를 호출하여 각 권역별 - 노선을 foreach로 돌면서 api 요청을 한다. 요청에 따라 데이터가 오면 filter와 map 함수로 원하는 정보 형태만 받고 가공하여 역 정보 리스트를 만든다. 리스트를 만든 후 해당 노선에 따른 역 정보들을 한번에 bulk로 insert 한다.
내부적으로만 쓸거라서 따로 error처리는 안했지만 추후 리팩토링해야겠다. 아무래도 주기적으로 이 함수를 호출하여 DB에 저장된 역 정보를 업데이트해야할 것 같다.
다음엔 등록된 정보를 이용하여 역 검색어 자동완성 기능을 구현해야하므로 그 때 다시 포스팅하도록 하겠다.
'개발 Study > Node' 카테고리의 다른 글
[Sequelize/Node.js] commit has been called on this transaction 에러 해결 (1) | 2023.01.31 |
---|---|
[Sequelize] ForeignKey로 Cascade delete 적용하기 (0) | 2022.12.15 |
[Node.js] 공공 오픈 API 이용하기 - 사업자 휴/폐업 실시간 조회 (5) | 2022.10.20 |
[Node.js] 비밀번호 암호화(bcrypt HASH) (0) | 2022.10.06 |
[SocketIO/WebRTC] 줌 클론 코딩(2) - WebRTC로 카메라 연결하기 (3) | 2022.08.23 |
댓글