LostBoard 프로젝트

[LostBoard 프로젝트] API를 활용하여 데이터 받아오기

qweasd5123 2025. 1. 8. 02:09

axios 라이브러리를 활용하여 데이터 받아오기

 

1. 로스트아크 openAPI

https://developer-lostark.game.onstove.com/  사이트 접속

 

Lostark OpenAPI Developer Portal

Open API For All Developers START BUILDING YOUR OWN CLIENTS TODAY USING OFFICIAL DATA. GET ACCESS TO LOSTARK API

developer-lostark.game.onstove.com

Get access to lostark api 클릭 후 stove아이디로 로그인 후 api 키 생성

로그인 후 api 키 생성 버튼

 

api 키 발급 후 상단의 API Documents로 여러 값들을 테스트할 수 있다. 또한 GET, POST 요청에 필요한 url 형식을 알 수 있다.

 

캐릭터 테스트 화면. Try it out 버튼을 누르고 캐릭터 명을 입력하면 그 캐릭터의 원정대 정보를 받아올 수 있다.

 

2. 프로젝트 react 파일에 api 키 설정

 

api 키 값 .env 파일에 입력

REACT_APP_API_TOKEN = Bearer "API 키 값"

 

※주의 사항 ※

1. React 환경 변수는 반드시 REACT_APP_으로 시작해야 한다.

2. API 키 값 부분의 " "(쌍따옴표)를 제거해야 한다.

3. .env 파일의 위치는 src 밖(프로젝트의 루트 디렉토리)에 있어야 한다.

 

instance 설정

// instance.js
// Axios 라이브러리를 가져옵니다.
import axios from "axios";

// 환경 변수에 저장된 API 토큰을 가져옵니다.
// REACT_APP_API_TOKEN은 .env 파일에 정의되어 있어야 하며, React 애플리케이션에서 사용하기 위해 REACT_APP_ 접두사가 필요합니다.
const accessToken = process.env.REACT_APP_API_TOKEN;

// Axios 인스턴스를 생성합니다.
// 기본적으로 사용될 API의 baseURL과 헤더를 설정합니다.
const instance = axios.create({
  // API의 기본 URL (LostArk API 엔드포인트)
  baseURL: "https://developer-lostark.game.onstove.com",
  // 기본적으로 모든 요청에 포함될 헤더를 설정합니다.
  headers: {
    "content-type": "application/json;charset-UTF-8", // 요청 데이터의 형식을 JSON으로 설정
    accept: "application/json,", // 응답 데이터 형식을 JSON으로 기대
  },
});

// 요청 인터셉터를 설정합니다.
// 요청이 서버로 전송되기 전에 특정 작업을 수행합니다.
instance.interceptors.request.use(
  function (config) {
    // 모든 요청에 Authorization 헤더를 추가합니다.
    // 여기서 `accessToken`은 API 서버에서 인증을 위해 요구하는 값입니다.
    config.headers.authorization = accessToken;
    return config; // 수정된 요청 설정을 반환
  },
  function (error) {
    // 요청을 보내기 전에 발생한 에러를 처리합니다.
    return Promise.reject(error); // 에러를 거부하여 이후의 처리를 중단
  }
);

// 위에서 설정한 Axios 인스턴스를 내보냅니다.
// 다른 파일에서 `instance`를 import하여 API 요청에 사용할 수 있습니다.
export default instance;

 

instance.js를 활용하여 데이터 값 받아오기

//Board.js
import instance from '../instance';
import { useEffect, useState } from 'react';

function Board() {
    let state = useSelector((state) => state.characterName); // Redux state
    let [characterData, setCharacterData] = useState([]);

    const getAPIData = async () => {
        try {
            const res = await instance({
                method: "get",
                url: `/characters/${state}/siblings`, // Redux state에 저장된 캐릭터 명 활용
                data: {
                    CharacterName: state, // state에 저장된 캐릭터명의 원정대 값 받아오기
                },
            });
            setCharacterData(res.data); // 데이터 상태 업데이트
        } catch (error) {
            console.error("Error fetching data:", error);
        }
    };
    useEffect(() => {
        getAPIData();
    }, []);
    console.log(characterData)
}

 

출력된 데이터

[
  {
    "ServerName": "아브렐슈드",
    "CharacterName": "이모쿠크다스좀",
    "CharacterLevel": 50,
    "CharacterClassName": "데빌헌터",
    "ItemAvgLevel": "1,100.00",
    "ItemMaxLevel": "1,100.00"
  },
  {
    "ServerName": "아브렐슈드",
    "CharacterName": "이모주먹좀",
    "CharacterLevel": 70,
    "CharacterClassName": "브레이커",
    "ItemAvgLevel": "1,584.17",
    "ItemMaxLevel": "1,584.17"
  },
  {
    "ServerName": "아브렐슈드",
    "CharacterName": "이모힐좀",
    "CharacterLevel": 70,
    "CharacterClassName": "홀리나이트",
    "ItemAvgLevel": "1,643.33",
    "ItemMaxLevel": "1,643.33"
  },
  {
    "ServerName": "아브렐슈드",
    "CharacterName": "이모물좀",
    "CharacterLevel": 70,
    "CharacterClassName": "리퍼",
    "ItemAvgLevel": "1,640.00",
    "ItemMaxLevel": "1,640.00"
  },
  {
    "ServerName": "아브렐슈드",
    "CharacterName": "이모낫좀",
    "CharacterLevel": 70,
    "CharacterClassName": "소울이터",
    "ItemAvgLevel": "1,585.00",
    "ItemMaxLevel": "1,585.00"
  },
  {
    "ServerName": "아브렐슈드",
    "CharacterName": "이모마늘빵좀",
    "CharacterLevel": 70,
    "CharacterClassName": "데빌헌터",
    "ItemAvgLevel": "1,680.83",
    "ItemMaxLevel": "1,680.83"
  },
  {
    "ServerName": "아브렐슈드",
    "CharacterName": "이모단검좀",
    "CharacterLevel": 70,
    "CharacterClassName": "블레이드",
    "ItemAvgLevel": "1,680.00",
    "ItemMaxLevel": "1,680.00"
  },
  {
    "ServerName": "아브렐슈드",
    "CharacterName": "이모총좀",
    "CharacterLevel": 70,
    "CharacterClassName": "건슬링어",
    "ItemAvgLevel": "1,660.00",
    "ItemMaxLevel": "1,660.00"
  },
  {
    "ServerName": "아브렐슈드",
    "CharacterName": "이모나쵸좀",
    "CharacterLevel": 61,
    "CharacterClassName": "인파이터",
    "ItemAvgLevel": "1,540.00",
    "ItemMaxLevel": "1,540.00"
  }
]

 

3. 받아온 데이터 활용

// Board.js
import Grid from '@mui/material/Grid2';
import instance from '../instance';

function Board(){
	// API로 데이터 받아오기
    
    // 필터링: ItemAvgLevel이 500.00 이하인 객체 제거
    const filteredData = characterData.filter(item => {
        const itemLevel = parseFloat(item.ItemAvgLevel.replace(/,/g, ""));
        return itemLevel > 500.00; // 500.00 초과만 포함
    });

    // 정렬: ItemAvgLevel 기준으로 내림차순 정렬
    const sortedData = filteredData.sort((a, b) => {
        const aLevel = parseFloat(a.ItemAvgLevel.replace(/,/g, ""));
        const bLevel = parseFloat(b.ItemAvgLevel.replace(/,/g, ""));
        return bLevel - aLevel; // 내림차순
    });
    
	return (
        <div className='content'>          
            <Grid container spacing={{ xs: 2, md: 3 }} columns={{ xs: 4, sm: 8, md: 12 }}>
                {sortedData.map((a, i) => (
                    <Grid key={i} size={{ xs: 2, sm: 4, md: 4 }} container spacing={2}>
                        <Grid item xs={8}>
                            <img src={process.env.PUBLIC_URL + '/class_logo/' + a.CharacterClassName + '.png'} width="30%" />
                            <p>{a.CharacterClassName}</p>
                            <p>{a.CharacterName}</p>
                            <p>{a.ItemAvgLevel}</p>
                        </Grid>
                        
                    </Grid>
                ))}
            </Grid>
        </div>
    )
}

export default Board

 

 

4. Board 화면