도서 관련 서비스 특성상 알라딘 api를 활용해서 도서 정보를 받아와야했다.
그런데 알라딘은 api를 열어 놓고서는 CORS policy를 열어 놓지 않는 것이었다. 관련해서 메일로 연락을 보냈지만 관련 개발자가 없는 건지 대답이 없었다.
CORS를 간단하게 설명하자면 aladin.co.kr 이 아닌 주소에서 알라딘 서버에 요청을 보내면 거절해버리는 정책이다.
원래는 client에서 header에 Access-Control-Allow-Origin policy를 * 값으로 보내면 이를 피할 수 있지만 서버에서도 설정을 해주어서 받아주지 않으면 답이 없다.
그럼 다른 이들은 어떻게 알라딘 api를 가져오고 있었을까? JSONP 방식이었다. JSONP는 get 요청만 가능하다는 단점이 있으나 CORS policy를 피할수 있다고 한다.
찾아보면 jqery로 받는 방법이 나와있으나 여기서 쓰이는 callback 함수가 도대체 뭔지 알 수가 없었다.
const url = `https://www.aladin.co.kr/ttb/api/ItemSearch.aspx?ttbKey=ttbkey&Query=${this.state.booktitle}&output=js&callback=bookdisplay`
이게 url 값인데 여기에서 callback은 도대체 뭐란 말인가? 샅샅이 구글링으로 뒤져본 결과 jquery 같은 경우엔 <script> const bookdisplay=(success, data )=>{ console.log(data) }<script>를 document상에서 찾아서 실행되게 하는것이었다. 즉 알라딘 서버에서는 해당 이름이랑 같은 함수를 찾아서 그 함수가 실행되게 하고 거기에 data를 넘겨준다.
그런데! 나는 현재 react 기반으로 서비스를 만들고 있다. Script 태그는 저어기 멀리 index에 있고 여기에다가 뭔가 추가해서 데이터를 받을 수는 있어도 원하는 페이지에 데이터를 넘길 수가 없다. (알고보면 window에서 정의해서 전역으로 만들면 상관 없었다고…)
궁여지책으로 localstorage.setItem(“bookdata”, JSON.stringify(data))를 해서 데이터를 토큰 처럼 넣어다가 나중에 빼는 것까지 해보았다. 그런데 알라딘과의 서버 교신이 비동기여서 setitem 보다는 localstorage.getItem(“bookdata”)가 먼저 실행되어버리는 문제가 생겼다.
그래서 약간 미친 척하고 settimeout까지 동원해서 localstorage.getItem이 300~400ms 의 딜레이 후에 실행되도록 했다. 그러니까 드디어 원하는 곳에 데이터를 불러올수 있었다.
하지만! 알라딘 서버와의 교신 시간은 인터넷 환경에 따라 얼마든지 다를 수 있고 그렇다고 딜레이를 너무 길게 잡으면 사용자가 불편하다. 특수한 상황이 아니면 비동기를 settimeout으로 해결하는 것은 개발자로서의 마인드가 아니다. 그래서 또 다른 방법을 다시 찾아보았다.
열심히 좀더 찾아본 결과 jqery 말고 순수 자바스크립트로 하면 위의 <script>태그에 굳이 함수를 넣지 않아도 실행 받을 수 있었다.
setbookinfo = ()=>{
var resultOfBookdata = null;
var callbacks = ()=>{
console.log(“결과물”,resultOfBookdata);
this.setState({data:resultOfBookdata});
console.log(“max”,Math.floor(resultOfBookdata.totalResults/5)+1)
this.setState({maxpage: Math.floor(resultOfBookdata.totalResults/5)+1 })
}
const url = `https://www.aladin.co.kr/ttb/api/ItemSearch.aspx?ttbKey=ttbporr34441025002&Query=${this.state.booktitle}&output=js&callback=bookdisplay&MaxResults=5&SearchTarget=Book&Sort=SalesPoint&Start=${this.state.page}`
$.ajax({
url : url,
async: false,
dataType : ‘jsonp’,
jsonp: “bookdisplay”,
})
window.bookdisplay = (success, data)=>{
if(!success){
alert(“도서검색에 실패했습니다.”)
return;
}
console.log(“data?”,data);
resultOfBookdata = data;
callbacks();
};
this.setState({isclicked : true})
}
이와 같이 작성하면 훌륭하게도 data가 잘 나온다. 내가 react를 잘 사용하는 방법을 잘 몰라서 그런지 몰라도 이렇게 script 태그를 꼭 사용해야하는 상황이 생기면 참 곤란하다. (위에도 적었지만 script안에서 정의할 필요 없었고window로 전역 정의하면 되는 것이었다.)
참고 자료: https://blog.garstasio.com/you-dont-need-jquery/ajax/#jsonp