공공 데이터 API를 통해 환율을 받아오자

SeongHyeon Bae·2022년 7월 27일
3

개인 프로젝트 진행 중 환율 정보를 받아와야 하는 케이스가 생겼다.
공공 데이터의 경우 단순히 URL로 데이터를 요청해서 받아오는 경우 보다 복잡해서 정리해 보려고 한다!
참고로 https://unipass.customs.go.kr/csp/index.do 사이트를 들어가면 환율 정보를 알 수있다.

https://unipass.customs.go.kr/csp/framework/filedownload/kcs4gDownload.do?attchFileId=MYC-20200710-00037918211TiAQI 를 클릭하면 관세청에서 제공하는 연계 가이드 문서를 볼 수 있어 이를 참고 하였다.

사전 작업

이 API 를 사용하기 위해 우선적으로 UNI-PASS의 회원으로 가입되어 있어야 하며, 각각의 용도에 맞는 서비스를 신청한 후 승인을 받아야 사용할 수 있다. 우리는 관세환율이 필요하므로 이를 신청하자!
이 부분은 연계가이드에 친절하게 설명이 되어있기 때문에 생략하겠다.

API 요청

연계 가이드 문서를 보면 관세 환율 정보는 ID값이 API012를 가지고 있다. 우리가 요청해야 하는 URL 주소는 다음과 같다.

URL : https://unipass.customs.go.kr:38010/ext/rest/trifFxrtInfoQry/retrieveTrifFxrtInfo?crkyCn=[인증키]&qryYymmDd=[날짜]&imexTp=2

인증키 부분은 사전작업 을 통해 받을 수 있고 날짜의 경우 원하는 날을 입력하면 된다 ex) 20150101
imexTp가 1 일경우 수출, 2일 경우 수입을 받아온다. 우리의 경우 수입을 예시로 진행할 것이다.

환율정보는 매주 일요일 마다 갱신이 되는것 같다.

Client 환경에서 우리가 원하는 데이터를 요청해보자. 필자는 React 환경에서 테스트를 해보았다.

Client Code

const getData = async () => {
  try {
    const data = await fetch(
      'https://unipass.customs.go.kr:38010/ext/rest/trifFxrtInfoQry/retrieveTrifFxrtInfo?crkyCn=[인증키]&qryYymmDd=20220725&imexTp=2',
    );
    console.log(data);
  } catch (e) {
    console.log(e);
  }
};

적절한 인증키와 20220725 날짜에 해당하는 데이터 요청시 우리를 항상 괴롭히는 CORS 에러가 발생했다. 그래.. 이렇게 쉽게 원하는 걸 얻을리가 없지...

그럼 CORS 에 대해 간단하게 알아보고 해결해 보자.

교차 출처 리소스 공유 (CORS)

교차 출처 리소스 공유(Cross-Origin Resource Sharing, CORS)는 추가 HTTP 헤더를 사용하여, 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제입니다. 웹 애플리케이션은 리소스가 자신의 출처(도메인, 프로토콜, 포트)와 다를 때 교차 출처 HTTP 요청을 실행합니다.

정의는 역시 어렵다. 간단하게 정리해보면 현재 Client에서 사용중인 도메인(현재는 localhost)과 서버의 도메인(UNI-PASS 서버)이 같아야지 서로 리소스(환율 정보)들을 공유할수 있다.(보안상의 이유라고 한다.)

하지만 요즘 다른 도메인 끼리 리소스를 공유해야 하는 경우도 많다.
이럴 경우 필요에 따라 '이 Client 도메인은 우리(서버)와 도메인이 달라도 리소스를 공유하겠습니다.' 라고 서버에 설정 해야한다.

우리가 UNI-PASS 쪽 서버에 접근해 우리의 도메인을 추가 할 수는 없으므로 우리가 서버를 하나 만들어서 UNI-PASS로 부터 데이터를 받아오고 우리쪽 서버에서 우리의 도메인이 리소스를 받을 수 있게 설정하고 데이터를 제공하는 방식으로 해결했다.

대략적인 flow

Server

자신의 서버가 있고 그곳에서 작업하면 좋겠지만 이번 프로젝트의 경우 그러지 못했다.
이것을 위해 서버를 띄운다 해도 너무 과한 느낌이 강하게 들어 나의 용도에 적합한 방법을 찾다 AWS Lambda 라는 서비스를 이용해보았다.

AWS Lambda는 서버를 프로비저닝하거나 관리하지 않고도 코드를 실행할 수 있게 해주는 컴퓨팅 서비스입니다.

프론트 엔드 개발자가 간단하게 서버리스로 코드를 실행하고 싶을때 적합한 방식이라고 판단했다.

그럼 AWS Lambda 함수의 코드 구현을 보면 다음과 같다.

파이썬보다 Node.js가 편해서 Node.js로 구현하였다.

Code

Server

const https = require("https");
let url = `https://unipass.customs.go.kr:38010/ext/rest/trifFxrtInfoQry/retrieveTrifFxrtInfo?crkyCn=[인증키]&qryYymmDd=${getToday()}&imexTp=2`;

exports.handler = async (event) => {
    const resultObj = await new Promise((res, reject) => {
    https.get(url, (response) => {
      var result = "";
      response.on("data", function (chunk) {
        result += chunk;
      });

      response.on("end", function () {
        
        const body = {
          headers: {
            "Access-Control-Allow-Headers" : "Content-Type",
            "Access-Control-Allow-Origin": "*",
            "Access-Control-Allow-Methods": "OPTIONS,POST,GET"
            },
          statusCode: 200,
          body: result,
        };
        res(body);
      });
    });
  });
    
    return resultObj;
};

function getToday(){
    var date = new Date();
    var year = date.getFullYear();
    var month = ("0" + (1 + date.getMonth())).slice(-2);
    var day = ("0" + date.getDate()).slice(-2);

    return year + month + day;
}

그럼 관공서에서 제공해주는 형식인 XML로 다음과 같이 출력된다.

음.. 우리는 JSONXML 보다 다루기 편하므로 xml-js의 라이브러리를 이용해 변환을 진행하였다.

사실 이 부분에서 lambda 계층에 xml-js 라이브러리를 저장 후 JSON 파일을 전송하는 방법도 있지만
Client에서 JSON으로 변환하는 방식으로 진행하였다.

Client

import { useEffect, useState } from 'react';
import axios from 'axios';

var convert = require('xml-js');

const getData = async setData => {
  const response = await axios.get(
    'AWS API 주소',
  );

  const jsonResponse = convert.xml2json(response.data);
  const USD = await getUSD(JSON.parse(jsonResponse));
  setData(USD);
};

const getUSD = data => {
  let USD = 0;

  data.elements[0].elements.forEach(e => {
    if (e.elements?.length > 2) {
      if (e.elements[3].elements[0].text === 'USD') {
        USD = e.elements[2].elements[0].text;
      }
    }
  });

  return USD;
};

function App() {
  const [data, setData] = useState();

  useEffect(() => {
    getData(setData);
  }, []);
  return <div className="App">{data}</div>;
}

export default App;

위와 같이 진행하면 아래처럼 USD 수입 환율을 받아올 수 있다.

참고

https://developer.mozilla.org/ko/docs/Web/HTTP/CORS
https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/welcome.html
https://www.npmjs.com/package/xml-js

profile
FE 개발자

0개의 댓글