본문 바로가기
Rust/프로젝트

Rust로 백엔드 개발기(feat. 메이플스토리) - 04 캐릭터 정보 조회

by lms0806 2025. 3. 13.
728x90
반응형

이전 시간에는 maple story open api를 발급받는 방법에 대해서 다뤄보았습니다.

 

이번 시간에는 이전에 다뤄본 open api를 rust 프로젝트에서 사용하는 방법에 대해서 다뤄보고자 합니다.

axum에서 api 통신

기본적으로 axum은 서버로, rest api로 요청이 들어오는 경우, 해당 요청을 수행한 후 결과를 전달하는 역할을 합니다.

 

따라서, 서버에서 다른 서버로 rest api 통신을 진행하기 위해서는 axum이 아닌 다른 라이브러리를 사용해야 합니다.

 

해당 프로젝트에서는 "reqwest"를 사용하도록 하겠습니다.

 

다음과 같이 "Cargo.toml"의 "dependencies"에 추가해 줍니다.

reqwest = { version = "0.11", features = ["json"] }

캐릭터 식별자 조회

"reqwest"를 통하여 "캐릭터 식별자(ocid) 조회"를 하는 방법에 대해 이야기해보도록 하겠습니다.

 

가장 먼저 reqwest에서 사용할 라이브러리를 import 해줍니다.

use reqwest::{Client, header};

다음으로 ocid 값을 받아올 구조체를 만들어줍니다.

#[derive(Serialize, Deserialize)]
struct userocid {
    ocid: String,
}

ocid의 값을 json에서 받아올 것이고, 해당 값을 보내줘야 하므로 직렬화(Serialize), 역직렬화(Deserialize)를 지정해 줍니다.

 

이후 다음과 같이 코드를 작성해주면 됩니다.

async fn get_ocid() -> Result<Json<userocid>, (StatusCode, &'static str)> {
    let client = Client::new();

    // 요청할 API의 URL
    let url = "https://open.api.nexon.com/maplestory/v1/id?character_name={nickname}";

    // 요청 헤더 정의
    let mut headers = header::HeaderMap::new();
    headers.insert("x-nxopen-api-key", "{API_KEY}".parse().unwrap());

    // POST 요청 보내기
    let response = client
        .get(url)
        .headers(headers)
        .send()
        .await
        .expect("Failed to send request");

    println!("{}", response.status());

    // 응답 결과 확인
    if response.status().is_success() {
        // 성공한 경우
        let user_ocid: userocid = response
            .json()
            .await
            .expect("Failed to parse response JSON");

        //결과 출력
        Ok(Json(user_ocid))
    } else {
        //실패한 경우
        Err((StatusCode::BAD_REQUEST, "Failed to fetch OCID"))
    }
}

해당 request에서 실패한 경우는 캐릭터 명이 틀리거나, apiKey가 틀리거나 하는 수밖에 없지만, 만약의 경우를 대비하여 예외 처리를 진행해 주었습니다.

 

해당 request를 요청하게 되면 다음과 같이 ocid 값을 json 형식으로 보여지게 됩니다.

{
  "ocid": "ocid"
}

캐릭터 정보 조회

캐릭터 정보 조회시에는 앞 포스팅에서 이야기드린대로, 현재 날짜 - 1의 값이 필요합니다.

 

rust에서 현재 날짜를 불러오는데 사용할 라이브러리는 chrono와 chrono_tz를 사용할 예정입니다.

 

dependencise에 다음 내용을 추가해줍니다.

chrono = "0.4"
chrono-tz = "0.5"

다음과 같이 사용할 라이브러리르 import 해줍니다.

use chrono::{Duration, Utc};
use chrono_tz::Asia::Seoul;

open api를 활용하기 위해서는 날짜를 가져오되, "%Y-%m-%d" 형식으로 가져와야 합니다.

let now_time = (Utc::now() - Duration::days(1)) // 현재 시간 - 1
        .with_timezone(&Seoul)  // 서울 시간
        .format("%Y-%m-%d") // 형식
        .to_string(); // 문자열로 변경

전체 코드는 캐릭터 식별자 조회와 동일하게 반환 하되, 구조체와 url을 다르게 진행하면 됩니다.

 

구조체는 다음과 같이 필요한 정보들만 가져오도록 지정해줍니다.

#[derive(Serialize, Deserialize, Debug)]
struct userData {
    character_name: String,
    world_name: String,
    character_gender: String,
    character_class: String,
    character_class_level: String,
    character_level: i16,
    character_exp: i64,
    character_exp_rate: String,
    character_guild_name: String,
    character_image: String,
}

요청을 진행하는 전체 코드는 다음과 같습니다.

async fn get_user_info() -> Result<Json<userData>, (StatusCode, &'static str)> {
    let client = Client::new();
    let now_time = (Utc::now() - Duration::days(1))
        .with_timezone(&Seoul)
        .format("%Y-%m-%d")
        .to_string();

    // 요청할 API의 URL
    let url = format!(
        "https://open.api.nexon.com/maplestory/v1/character/basic?ocid={}&date={}",
        "{ocid}".to_string(),
        now_time.to_string()
    );

    // 요청 헤더 정의
    let mut headers = header::HeaderMap::new();
    headers.insert("x-nxopen-api-key", "{API_KEY}".parse().unwrap());

    // POST 요청 보내기
    let response = client
        .get(url)
        .headers(headers)
        .send()
        .await
        .expect("Failed to send request");

    println!("{}", response.status());
    // 응답 결과 확인
    if response.status().is_success() {
        let user_data: userData = response
            .json()
            .await
            .expect("Failed to parse response JSON");

        Ok(Json(user_data))
    } else {
        Err((StatusCode::BAD_REQUEST, "Failed to fetch OCID"))
    }
}

여기까지 rust reqwest 라이브러리를 활용하여 open api 통신하는 방법에 대해 다뤄보았습니다.

 

다음 시간에는, getOcid를 통하여 가져온 ocid값을 전역변수에 담아, 다른 api를 활용하는데 사용하는 방식으로 해당 코드를 개선해보도록 하겠습니다.

728x90
반응형

댓글