트레이트
Trait
Rust의 공유 동작 정의 방식. 인터페이스와 유사. 제네릭과 결합해 다형성 구현.
Trait
Rust의 공유 동작 정의 방식. 인터페이스와 유사. 제네릭과 결합해 다형성 구현.
트레이트(Trait)는 Rust에서 공유 동작(behavior)을 정의하는 방법입니다. 다른 언어의 인터페이스와 유사하지만, 기본 구현을 제공할 수 있고 기존 타입에 트레이트를 구현할 수 있다는 점에서 더 유연합니다. 트레이트는 Rust의 다형성과 제네릭 시스템의 핵심입니다.
트레이트는 메서드 시그니처의 집합을 정의합니다. 타입이 트레이트를 구현(impl)하면 해당 메서드들을 반드시 제공해야 합니다. 트레이트에 기본 구현이 있으면 구현 타입에서 오버라이드하지 않아도 됩니다. 이를 통해 코드 재사용과 일관된 인터페이스를 보장합니다.
트레이트 바운드(Trait Bound)를 사용하면 제네릭 타입에 제약을 걸 수 있습니다. fn print<T: Display>(item: T)는 Display 트레이트를 구현한 타입만 받습니다. where 절로 복잡한 바운드도 깔끔하게 표현할 수 있습니다.
Rust 표준 라이브러리의 Clone, Copy, Debug, Default, PartialEq 등은 자주 사용되는 트레이트입니다. #[derive] 매크로로 자동 구현이 가능하여 보일러플레이트 코드를 줄입니다. dyn Trait을 사용하면 런타임 다형성(동적 디스패치)도 가능합니다.
// Rust 트레이트 예제
// 1. 트레이트 정의
trait Drawable {
fn draw(&self);
// 기본 구현
fn description(&self) -> String {
String::from("A drawable object")
}
}
// 2. 트레이트 구현
struct Circle {
radius: f64,
}
impl Drawable for Circle {
fn draw(&self) {
println!("Drawing circle with radius {}", self.radius);
}
}
struct Rectangle {
width: f64,
height: f64,
}
impl Drawable for Rectangle {
fn draw(&self) {
println!("Drawing rectangle {}x{}", self.width, self.height);
}
fn description(&self) -> String {
format!("Rectangle {}x{}", self.width, self.height)
}
}
// 3. 트레이트 바운드
fn draw_all(items: &[T]) {
for item in items {
item.draw();
}
}
// 4. where 절
fn compare_and_draw(a: T, b: U)
where
T: Drawable + Clone,
U: Drawable + Default,
{
a.draw();
b.draw();
}
// 5. 동적 디스패치
fn draw_dynamic(item: &dyn Drawable) {
item.draw();
}
// 6. derive 매크로
#[derive(Debug, Clone, PartialEq)]
struct Point {
x: i32,
y: i32,
}
시니어: 여러 스토리지 백엔드를 지원해야 해요. 트레이트로 추상화합시다.
주니어: Storage 트레이트에 read, write 메서드를 정의하면 될까요?
시니어: 네, 그리고 async_trait 크레이트를 쓰면 비동기 메서드도 트레이트에 정의할 수 있어요. 각 백엔드(S3, 로컬, Redis)에서 이 트레이트를 구현하면 됩니다.
면접관: Rust의 트레이트와 Java 인터페이스의 차이점은 무엇인가요?
지원자: 트레이트는 기본 구현을 제공할 수 있고, 기존 타입에도 외부에서 트레이트를 구현할 수 있습니다. 또한 트레이트 바운드로 제네릭에 제약을 거는 방식이 다릅니다. Java의 default 메서드가 비슷하지만 Rust가 더 유연합니다.
면접관: 정적 디스패치와 동적 디스패치의 차이는요?
지원자: 정적 디스패치는 컴파일 타임에 호출될 함수가 결정되어 인라인 최적화가 가능합니다. 동적 디스패치(dyn Trait)는 런타임에 vtable을 통해 결정되어 유연하지만 약간의 오버헤드가 있습니다.
리뷰어: 이 제네릭 함수에 트레이트 바운드가 너무 많아요. 리팩토링이 필요해 보여요.
작성자: 기능이 많이 필요해서요.
리뷰어: 여러 트레이트를 조합한 슈퍼트레이트를 만들거나, 함수를 분리하는 게 좋겠어요. where 절이 5줄 넘으면 설계를 재고해보세요.