Menu
Coddy logo textTech

where 절

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

트레이트 바운드(trait bound)를 더 많이 추가할수록, 함수 시그니처는 읽기 어려워질 수 있습니다. 여러 개의 제네릭 매개변수를 가지고 있으며, 각각 여러 개의 트레이트를 요구하는 함수를 생각해 봅시다:

fn complex_operation<T: Display + Clone, U: Debug + Summary>(first: T, second: U) {
    // ...
}

이 방식도 작동하지만, 시그니처가 복잡해지고 있습니다. where 절은 트레이트 바운드(trait bounds)를 매개변수 목록 뒤로 옮김으로써 더 깔끔한 대안을 제공합니다:

fn complex_operation<T, U>(first: T, second: U)
where
    T: Display + Clone,
    U: Debug + Summary,
{
    // ...
}

두 버전은 기능적으로 동일합니다. where 절은 순전히 가독성을 위한 것입니다. 각 타입의 요구 사항이 별도의 줄에 표시되어, 각 제네릭 매개변수에 무엇이 필요한지 쉽게 훑어볼 수 있게 해줍니다.

where 절은 바운드(bounds)가 복잡하거나 제네릭 매개변수가 많을 때 특히 유용합니다. 이는 함수 이름과 매개변수를 한눈에 볼 수 있게 유지하면서, 제약 조건은 아래에 별도로 나열합니다. 이는 바운드가 단순한 T: Trait를 넘어설 때 대부분의 Rust 코드베이스에서 선호되는 스타일입니다.

challenge icon

챌린지

쉬움

복잡한 트레이트 바운드(trait bounds)를 가독성 있게 유지하기 위해 where 절을 사용하는 데이터 처리 시스템을 구축해 봅시다! 여러 개의 타입 매개변수를 가진 제네릭 함수를 만들고, 각 타입에 필요한 서로 다른 트레이트들을 where 구문을 사용하여 깔끔하게 정리하게 됩니다.

코드는 두 개의 파일로 구성됩니다:

  • processor.rs: 두 개의 공개(public) 트레이트와 이를 모두 사용하는 제네릭 함수를 정의합니다:
    • Summarize&self를 매개변수로 받고 String을 반환하는 summary 메서드를 가진 트레이트
    • Validate&self를 매개변수로 받고 bool을 반환하는 validate 메서드를 가진 트레이트
    그 다음, 서로 다른 제네릭 타입의 두 매개변수를 받는 process_items라는 공개 제네릭 함수를 만듭니다. where 절을 사용하여 첫 번째 타입은 CloneSummarize를 모두 구현해야 하며, 두 번째 타입은 Validate를 구현해야 함을 명시하세요. 이 함수는 첫 번째 항목의 요약(summary)을 출력한 다음, 두 번째 항목의 유효 여부를 출력해야 합니다.
  • main.rs: 필요한 트레이트를 구현하는 두 개의 공개 구조체를 만듭니다:
    • Article — 공개된 title 필드(String)를 가집니다. Summarize를 구현하여 "Article: {}" 형식으로 반환하도록 하고, Clone을 파생(derive)시킵니다.
    • Form — 공개된 filled 필드(bool)를 가집니다. Validate를 구현하여 filled의 값을 반환하도록 합니다.
    제공된 입력을 사용하여 Article과 Form을 생성한 후, 두 항목을 모두 인자로 하여 process_items를 호출하세요.

where 절은 모든 바운드를 꺾쇠괄호(angle brackets) 안에 밀어 넣는 것보다 함수 시그니처를 훨씬 깔끔하게 만들어 줍니다. 각 타입의 요구 사항이 별도의 줄에 표시되므로 각 제네릭 매개변수에 무엇이 필요한지 쉽게 확인할 수 있습니다.

출력은 요약 내용과 그 뒤에 이어지는 유효성 검사 결과를 보여주어야 합니다:

Article: {title}
Valid: {true/false}

예를 들어, 입력값이 Rust Tipstrue인 경우:

Article: Rust Tips
Valid: true

그리고 입력값이 Breaking Newsfalse인 경우:

Article: Breaking News
Valid: false

두 개의 입력을 받게 됩니다: 기사 제목(article title)과 양식 작성 여부(bool로 파싱)입니다.

치트 시트

where 절은 제약 조건을 매개변수 목록 뒤로 이동시켜 제네릭 함수에 대한 트레이트 바운드를 지정하는 더 깔끔한 방법을 제공합니다:

fn complex_operation<T, U>(first: T, second: U)
where
    T: Display + Clone,
    U: Debug + Summary,
{
    // ...
}

이것은 인라인 트레이트 바운드와 기능적으로 동일하지만 가독성을 향상시킵니다:

fn complex_operation<T: Display + Clone, U: Debug + Summary>(first: T, second: U) {
    // ...
}

where 절은 특히 다음과 같은 경우에 유용합니다:

  • 여러 개의 제네릭 매개변수가 있는 경우
  • 각 매개변수가 여러 개의 트레이트 바운드를 필요로 하는 경우
  • 함수 시그니처를 깔끔하고 훑어보기 좋게 유지하고 싶은 경우

각 타입의 요구 사항이 별도의 줄에 표시되어 각 제네릭 매개변수에 무엇이 필요한지 쉽게 확인할 수 있습니다. 이는 바운드가 단순한 T: Trait를 넘어설 때 대부분의 Rust 코드베이스에서 선호되는 스타일입니다.

직접 해보기

mod processor;

use processor::{Summarize, Validate, process_items};
use std::io;

// TODO: 공개 필드 title (String)을 가진 공개 구조체 Article을 정의하세요.
// Article에 대해 Clone을 파생(Derive)하세요.

// TODO: Article에 대해 Summarize를 구현하세요.
// summary 메서드는 "Article: {title}"을 반환해야 합니다.

// TODO: 공개 필드 filled (bool)를 가진 공개 구조체 Form을 정의하세요.

// TODO: Form에 대해 Validate를 구현하세요.
// validate 메서드는 filled의 값을 반환해야 합니다.

fn main() {
    let mut title = String::new();
    io::stdin().read_line(&mut title).expect("Failed to read line");
    let title = title.trim().to_string();

    let mut filled_input = String::new();
    io::stdin().read_line(&mut filled_input).expect("Failed to read line");
    let filled: bool = filled_input.trim().parse().expect("Failed to parse bool");

    // TODO: 주어진 title로 Article을 생성하세요.
    
    // TODO: 주어진 filled 값으로 Form을 생성하세요.
    
    // TODO: article과 form을 사용하여 process_items를 호출하세요.
}
quiz icon실력 점검

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

Object Oriented Programming의 모든 레슨