[React] Swagger 문서 기반 Axios API 요청 구조 세팅하기

DoHyeon Kim·2026년 5월 26일

React

목록 보기
11/15
post-thumbnail

프론트엔드 개발에서 API 연동은 필수적인 작업이다.
하지만 API 문서를 제대로 확인하지 않은 상태에서 개발을 진행하면 요청 형식이나 응답 데이터 구조를 정확히 파악하기 어려운 경우가 많다.

특히 백엔드와 협업하는 과정에서는 엔드포인트나 파라미터가 변경되기도 하고, 요청 데이터 구조가 수정되는 경우도 있기 때문에 명세서를 기반으로 API 구조를 관리하는 것이 중요하다.

이번 프로젝트에서는 Swagger 문서를 참고하여 Axios 기반 API 요청 구조를 구성하였다.


테스트 토큰 및 CORS 설정 요청

로그인 기능이 완성되기 전에는 API 테스트를 위해 백엔드에서 임시 테스트 토큰을 발급받아 사용하였다.

이때 함께 요청했던 내용은 다음과 같다.

  • 최대한 긴 유효기간의 테스트 토큰 발급
  • localhost:5173에서 오는 요청에 대한 CORS 허용
  • 프론트 배포 이후에는 배포 주소에 대한 CORS 허용

환경변수 설정

.env 파일을 생성하여
Base URL과 테스트 토큰 등을 관리하였다.

VITE_SERVER_URL_API=https://example-server.store/api/
VITE_TEST_TOKEN=your_test_token
VITE_NAVER_MAPS_CLIENT_ID=your_client_id

환경변수로 분리하면 서버 주소 변경이나 토큰 변경 시 유지보수가 훨씬 편해진다.


Vite Proxy 설정

로컬 개발 환경에서 발생하는 CORS 문제를 줄이기 위해 vite.config.js에서 Proxy 설정을 추가하였다.

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import svgr from 'vite-plugin-svgr';
export default defineConfig({
  plugins: [react(), svgr()],
  server: {
    proxy: {
      '/api': {
        target: 'https://example-server.store',
        changeOrigin: true,
        secure: false,
      },
    },
  },
});

Axios 인스턴스 생성

API 요청을 공통 관리하기 위해 Axios 인스턴스를 별도로 생성하였다.

// api.js
import axios from 'axios';
// localStorage에서 accessToken 가져오기
export const getAccessToken = () => {
  return localStorage.getItem('accessToken');
};
// localStorage에서 refreshToken 가져오기
export const getRefreshToken = () => {
  return localStorage.getItem('refreshToken');
};
// 테스트용 토큰
const testToken = import.meta.env.VITE_TEST_TOKEN;
// axios 인스턴스 생성
export const api = axios.create({
  baseURL: import.meta.env.VITE_SERVER_URL_API,
  headers: {
    'Content-Type': 'application/json',
  },
});
// 요청 인터셉터
api.interceptors.request.use(
  (config) => {
    let token = getAccessToken();
    if (!token) {
      console.warn(
        'Access token이 없어 테스트 토큰을 사용합니다.'
      );
      token = testToken;
    }
    config.headers['Authorization'] = `Bearer ${token}`;
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);
  • baseURL
    • 공통 서버 주소 관리
  • interceptors
    • 모든 요청에 Authorization 헤더 자동 추가

Swagger 문서 확인

Swagger 문서를 통해 API 연결에 필요한 정보를 먼저 확인하였다.

  • 요청 방식 (GET, POST)
  • Query Parameter
  • Request Body
  • Response Data 구조

특히 응답 데이터의 경우, 실제 화면에서 사용할 필드가 어떤 구조로 내려오는지 확인하는 것이 중요하다.


API 함수 분리

API 요청 로직은 /apis 폴더 내부에서 기능별로 분리하여 관리하였다.
아래 예시는 숙련도별 테마 리스트를 조회하는 API이다.

// getProficiencyListAPI.js

import { api } from '../API';

export const getProficiencyListAPI = async (proficiency, page) => {
  try {
    const response = await api.get('themes/home/proficiency', {
      params: {
        proficiency,
        page,
      },
    });

    return {
      profName: response.data.profName,
      profDescription: response.data.profDescription,
      contents: response.data.proficiencyDataList.contents,
    };
  } catch (error) {
    console.error('API 요청 중 오류 발생:', error);
    throw error;
  }
};

Swagger 응답 구조에 맞춰 데이터 가공

Swagger 응답 예시를 확인하면 profName, profDescription, proficiencyDataList.contents와 같은 필드를 확인할 수 있다.

따라서 API 함수 내부에서 필요한 데이터만 정리해서 반환하도록 구성하였다.

return {
  profName: response.data.profName,
  profDescription: response.data.profDescription,
  contents: response.data.proficiencyDataList.contents,
};

페이지에서 API 사용

페이지에서는 useEffect를 사용하여 API 데이터를 불러오도록 구성하였다.

useEffect(() => {
  const fetchStudies = async () => {
    try {
      const response = await getProficiencyListAPI(level, page);

      setProfName(response.profName);
      setProfDescription(response.profDescription);
      setCafeLists(response.contents);
    } catch (error) {
      console.error(
        '카페 목록 데이터를 불러오는 중 오류 발생:',
        error
      );
    }
  };

  fetchStudies();
}, [level, page]);

level이나 page 값이 변경될 때마다 API를 다시 호출하여
현재 조건에 맞는 데이터를 화면에 반영할 수 있도록 하였다.


데이터 렌더링

API에서 받아온 리스트 데이터는 map을 사용하여 화면에 렌더링하였다.

return (
  <Wrapper>
    {cafeLists.map((cafe) => (
      <TableRow key={cafe.themeId}>
        <TableData>{cafe.cityName}</TableData>
        <TableData>{cafe.townName}</TableData>
        <TableData>{cafe.pointName}</TableData>
        <TableData>{cafe.themeName}</TableData>
      </TableRow>
    ))}
  </Wrapper>
);

Swagger 문서를 기준으로 응답 구조를 확인하고 API 함수에서 필요한 데이터만 정리해두면, 페이지 컴포넌트의 코드가 훨씬 단순해진다.

또한 API 변경이 발생했을 때도 페이지 전체를 수정하기보다 API 함수의 반환 구조만 조정하면 되기 때문에 유지보수 측면에서도 유리하다.

profile
끄적끄적

0개의 댓글