[외부 API] 외부 api 호출해 MySQL 데이터베이스에 데이터 인풋하기

julia·2022년 2월 13일
0

Spoon Feed

목록 보기
2/5

우리 프로젝트는 사실상 데이터가 매우 중요한 서비스이다. 온라인 청년센터에서 제공해주는 신뢰성 있는 내용들을 보기 좋게 정리해주고 필터링해주는 서비스이기 때문에, 온라인 청년센터의 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" 라고 출력되는 모습을 볼 수 있다 🧚

profile
Move Forward

0개의 댓글

관련 채용 정보