우리 프로젝트는 사실상 데이터가 매우 중요한 서비스이다. 온라인 청년센터에서 제공해주는 신뢰성 있는 내용들을 보기 좋게 정리해주고 필터링해주는 서비스이기 때문에, 온라인 청년센터의 api를 사용해야 했다. 오늘은 외부 api 를 호출해 데이터를 인풋/저장하는 과정을 기록해보기로!! 💪
청년정책 api 신청하기
온라인 청년센터 에 들어가 회원가입 및 로그인을 한 후 인증키 신청과정을 거친다. 처음에는 공공데이터포털처럼 심사가 하루면 될 줄 알았는데 아니었다. 답답해서 청년정책 오픈카톡방에 문의해보니 일주일 내외로 걸린다고 하셨으니 참고가 되길 바랍니당 ㅜㅜ
마이페이지에서 인증키 확인이 된다면 성공이다.
Postman으로 확인하기
참고로 우리는 MVP 단계에서는 범위를 좁혀 주거/금융 카테고리의 정책들 중 중앙부처의 정책들만 다루기로 했다. 서비스에 맞게 파라미터를 입력해준 뒤 리스트가 응답으로 잘 오는지 확인한다.
데이터 인풋 코드 작성
우리 개발 환경은 node express + typescript, 디비는 mysql 이다. 파이썬으로 input 코드 작성은 꽤 해봤는데 이번에 기왕 js 로 개발하는거 인풋 코드도 스크립트 언어로 짜보기로 했다.
온라인 청년센터의 api는 결과를 json이 아닌 xml로 전달해주는데, json이 다루기 더 편하기 때문에 xml에서 json 으로 변환해주는 xml-js 라이브러리를 설치해주었다. 또한 외부 api 호출하는 데에 사용되는 request 라이브러리도 install 및 import 해준다.
인증키와 디비 관련 정보들은 .env 파일에 안전하게 저장해주고 dotenv 방식으로 호출한다.
아래는 작성한 전체 코드 내용이다 🤓
const convert = require('xml-js');
const request = require('request');
const mysql = require('mysql');
require('dotenv').config();
const OPEN_API_KEY = process.env.OPEN_API_KEY;
const connection = mysql.createConnection({
host: process.env.DB_HOST,
user: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
});
const requestUrl = `https://www.youthcenter.go.kr/opi/empList.do?display=100&pageIndex=1&bizTycdSel=004003&openApiVlak=${OPEN_API_KEY}`;
request.get(requestUrl, (err, res, body) => {
if (err) {
console.log(`err => ${err}`);
} else {
if (res.statusCode == 200) {
const xmlToJson = convert.xml2json(body, { compact: true, spaces: 4 });
const json = JSON.parse(xmlToJson); // json 객체로 파싱
const emp = json.empsInfo.emp;
emp.forEach((data) => {
// 중앙부처 정책만
if (data.polyBizTy._cdata === '중앙부처') {
connection.query(
`SELECT count(*) FROM policy where name = "${data.polyBizSjnm._cdata}"`,
(err, results) => {
if (err) throw err;
// 정책 이름이 같은 데이터가 존재하지 않는다면 데이터 삽입
if (results[0]['count(*)'] == 0) {
connection.query(
`INSERT INTO policy(name, number, summary, content, limit_age, work_status, specialization, operating_institute, application_period, application_process, announcement, application_site) VALUES(?,?,?,?,?,?,?,?,?,?,?,?)`,
[
data.polyBizSjnm._cdata,
data.bizId._text,
data.polyItcnCn._cdata,
data.sporCn._cdata,
data.ageInfo._cdata,
data.empmSttsCn._cdata,
data.splzRlmRqisCn._cdata,
data.cnsgNmor._cdata,
data.rqutPrdCn._cdata,
data.rqutProcCn._cdata,
data.jdgnPresCn._cdata,
data.rqutUrla._cdata,
],
(err, results) => {
if (err) throw err;
console.log('results: ', results);
}
);
} else {
// 정책 이름이 같은 데이터가 존재한다면 넘어감
console.log('same policy already in db');
}
}
);
}
});
}
}
});
우선 request.get 으로 응답을 받아온다.
만약 성공적으로 응답을 받아 200 코드가 반환되었다면 밑의 코드들을 실행하게 되는데, 이때
const xmlToJson = convert.xml2json(body, { compact: true, spaces: 4 });
const json = JSON.parse(xmlToJson);
이 두 라인은 xml 결과인 body를 넣어 json으로 변환해준 뒤 json 객체로 파싱해주는 작업을 한다.
이후 forEach로 데이터를 훑으며 중앙부처의 정책만 저장했다.
sql 쿼리를 실행하기 위해서는 connection.query()를 사용하면 되는데, 특정 컬럼에 대해 중복되는 값이 있는지 확인하기 위해
SELECT count(*) FROM policy where name = "${data.polyBizSjnm._cdata}"
count를 가져오는 구문을 이용했다. policy 테이블의 name 컬럼에 대해 비교값과 일치하는 데이터가 존재한다면 쿼리 결과가 0보다 클 것이다.
이미 존재한다면 그 데이터는 넘어가고, 디비에 존재하지 않는 데이터는 insert 해준다.
connection.query(`INSERT INTO policy(컬럼) VALUES(?)`, [ 삽입할 값들 ]);
참고로 당연한 얘기겠지만 컬럼 개수와 물음표 개수, 삽입할 값의 개수는 모두 같아야 한다.
requestUrl의 파라미터 중 pageIndex 값을 11까지 늘려가며 인풋했으며
node (코드의 경로)
를 터미널에 입력해 코드를 실행할 수 있다.
디비에 저장되면서 이런 식으로 저장된 결과가 출력되고,
같은 이름의 정책이 이미 저장되어있다면 아래와 같이 "same policy already in db" 라고 출력되는 모습을 볼 수 있다 🧚