본문 바로가기
카테고리 없음

Rust 클로저(Closure)와 함수형 프로그래밍 기초

by mystory55801 2025. 6. 3.

Rust에서 클로저(Closure)란 무엇인가요?

Rust에서 클로저(Closure)는 다른 언어의 람다(lambda) 또는 익명 함수에 해당합니다. 변수에 저장하거나 다른 함수의 인자로 전달할 수 있는 익명 함수로, 주변 환경의 변수들을 캡처할 수 있는 특징이 있습니다.

간단한 예제를 통해 클로저의 기본 문법을 알아보겠습니다.


fn main() {
    let add = |x, y| x + y;
    println!("3 + 5 = {}", add(3, 5));
}

위 예제에서 add|x, y| x + y라는 클로저를 저장한 변수입니다. 일반 함수처럼 사용할 수 있으며, 타입을 명시하지 않아도 컴파일러가 자동으로 추론해 줍니다.

클로저 vs 일반 함수: 무엇이 다를까요?

Rust에서는 클로저와 일반 함수 모두 함수를 정의할 수 있지만, 클로저는 다음과 같은 차이점을 가집니다:

  • 익명 함수로서 변수에 저장하거나 다른 함수에 인자로 전달 가능
  • 외부 변수 캡처 가능
  • 타입 추론이 가능해 더 간결한 코드 작성 가능

fn main() {
    let name = "Rust";
    let say_hello = || println!("Hello, {}", name);
    say_hello();
}

위 예제에서 클로저 say_hello는 외부 변수 name을 캡처하여 사용할 수 있습니다. 일반 함수에서는 이와 같은 동작이 불가능합니다.

클로저의 타입과 Fn, FnMut, FnOnce

Rust에서는 클로저의 동작 방식에 따라 세 가지 트레잇 중 하나를 자동으로 구현합니다:

  • Fn: 클로저가 환경을 불변 참조로 캡처
  • FnMut: 가변 참조로 캡처
  • FnOnce: 환경을 이동(move)하여 소유

fn apply(f: F) {
    f();
}

fn main() {
    let message = "Hello";
    apply(|| println!("{}", message));
}

이 예제는 Fn 트레잇을 사용하는 함수를 정의하고, 클로저를 인자로 전달합니다. 클로저의 타입은 자동 추론되며, 적절한 트레잇이 적용됩니다.

move 키워드로 소유권 이동

클로저에서 환경 변수를 소유권 이동으로 캡처하고자 할 때는 move 키워드를 사용합니다.


fn main() {
    let name = String::from("Rust");
    let say = move || println!("Welcome, {}", name);
    say();

    // name은 move로 인해 더 이상 사용할 수 없음
}

이 경우 say 클로저는 name의 소유권을 가져가므로, 클로저 호출 이후 name을 사용할 수 없습니다.

함수형 프로그래밍의 기초 개념

클로저는 Rust에서 함수형 프로그래밍 패러다임을 구현하는 데 핵심적인 역할을 합니다. 함수형 프로그래밍은 다음과 같은 특징을 지닙니다:

  • 함수는 일급 객체로, 변수에 저장하거나 전달 가능
  • 순수 함수(pure function)를 중시
  • 불변성(immutability) 강조
  • 고차 함수(higher-order function) 사용

고차 함수와 map, filter, fold 사용 예제

Rust의 Iterator와 함께 사용하는 map, filter, fold 등은 대표적인 함수형 프로그래밍 요소입니다.


fn main() {
    let numbers = vec![1, 2, 3, 4, 5];

    let doubled: Vec<_> = numbers.iter().map(|x| x * 2).collect();
    println!("Doubled: {:?}", doubled);

    let even: Vec<_> = numbers.iter().filter(|&x| x % 2 == 0).collect();
    println!("Even: {:?}", even);

    let sum: i32 = numbers.iter().fold(0, |acc, x| acc + x);
    println!("Sum: {}", sum);
}

이처럼 클로저를 활용한 고차 함수는 Rust에서 가독성 높고 선언적인 스타일의 코드 작성을 가능하게 해 줍니다.

결론: Rust 클로저는 함수형 프로그래밍의 시작점

Rust에서의 클로저는 간단한 람다 표현을 넘어서, 메모리 안전성과 강력한 타입 시스템을 기반으로 한 함수형 프로그래밍을 실현하는 중요한 도구입니다. 클로저를 사용하면 더 유연하고 재사용 가능한 코드를 작성할 수 있으며, map, filter, fold 같은 고차 함수와 함께 사용하면 Rust 코드의 표현력을 크게 향상시킬 수 있습니다.

Rust 초보자라면 다양한 클로저 예제를 실습하면서 개념을 체득하고, 함수형 프로그래밍 스타일을 익혀보세요. 실전 개발에서도 매우 유용하게 쓰일 수 있습니다.