Menu
Coddy logo textTech

Option Enum 다시 살펴보기

Coddy Rust 여정의 Object Oriented Programming 섹션에 포함된 레슨 — 61개 중 17번째.

이미 Rust에서 Option<T>를 접해 보셨을 것입니다. 이는 존재할 수도 있고 존재하지 않을 수도 있는 값을 나타내기 위한 표준 열거형(enum)입니다. 이제 이를 OOP의 관점에서 살펴보겠습니다. Option은 단순한 열거형이 아니라, null이 될 수 있는(nullable) 값을 안전하고 우아하게 처리할 수 있게 해주는 강력한 내장 메서드들을 가진 타입입니다.

매번 매칭하는 대신, Option 값에서 직접 메서드를 사용할 수 있습니다. unwrap_or 메서드는 내부 값이 존재하면 그 값을 반환하고, 그렇지 않으면 제공된 기본값을 반환합니다:

let maybe_name: Option<String> = Some(String::from("Alice"));
let name = maybe_name.unwrap_or(String::from("Guest"));
println!("{}", name);  // Alice

let empty: Option<String> = None;
let fallback = empty.unwrap_or(String::from("Guest"));
println!("{}", fallback);  // Guest

map 메서드는 내부 값이 존재하면 그 값을 변환하고, None은 변경하지 않은 상태로 둡니다. 이를 통해 None인지 매번 확인하지 않고도 연산을 체이닝할 수 있습니다:

let maybe_num: Option<i32> = Some(5);
let doubled = maybe_num.map(|x| x * 2);
println!("{:?}", doubled);  // Some(10)

let nothing: Option<i32> = None;
let still_nothing = nothing.map(|x| x * 2);
println!("{:?}", still_nothing);  // None

이러한 메서드들은 OOP 원칙을 구현합니다. Option 타입은 "값이 있을 수도 있음"이라는 개념을 캡슐화하며 이를 다루기 위한 깔끔한 인터페이스를 제공합니다. 객체를 조사하기 위해 외부 로직을 작성하는 대신 객체의 메서드를 호출하게 됩니다.

challenge icon

챌린지

쉬움

Option 메서드를 사용하여 선택적 데이터를 우아하게 처리하는 사용자 프로필 시스템을 구축해 봅시다. 사용자는 닉네임을 설정했을 수도 있고 설정하지 않았을 수도 있습니다. 여러분의 시스템은 명시적인 매칭 없이 두 경우를 모두 우아하게 처리할 것입니다.

코드를 구성하기 위해 두 개의 파일을 생성합니다:

  • profile.rs: 두 개의 필드 username (String)과 nickname (Option<String>)을 가진 공개 Profile 구조체를 정의합니다. 다음을 구현하세요:
    • username과 선택적인 nickname을 인자로 받는 new 생성자
    • 닉네임이 존재하면 닉네임을 반환하고, 존재하지 않으면 username을 폴백(fallback)으로 반환하는 display_name 메서드 — 이를 처리하기 위해 unwrap_or를 사용하세요
    • 닉네임이 존재하면 대괄호로 감싸진 닉네임(예: "[CoolNick]")을 포함하는 Option<String>을 반환하고, 닉네임이 없으면 None을 반환하는 formatted_nickname 메서드 — 값을 변환하기 위해 map을 사용하세요
  • main.rs: profile 모듈을 가져와서 닉네임이 있는 프로필과 없는 프로필 두 개를 생성합니다. 각 프로필에서 두 메서드를 모두 실행하여 Option 메서드가 값이 있는 경우와 없는 경우를 어떻게 다르게 처리하는지 보여주세요.

formatted_nickname 메서드는 Option을 반환하므로, 출력할 때 디버그 포맷팅({:?})을 사용하세요.

출력은 두 프로필을 모두 보여주는 다음 형식을 정확히 따라야 합니다:

Display name: {name}
Formatted nickname: {option}
Display name: {name}
Formatted nickname: {option}

예를 들어, username이 "alice"이고 nickname이 "Ace"인 프로필과, username이 "bob"이고 nickname이 없는 프로필의 경우 출력은 다음과 같습니다:

Display name: Ace
Formatted nickname: Some("[Ace]")
Display name: bob
Formatted nickname: None

세 개의 입력을 받게 됩니다: 첫 번째 사용자의 username, 첫 번째 사용자의 nickname, 그리고 두 번째 사용자의 username (닉네임 없음).

치트 시트

Option<T> 타입은 명시적인 매칭 없이 선택적 값을 다루기 위한 메서드들을 제공합니다.

unwrap_or 메서드는 내부 값이 존재하면 그 값을 반환하고, None인 경우에는 기본값을 반환합니다:

let maybe_name: Option<String> = Some(String::from("Alice"));
let name = maybe_name.unwrap_or(String::from("Guest"));
println!("{}", name);  // Alice

let empty: Option<String> = None;
let fallback = empty.unwrap_or(String::from("Guest"));
println!("{}", fallback);  // Guest

map 메서드는 내부 값이 존재하면 그 값을 변형시키고, None인 경우에는 변경하지 않고 그대로 둡니다:

let maybe_num: Option<i32> = Some(5);
let doubled = maybe_num.map(|x| x * 2);
println!("{:?}", doubled);  // Some(10)

let nothing: Option<i32> = None;
let still_nothing = nothing.map(|x| x * 2);
println!("{:?}", still_nothing);  // None

이 메서드들을 사용하면 None 여부를 계속해서 확인하지 않고도 Option 값에 대한 연산을 체이닝(chaining)할 수 있습니다.

직접 해보기

mod profile;

use profile::Profile;

fn main() {
    // 입력 읽기
    let mut input1 = String::new();
    std::io::stdin().read_line(&mut input1).expect("Failed to read line");
    let username1 = input1.trim().to_string();

    let mut input2 = String::new();
    std::io::stdin().read_line(&mut input2).expect("Failed to read line");
    let nickname1 = input2.trim().to_string();

    let mut input3 = String::new();
    std::io::stdin().read_line(&mut input3).expect("Failed to read line");
    let username2 = input3.trim().to_string();

    // TODO: username1과 nickname1(Some)을 사용하여 첫 번째 프로필 생성
    
    // TODO: username2를 사용하고 닉네임 없이(None) 두 번째 프로필 생성
    
    // TODO: 첫 번째 프로필의 display_name과 formatted_nickname 출력
    // formatted_nickname은 Option을 반환하므로 {:?}를 사용하십시오
    
    // TODO: 두 번째 프로필의 display_name과 formatted_nickname 출력
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

Object Oriented Programming의 모든 레슨