[메이플스토리 Open API] 공통 Fetch 함수로 데이터 요청 최적화하기

2025. 1. 16. 22:27·FrontEnd

개인 프로젝트를 구상하다가 재미있고 애정이 가는 프로젝트를 해보고 싶었습니다. 삶에 유익한 Open API도 많지만, 메이플스토리 Open API를 활용하여 maple.gg 같은 종합 통계 페이지를 만들어보기로 했습니다.


☑️ 목표

우선 메인 페이지에 카테고리별 랭킹 데이터를 노출시켜 보는 것부터 시작했습니다. 메이플스토리 Open API를 통해 제공되는 다양한 데이터를 활용하며, 첫 번째로 종합 랭킹(overall)과 유니온 랭킹(union) 데이터를 가져오는 기능을 구현했습니다.

 


☑️ 메이플스토리 Open API 소개

메이플스토리 Open API는 Nexon Open API 문서를 통해 제공되며, 유저 데이터를 활용할 수 있도록 다양한 엔드포인트를 제공합니다.

API Key 발급 및 환경 변수 설정

먼저, 문서에 따라 Nexon Developer Center에서 API Key를 발급받고 프로젝트의 .env 파일에 설정했습니다.

REACT_APP_MAPLE_KEY=YOUR_API_KEY_HERE
REACT_APP_BASE_URL=https://open.api.nexon.com

 


☑️ 랭킹 데이터 가져오기

API 사용 예제는 문서에서 아래와 같은 형태로 제공됩니다.

const API_KEY = "YOUR API KEY HERE";
const characterName = "CHARACTER NAME";
const urlString = "https://open.api.nexon.com/heroes/v1/id?character_name=" + characterName;

fetch(urlString, {
  headers: {
    "x-nxopen-api-key": API_KEY,
  },
})
  .then((response) => response.json())
  .then((data) => console.log(data))
  .catch((error) => console.error(error));

 


☑️ 랭킹 데이터 Fetch 구현

저는 우선 종합 랭킹(overall)과 유니온 랭킹(union) 데이터를 가져와 메인 컴포넌트에 렌더링하도록 구현했습니다.

초기 구현 코드

아래는 Main 컴포넌트에서 각각의 데이터를 가져오는 초기 코드입니다.

useEffect(() => {
  const overallFetch = async () => {
    try {
      const response = await fetch(urlString, {
        headers: {
          "x-nxopen-api-key": API_KEY || "",
        },
      });
      if (!response.ok) {
        throw new Error(`error: ${response.status}`);
      }

      const data = await response.json();
      setOverallRanking(data.ranking);
    } catch (error) {
      console.error(error);
    }
  };

  const unionFetch = async () => {
    try {
      const response = await fetch(urlString, {
        headers: {
          "x-nxopen-api-key": API_KEY || "",
        },
      });
      if (!response.ok) {
        throw new Error(`error: ${response.status}`);
      }

      const data = await response.json();
      setUnionRanking(data.ranking);
    } catch (error) {
      console.error(error);
    }
  };

  overallFetch();
  unionFetch();
}, [urlString]);

☑️ 코드 단순화 및 개선

하지만 위 코드는 중복된 데이터 요청 로직이 포함되어 있어, 데이터를 더 많이 가져와야 하는 경우 유지보수가 어려워질 수 있습니다. 이를 개선하기 위해 공통된 로직을 함수로 추출하고 재사용 가능한 방식으로 리팩터링했습니다.

공통 Fetch 함수 추출

먼저, 데이터를 가져오는 공통 로직을 함수로 추출했습니다. 제네릭(Generic) 을 사용해 다양한 데이터 타입을 처리할 수 있도록 구현했습니다.

const fetchRanking = async <T,>(
  endpoint: string,
  setData: (data: T[]) => void
) => {
  try {
    const response = await fetch(endpoint, {
      headers: {
        "x-nxopen-api-key": API_KEY || "",
      },
    });

    if (!response.ok) {
      throw new Error(`error: ${response.status}`);
    }

    const data = await response.json();
    setData(data.ranking);
  } catch (error) {
    console.error(error);
  }
};

URL 변수화 및 데이터 요청 단순화

Main 컴포넌트에서 URL을 변수로 관리하여 가독성을 높였습니다. 또한, 공통 Fetch 함수를 호출하여 데이터를 가져오는 로직을 단순화했습니다.

const overallUrl = `${BASE_URL}/ranking/overall?date=${todayDate}&page=1`;
const unionUrl = `${BASE_URL}/ranking/union?date=${todayDate}&page=1`;

useEffect(() => {
  fetchRanking<OverallRanking>(overallUrl, setOverallRanking);
  fetchRanking<UnionRanking>(unionUrl, setUnionRanking);
}, [overallUrl, unionUrl]);

☑️ 최종 구현 코드

import { FC, useEffect, useState } from "react";
import { getTodayDate } from "../../utils/getTodayDate.utils";
import { OverallRanking, UnionRanking } from "../../types/ranking.types";
import Overall from "../../components/ranking/overall";
import Union from "../../components/ranking/union";
import "./main.style.scss";

const API_KEY = process.env.REACT_APP_MAPLE_KEY;
const BASE_URL = process.env.REACT_APP_BASE_URL;

const fetchRanking = async <T,>(
  endpoint: string,
  setData: (data: T[]) => void
) => {
  try {
    const response = await fetch(endpoint, {
      headers: {
        "x-nxopen-api-key": API_KEY || "",
      },
    });

    if (!response.ok) {
      throw new Error(`error: ${response.status}`);
    }

    const data = await response.json();
    setData(data.ranking);
  } catch (error) {
    console.error(error);
  }
};

const Main: FC = () => {
  const todayDate = getTodayDate();
  const [overallRanking, setOverallRanking] = useState<OverallRanking[]>([]);
  const [unionRanking, setUnionRanking] = useState<UnionRanking[]>([]);

  const overallUrl = `${BASE_URL}/ranking/overall?date=${todayDate}&page=1`;
  const unionUrl = `${BASE_URL}/ranking/union?date=${todayDate}&page=1`;

  useEffect(() => {
    fetchRanking<OverallRanking>(overallUrl, setOverallRanking);
    fetchRanking<UnionRanking>(unionUrl, setUnionRanking);
  }, [overallUrl, unionUrl]);

  return (
    <section id="main">
      <h1>Main</h1>
      <ul>
        <li>
          <Overall overallRanking={overallRanking} />
        </li>
        <li>
          <Union unionRanking={unionRanking} />
        </li>
      </ul>
    </section>
  );
};

export default Main;

'FrontEnd' 카테고리의 다른 글

[메이플스토리 Open API] React Query로 API 요청 최적화하기  (1) 2025.01.20
Spotify 프로젝트 기록 일지(1)  (1) 2024.12.23
'FrontEnd' 카테고리의 다른 글
  • [메이플스토리 Open API] React Query로 API 요청 최적화하기
  • Spotify 프로젝트 기록 일지(1)
FE Dev. 굼지
FE Dev. 굼지
굼지의 웹 개발 레시피 입니다.
  • FE Dev. 굼지
    굼지의 웹 개발 레시피
    FE Dev. 굼지
    • 분류 전체보기 (14)
      • FrontEnd (3)
      • React (3)
      • Next (8)
      • React-Native (0)
  • 블로그 메뉴

    • 홈
    • 태그
  • 최근 글

FE Dev. 굼지
[메이플스토리 Open API] 공통 Fetch 함수로 데이터 요청 최적화하기
상단으로

티스토리툴바