[CORS] 알라딘 , 네이버 Open API 활용기 - 1

Hayeon LEE·2024년 1월 11일
0

problem solving

목록 보기
1/2

필자는 팀 프로젝트에서 책 정보를 얻기 위해 알라딘과 네이버 Open API를 활용하던 중, CORS(Cross-Origin Resource Sharing) 문제가 발생하여 이를 해결한 과정을 정리했습니다.

웹 브라우저는 동일 출처 정책(Same-Origin Policy)을 따라 다른 출처(origin)에서 오는 리소스에 대한 접근을 제한하기때문에 Open API 데이터에 접근해야 하기 위해선 CORS 정책을 허용해야 합니다.

이때 필자는 많은 방법을 찾아보다 express 프레임워크를 사용해 간단한 벡엔드 서버를 만들어 CORS 문제를 해결하는 방법을 택했습니다.
이 방법은 클라이언트에서 직접 API를 요청하는 것이 아니라 서버를 중간에 두고,서버가 Open API를 요청을 하고, Open API서버로 부터 응답을 받아서 클라이언트에게 결과를 전달하는 것입니다.

필자는 react 프로젝트를 배포하기 위해 처음부터 Cloudtype의 플랫폼의 node.js 템플릿을 활용하여 서버를 배포했습니다.

1. 먼저 필요한 패키지를 설치 및 환경 변수 설정 (API 키)

npm install express cors morgan axios dotenv compression
  • express: Express 웹 프레임워크
  • cors: Cross-Origin Resource Sharing을 가능하게 하는 미들웨어.
  • morgan: HTTP 요청 로거 미들웨어.
  • axios: Promise API를 활용하는 HTTP 비동기 통신 라이브러리
  • dotenv: .env 파일에서 환경 변수를 process.env로 로드하기 위한 도구.
  • compression: 데이터를 압축하여 전송하므로 네트워크 대역폭을 줄이고 응답 시간을 단축하여 웹 애플리케이션의 성능을 향상시키기 위한 미들웨어 (없어도 상관없음)

// app.js
//  express와 필요한 미들웨어를 요청
const express = require("express");
const cors = require("cors");
const morgan = require("morgan");
const axios = require("axios");
const compression = require("compression");
// 서버와 연결할 port 설정 및 express 초기화 
const app = express();
const port = 8080;
// 환경 변수 로드
require("dotenv").config();
// 미들웨어 설정
app.use(compression()); //응답 압축
app.use(morgan("dev")); // 로깅
app.use(cors());// CORS 처리
app.use(express.json()); // JSON 파싱

// compression 옵션 정의
app.use(
  compression({
    level: 6,
    threshold: 2 * 1024,
    filter: (req, res) => {
      if (req.headers["x-no-compression"]) {
        return false;
      }
      return compression.filter(req, res);
    },
  })
);

// .env에 설정한 API KEY를 가져옵니다.
const aladinApiKey = process.env.REACT_APP_ALADIN_API_KEY;
const naverClientId = process.env.REACT_APP_NAVER_CLIENT_ID;
const naverClientSecret = process.env.REACT_APP_NAVER_CLIENT_SECRET;

2. 필요한 API에 맞는 요청 URL을 선정해 정의

필자는 신간 전체 리스트 ,주목할 만한 신간 리스트 , 베스트셀러의 데이터가 필요해 해당 메뉴얼에서 base url을 변수로 설정해 각 필요한 QueryType만 변경해 API를 요청했습니다.

알라딘 Open API 메뉴얼
네이버 Search API 메뉴얼


const aladinApiBaseUrl = "https://www.aladin.co.kr/ttb/api/ItemList.aspx";
const aladinApiSearchUrl = "http://www.aladin.co.kr/ttb/api/ItemSearch.aspx";
const aladinApiLookUpUrl = "http://www.aladin.co.kr/ttb/api/ItemLookUp.aspx";
const naverApiBaseUrl = "https://openapi.naver.com/v1/search/book.json";

3. 클라이언트에서 받을 경로(엔드포인트) 를 정의

이 엔드포인트는 클라이언트의 요청에 응답하기 위한 경로

//HTTP 요청을 보낼 함수를 정의 
const fetchData = async (url, headers = {}) => {
  try {
    const response = await axios.get(url, { headers });
    return response.data;
  } catch (error) {
    throw new Error("에러 발생");
  }
};

// 알라딘의 베스트셀러 목록 가져오기
app.get("/bestseller", async (req, res) => {
  const queryType = "Bestseller";
  const aladinApiUrl = `${aladinApiBaseUrl}?ttbkey=${aladinApiKey}&QueryType=${queryType}&MaxResults=100&start=1&SearchTarget=Book&output=js&Cover=Big&CategoryId&Version=20131101`;
  try {
    //fetchData함수를 사용해 알라딘 API로부터 데이터를 가져옴
    const data = await fetchData(aladinApiUrl);
    res.json(data); // 가져온 데이터를 클라이언트에 json형식으로 응답
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// 신간도서 목록 가져오기 
app.get("/newbooks", async (req, res) => {
  const queryType = "ItemNewAll";
  const aladinApiUrl = `${aladinApiBaseUrl}?ttbkey=${aladinApiKey}&QueryType=${queryType}&MaxResults=100&start=1&SearchTarget=Book&output=js&Cover=Big&CategoryId&Version=20131101`;

  try {
    const data = await fetchData(aladinApiUrl);
    res.json(data);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});
// 주목받을 만한 책 목록 가져오기 
app.get("/special", async (req, res) => {
  const queryType = "ItemNewSpecial";
  const aladinApiUrl = `${aladinApiBaseUrl}?ttbkey=${aladinApiKey}&QueryType=${queryType}&MaxResults=100&start=1&SearchTarget=Book&output=js&Cover=Big&Version=20131101`;

  try {
    const data = await fetchData(aladinApiUrl);
    res.json(data);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});
  
// 네이버 검색 API와 알라딘 검색 API 동시에 사용 

app.get("/search", async (req, res) => {
  try {
    const { isbn, searchQuery } = req.query;
    let naverApiUrl = "";
    let aladinApiUrl = "";

    if (!isbn && !searchQuery) {
      return res
        .status(400)
        .json({ error: "ISBN 정보 또는 검색어가 필요합니다." });
    }

    if (isbn) {
      naverApiUrl = `${naverApiBaseUrl}?query=${isbn}`;
      aladinApiUrl = `${aladinApiLookUpUrl}?ttbkey=${aladinApiKey}&itemIdType=ISBN&ItemId=${isbn}&output=js&Cover=Big&Version=20131101&CategoryId`;
    } else {
      naverApiUrl = `${naverApiBaseUrl}?query=${encodeURIComponent(
        searchQuery
      )}`;
      aladinApiUrl = `${aladinApiSearchUrl}?ttbkey=${aladinApiKey}&Query=${encodeURIComponent(
        searchQuery
      )}&MaxResults=100&start=1&SearchTarget=Book&output=js&Cover=Big&Version=20131101&CategoryId`;
    }

    const naverHeaders = {
      "X-Naver-Client-Id": naverClientId,
      "X-Naver-Client-Secret": naverClientSecret,
    };

    const [naverData, aladinData] = await Promise.all([
      fetchData(naverApiUrl, naverHeaders),
      fetchData(aladinApiUrl),
    ]);

    res.json({ naverData, aladinData });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.listen(port, () => {
  console.log(`Listening on port ${port}...`);
});


마지막으로 터미널에 node app.js 를 실행하고 http://localhost:8080/bestseller 이런식으로 브라우저 url을 통해 받아온 json 데이터를 확인할 수 있습니다!

여기서 port는 임의로 설정했습니다

  • 예시
http://localhost:8080/newbooks
http://localhost:8080/special
http://localhost:8080/search?searchQuery=검색어
profile
미래의 나를 위한 기록

0개의 댓글