지난포스트 (deprecated)/Result (deprecated)

공공데이터 API 활용 - 상품정보 불러오기

.log('FE') 2018. 11. 20. 14:29
728x90
반응형

 

 

 

공공데이터포털 바로가기 : 공공데이터포털

 

 

공공데이터포털 API 활용

- 상품정보 불러오기 -

 

# create-react-app mt_shop
# cd mt_shop
# npm i react-xml-parser
# npm start

 

 

원래 하려던건 API 정보를 활용해서 MT 장바구니 시스템을 한번 만들어 보려고했다.

 

동호회에서나 MT 놀러갈때 음식을 어느정도 사야하는지 감이 안와서 대충 짐작해서 사가는 경우가 많은데

 

이럴때 활용할 수 있을까 싶어서 시도해봤는데 .... 정보 불러오기까진 성공했는데 이게 내가 원하는 정보가 한꺼번에 들어있지가 않다....

 

1. 공공데이터포털에서 API 정보 신청하기

 

 

이 홈페이지에서 오픈API 페이지에들어가서 원하는 정보를 검색하고 활용신청을하고 1시간~하루정도 지나면 데이터를 받아서 활용 할 수 있다.

 

나는 '생필품 가격정보 조회 서비스' 를 신청하였고 신청이 완료되면 인증키가 발급되고 개발가이드를 참고하여 url 링크를 fetch 함수를 활용하여 적용하였다.

 

API 정보는 XML, JSON, CSV 등 정보에따라 각기 다른 포맷으로 정보를 제공한다.

 

JSON 이면 참 편하겠지만 내가 신청한 정보는 XML 밖에 없어서 별도의 파싱이 필요하다.

 

 

1. 첫번째 난관 (CORS Issue)

 

 

 

App.js

fetch('http://openapi.price.go.kr/
openApiImpl/
ProductPriceInfoService/
getProductInfoSvc.do?ServiceKey=인증키')
.then(response => response.text())
.then(xmlText => console.log(xmlText))

 

fetch 를 활용하여 넣었는데 저게무엇인가...CORS 정책에 의해 막힌다고 나온다..

검색....

 

CORS 란 Cross Origin Resource Sharing 의 약자로 Cross-Site Http Request 를 가능하게 하는 표준규약이라고한다. 타 도메인으로부터 리소스가 필요할 경우에는 Cross-Site Http Request 가 필요하다.

 

 

이것때문에 한참을 골머리 썩다가 구글에서는 이걸 강제로 허용해주는 확장프로그램이 있어서 설치하고 해결하였다.

 

구글 확장프로그램에서

Allow-Control-Allow-Origin: *

 

를 검색하고 설치한 후 작동시켜주면 된다.

 

 

정상적으로 콘솔에 텍스트형태로 보여지는것을 확인할 수 있다.

 

이제 이걸 xml 형식으로 파싱과정을 거쳐 정보를 뽑아내려고 한다.

 

# npm i react-xml-parser 를 설치하고 상단에

import XMLParser from 'react-xml-parser';


모듈을 불러와주고 아래처럼 사용하면된다.

 

// .then(xmlText => console.log(xmlText))
.then(stringToXml => new XMLParser().parseFromString(stringToXml))

 

 

콘솔로 확인하면 뭔가 참 깊숙히 내가 찾아야할 정보가 들어가있다.

 

.then(a => {
for(let i = 0; i < a.length; i++) {
let name = a[i].getElementsByTagName('goodName')[0].value;
let id = a[i].getElementsByTagName('goodId')[0].value;
if(a[i].children.length === 8) {
this.setState({
products:[
...this.state.products,
{
id: id,
name:name
}
]
})
} else {
let info = a[i].getElementsByTagName('detailMean')[0].value;
this.setState({
products:[
...this.state.products,
{
id: id,
name:name,
info:info
}
]
})
}
}
})

 

name 에는 상품의 이름을 for문을 돌면서 setState로 상태값에 들어가도록 하였고 id 는 나중에 다른정보를 불러와서 id 로 비교한후에 상품의 가격을 뽑아내려고 같이 입력해주었다.

 

그리고 상품에 대한 간략한 정보에 대한 내용도 함께 출력되도록 하였다.

 

_renderProducts = () => {
const products = this.state.products.map((product, index) => {
return <Products name={product.name} info={product.info} key={index} />
})
return products
}

 

_renderProducts() 함수를 만들어서 자식컴포넌트에게 정보를 넘겨주도록 하였다.

 

 

Products.js

import React, { Component } from 'react';
import './Products.css';

class Products extends Component {
render() {
return (
<div className="productCard">
<h3>{this.props.name}</h3>
<ProductInfo info={this.props.info} />
</div>
)
}
}


class ProductInfo extends Component {
render() {
return (
<div>
{this.props.info}
</div>
)
}
}

export default Products;



App.js

render() {
return (
<div className="App">
{this._renderProducts()}
</div>
);
}

 

 

이렇게 컴포넌트를 생성해주고 적당한 css 를 주고 화면에 뿌려주면

 

 

 

 

이렇게 원하는 정보를 출력할 수 있게 된다.

 

 

두번째 난관은 저 정보를 어떻게 꺼내 오는가 였다.

 

NomadCoder 실습예제로 연습했던 MovieApp 만들때는 DATA도 JSON 형태였고 필요한 정보의 단계도 깊이 있지않고 쉽게 찾아낼수있었지만 공공데이터포털에서 제공하는 정보는 사실 설명서도 그렇고 데이터도 그렇고 그렇게 친절하게 알려주는것같지는 않다.

 

어쩔수없이 for 문으로 모든 정보를 돌면서 필요한 태그명을 가진 정보를 추출해냈고

 

설명부분은 없는 항목도 있었어서 length === 8 가지인경우에는 상품명만 setState 되도록 하였다.

 

가격출력까지 해보려고했지만....전체정보에있는 점포 아이디와 상품아이디를 모두 매칭시켜 출력하거나 하나의 상품정보에 수백가지의 가격정보(점포마다 다름)가 포함되어있어서 이중에 하나만 출력하기도 어려운문제가...

 

그리고 이건 현재 가지고있는 문제점인데 로딩이 너무 오래 걸린다...

 

이걸 어떠한 식으로 처리할지는 좀더 고민을 해 봐야할 문제인것같다.

 

어차피 데이터 없이는 못쓰겠지만 MT 장바구니 형태의 기능이 동작하도록 만들어보려고는 한다.

 

 

code-reading 블로그에 방문해 주셔서 환영합니다.
댓글은 모두 환영하니 많이 달아주세요.

 

 

728x90
반응형