React

[React] APP 오픈 API CORS에러 NAVER geocode API

차노도리 2023. 4. 8. 17:39

 

React에서 오픈 API 사용시 CORS에러 이유 

ex) 

  • 클라이어트에서 외부 API서버로 바로 요청을 보내서

 

해결 방법

  • client to server 찌르는게 아니라 server to server로 Middleware를 통해서 찌른다.

 

 

예시 코드

  • Naver API geocode 사용
  • Next 서버르 통해서 통신

 

https://api.ncloud-docs.com/docs/ai-naver-mapsgeocoding-geocode

 

geocode

 

api.ncloud-docs.com

 

next로 통실한 함수 생성

import axios from 'axios';
import { NextApiRequest, NextApiResponse } from 'next';

const NEXT_PUBLIC_NAVER_MAP_API_URL = 'https://naveropenapi.apigw.ntruss.com';
const NEXT_PUBLIC_NAVER_MAP_CLIENT_ID_KEY = {애플리케이션 등록 시 발급받은 client id값}
const NEXT_PUBLIC_NAVER_MAP_CLIENT_ID_SECRET = {애플리케이션 등록 시 발급받은 client secret값}

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  try {
    const { data } = await axios.get(`${NEXT_PUBLIC_NAVER_MAP_API_URL}/map-geocode/v2/geocode`, {
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
        'X-NCP-APIGW-API-KEY-ID': NEXT_PUBLIC_NAVER_MAP_CLIENT_ID_KEY,
        'X-NCP-APIGW-API-KEY': NEXT_PUBLIC_NAVER_MAP_CLIENT_ID_SECRET,
      },
      params: { query: decodeURIComponent(req.query.query as string) },
    });
    res.status(200).json(data.addresses);
  } catch (error) {
    logger.error(error);
    res.status(error.response.status).json({ message: error.response.statusText });
  }
}

 

타입 정의 (안해도됨)

/**
 * Naver Map geocode 얻기 검색 메타 데이터
 */
export type NaverMapGeocodingMeta = {
  /**
   * 총 검색 건수
   */
  totalCount?: number;
  /*
   * 현재 페이지 번호
   */
  page?: number;
  /**
   * 페이지 내 결과 개수
   */
  count?: number;
};

/**
 * Naver Map geocode 얻기 주소를 이루는 요소들
 */
export type NaverMapGeocodingAddressesElements = {
  types: string[];
  longName: string;
  shortName: string;
  code: string;
};

/**
 * Naver Map geocode 얻기 주소 검색 결과 목록
 */
export type NaverMapGeocodingAddresses = {
  /**
   * 도로명 주소
   */
  roadAddress?: string;
  /**
   * 지번 주소
   */
  jibunAddress?: string;
  /**
   * 영어 주소
   */
  englishAddress?: string;
  /**
   * x 좌표(경도)
   */
  x?: string;
  /**
   * y 좌표(위도)
   */
  y?: string;
  /**
   * 검색 중심 좌표로부터의 거리(단위: 미터)
   */
  distance?: number;
  /**
   * 주소를 이루는 요소들
   */
  addressElements?: NaverMapGeocodingAddressesElements[];
};

/**
 * Naver Map geocode 얻기 request
 */
export interface NaverMapGeocodingParameters {
  /**
   * 주소
   */
  query: string;
  /**
   * - 검색 중심 좌표
   * 'lon,lat' 형식으로 입력
   */
  coordinate?: string;
  /**
   * - 검색 결과 필터링 조건
   * '필터 타입@코드1;코드2;... ' 형식으로 입력
   * 제공하는 필터 타입은 다음과 같음:
   * HCODE: 행정동 코드
   * BCODE: 법정동 코드
   * 예) HCODE@4113554500;4113555000
   */
  filter?: string;
  /**
   * - language=eng 추가 시 영문 주소 검색 활성화
   * 기본값: kor
   */
  language?: string;
  /**
   * - 페이지 번호
   * 기본값: 1
   */
  page?: number;
  /**
   * - 결과 목록 크기
   * 입력 범위: 1~100
   * 기본값: 10
   */
  count?: number;
}

/**
 * Naver Map geocode 얻기 response
 */
export interface NaverMapGeocodingResponse {
  /**
   * 검색 결과 상태 코드
   */
  status: string;
  /**
   * 예외 발생 시 메시지
   */
  errorMessage?: string;
  /**
   * 검색 메타 데이터
   */
  meta?: NaverMapGeocodingMeta;
  /**
   * 주소 검색 결과 목록
   */
  addresses?: NaverMapGeocodingAddresses[];
}

 

 

사용 방법

      const { data: roadNameAddressData } = await axios.get<NaverMapGeocodingAddresses[]>(
          `${globalThis.process.env['NEXT_PUBLIC_SERVICES_HTTPS_URL']}/api/msa/naver`,
          {
            params: {
              query: addressGroup.lotNumberAddress,
            },
          },
        );