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

Rust로 백엔드 개발기(feat. 메이플스토리) - 07 Null 제외하는 방법

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

이번 시간에는 몇가지 기능을 추가 개발하면서, rust에는 없는 null관련 데이터를 가져오는 방법에 대해 배워보도록 하겠습니다.

 

rust에는 null이 없지만 response로 받은 json에 null값이 포함되어 있는 경우에 대하여 대처할 수 있습니다.

방법 1 Option

rust에는 Option이라는 함수를 통하여 해당 값이 있는 경우와 없는 경우로 나눠서 체크할 수 있습니다.

 

다음과 같이 skill에 대한 정보를 불러오는 구조체가 있다고 생각해봅시다.

pub struct SkillInfo {
    pub skill_name: String,
    pub skill_description: String,
    pub skill_level: i8,
    pub skill_effect: Option<String>,
    pub skill_icon: String,
    pub skill_effect_next: Option<String>,
}

#[derive(Deserialize, Serialize, Debug)]
pub struct CharacterSkill {
    pub character_skill: Vec<SkillInfo>,
}

skill_effect에 값으로 null이 올 수 있으므로 Option<String>으로 만들어줍니다.

 

이후 다음과 같이 값을 요청받은 결과를 받아오게 된 경우, null이 포함될 수 있습니다.

let user_character_skill: CharacterSkill = response
    .json()
    .await
    .expect("Failed to parse response JSON");

그런 경우 다음과 같이 filter를 활용하여 처리가 가능합니다.

let filter_character_skill: CharacterSkill = CharacterSkill {
    character_skill: user_character_skill
        .character_skill
        .into_iter()
        .map(|skill| SkillInfo {
            skill_name: skill.skill_name,
            skill_description: skill.skill_description,
            skill_level: skill.skill_level,
            skill_effect: Some(skill.skill_effect.unwrap_or_default()),
            skill_icon: skill.skill_icon,
            skill_effect_next: Some(skill.skill_effect_next.unwrap_or_default()),
        })
        .collect(),
};

Some(skill.skill_effect.unwrap_or_default()) 만약 어떠한 값이 있다면 그 값을 넣고, 아닌 경우 unwrap_or_default()를 통해 기본값으로 만들 수 있습니다.

 

그러나, 이렇게 하는 경우, 값으로 받아온 객체 뿐만 아니라 새로운 객체를 만들어서 반환하기 때문에 메모리적으로 불리하게 작동할 수 있습니다.

 

그렇다면 어떤 방법이 있을까요?

방법 2 serde_as (추천)

serde_as라는 외부 라이브러리를 통하여 같은 결과를 받아올 수 있습니다.

#[serde_as]
#[derive(Deserialize, Serialize, Debug)]
pub struct SkillInfo {
    pub skill_name: String,
    pub skill_description: String,
    pub skill_level: i8,
    #[serde_as(deserialize_as = "DefaultOnNull")]
    pub skill_effect: String,
    pub skill_icon: String,
    #[serde_as(deserialize_as = "DefaultOnNull")]
    pub skill_effect_next: String,
}

#[derive(Deserialize, Serialize, Debug)]
pub struct CharacterSkill {
    pub character_skill: Vec<SkillInfo>,
}

다음과 같이 skill_effectOption<String>대신 String으로 주어지고, #[serde_as(deserialize_as = "DefaultOnNull")]와 같은 태그를 붙여 만약 null인 경우 ""으로 치환하도록 해줍니다.

 

그러면 기존에 .filter()를 활용해서 만들던 로직을 수행하지 않아도 같은 결과를 만들어낼 수 있습니다.

 

다음 시간에는 user_ocid 값을 어떻게 사용자별로 사용하여 api를 호출할 수 있는지에 대해 다뤄보고자 합니다.

728x90
반응형

댓글