RoomE / 알라딘 도서 검색 API 사용시 CORS 에러 발생

프로젝트 기록트러블 슈팅
avatar
2025.02.27
·
5 min read

3633

와우 벌써 일주일이나 기록이 밀리다니...

정확히 일주일 전에 노션에 정리해놨던 내용인데, 이제야 여유가 좀 생겨서 오늘 마저 정리할 수 있었다🥲

오늘의 이슈

알라딘 Open API를 호출하는 과정에서 이슈가 있었다.

브라우저의 보안 정책인 CORS(Cross-Origin Resource Sharing) 에러가 발생했는데, 이는 다른 출처의 리소스에 대한 접근을 제한하는 중요한 보안 메커니즘이다. 확인해보니 브라우저 콘솔에 'Access to XMLHttpRequest at '<http://www.aladin.co.kr/ttb/api/ItemSearch.aspx>' has been blocked by CORS policypolicy'라는 오류 메시지가 떴다.

프론트엔드(localhost:5173)와 알라딘 API 서버의 도메인이 달라서 브라우저의 Same-Origin Policy 때문에 다른 도메인(aladin.co.kr)으로의 직접적인 API 요청이 차단된 것이었다.

오류 발생 상황

  • API 호출 로직 (apis/book.ts)

  /**
   * 알라딘 도서 검색
   * @param keyword 검색 키워드
   * @returns 알라딘 도서 검색 결과
   */
  searchAladinBooks: async (keyword: string) => {
    const params = {
      ttbkey: ALADIN_KEY,
      Query: keyword,
      QueryType: 'Keyword',
      MaxResults: 10,
      start: 1,
      SearchTarget: 'Book',
      output: 'JS',
      Version: '20131101',
    };

    const response = await axios.get(
      '<http://www.aladin.co.kr/ttb/api/ItemSearch.aspx>',
      {
        params,
      },
    );
    return response.data;
  },
  • 결과 (오류 발생)

363036313632

/

시도한 것

  1. Vite 개발 서버에 프록시 설정 추가

// vite.config.ts
export default defineConfig({
  server: {
    proxy: {
      '/api/aladin': {
        target: '<http://www.aladin.co.kr>',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\\\\\\\\/api\\\\\\\\/aladin/, '')
      }
    }
  }
})

  1. API 호출 URL 변경

// 변경 전
const response = await axios.get('<http://www.aladin.co.kr/ttb/api/ItemSearch.aspx>');

// 변경 후
const response = await axios.get('/api/aladin/ttb/api/ItemSearch.aspx');

해결

  • API 호출 로직(apis/book.ts)

  /**
   * 알라딘 도서 검색
   * @param keyword 검색 키워드
   * @returns 알라딘 도서 검색 결과
   */
  searchAladinBooks: async (keyword: string) => {
    const params = {
      ttbkey: ALADIN_KEY,
      Query: keyword,
      QueryType: 'Keyword',
      MaxResults: 10,
      start: 1,
      SearchTarget: 'Book',
      output: 'JS',
      Version: '20131101',
    };

    try {
      const response = await axios.get('/api/aladin/ttb/api/ItemSearch.aspx', {
        params,
        headers: {
          Accept: 'application/json, text/plain, */*',
          'Content-Type': 'application/json;charset=utf-8',
        },
      });

      if (response.data && typeof response.data === 'string') {
        return JSON.parse(response.data);
      }
      return response.data;
    } catch (error) {
      console.error('알라딘 API 호출 오류:', error);
      throw error;
    }
  },

  • proxy 설정 (vite.config.js)

export default defineConfig({
  server: {
    proxy: {
      '/api/aladin': {
        target: '<http://www.aladin.co.kr>',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\\/api\\/aladin/, ''),
        configure: (proxy, options) => {
          proxy.on('proxyReq', (proxyReq, req, res) => {
            proxyReq.setHeader('Accept', 'application/json, text/plain, */*');
            proxyReq.setHeader(
              'Content-Type',
              'application/json;charset=utf-8',
            );
          });
          proxy.on('proxyRes', (proxyRes, req, res) => {
            proxyRes.headers['content-type'] = 'application/json;charset=utf-8';
          });
        },
      },
    },
  },
  // ... 기존 코드

느낀 점

프록시가 무엇이고 왜 필요한지에 대해 오늘 자세히 배웠다. 프록시는 클라이언트와 서버 사이에서 중개자 역할을 하는데, 이를 통해 CORS 정책을 우회하여 다른 도메인의 API를 호출할 수 있다.

특히 개발 환경에서는 Vite의 프록시 설정만으로도 이 문제를 해결할 수 있어서 백엔드를 거치지 않고 완료할 수 있었다.

실제 서비스 환경에서는 백엔드 서버가 이 프록시 역할을 수행해야 하지만, 이번 케이스처럼 특정한 부분만 외부 API를 호출하는 경우에는 이런 방식으로 문제를 해결할 수 있을 것 같다.







- 컬렉션 아티클