# 클로저 정의

클로저(Closure)는 러스트에서 함수처럼 동작하지만, 함수 본문 외부의 변수를 캡처(capture)하여 함께 사용할 수 있는 특별한 유형의 익명 함수다. 일반적인 함수와 달리 별도의 이름을 갖지 않으며, 자신이 정의된 영역에 존재하는 변수들을 필요에 따라 포인터나 참조가 아닌 직접적인 방식(특히 move 키워드를 사용하는 경우)에 가까운 형태로 가져올 수도 있다. 이러한 특징 때문에 클로저는 함수형 프로그래밍 패러다임의 핵심 요소를 러스트에서 자연스럽게 표현할 수 있는 수단이 된다.

러스트에서 클로저를 정의하는 구문은 크게 세 부분으로 나뉜다. 클로저의 매개변수를 나타내는 파라미터 목록, “화살표” 역할을 하는 `->` 부분(필요하다면 반환 타입 명시), 그리고 실제로 수행될 본문이다. 가장 일반적인 형태는 다음과 같다.

```
let 클로저_이름 = |매개변수들| 본문_표현식;
```

매개변수와 반환 타입이 명시적으로 필요한 경우 다음과 같은 형태로 정의할 수 있다.

```
let 클로저_이름 = |x: i32, y: i32| -> i32 {
    x + y
};
```

예를 들어 아래와 같은 코드에서 클로저는 기본적으로 외부 변수 `factor`를 캡처하여 사용한다.

```
fn main() {
    let factor = 2;
    let multiply = |x: i32| x * factor;
    let result = multiply(10);
    println!("결과: {}", result);
}
```

이 클로저는 함수처럼 호출이 가능하면서도 외부 스코프에서 정의된 `factor` 변수를 내부로 가져와 연산에 사용한다. 함수가 매개변수로 전달받지 않은 값을 사용하려면 일반적으로는 전역 범위에 있는 변수나 구조체의 필드를 접근해야 하지만, 클로저는 자신이 정의된 범위에 있는 변수를 캡처하므로 별도의 전역 선언 없이도 간편하게 외부 값을 참조할 수 있다.

러스트에서 클로저가 변수를 캡처하는 방식은 자동으로 결정되며, 크게 다음 세 가지 트레이트 바운드로 구분된다: `Fn`, `FnMut`, `FnOnce`. 클로저가 필요한 맥락에 따라 적절한 트레이트로 취급된다. 러스트 컴파일러는 특정 클로저가 외부 변수를 어떤 식으로 캡처하는지(불변 참조, 가변 참조, 혹은 소유권 이전) 분석하여 최적의 방식으로 처리한다.

클로저를 정의할 때 매개변수 타입이나 반환 타입을 생략할 수도 있다. 러스트의 타입 추론 시스템은 클로저가 사용되는 맥락을 통해 매개변수 타입과 반환 타입을 추론해 낸다. 하지만 복잡한 경우에는 컴파일러가 추론에 실패할 수도 있으므로 명시적으로 타입을 표기해야 할 때도 있다.

아래 예제는 문자열 슬라이스를 받아 소문자로 변환한 뒤 앞뒤 공백을 제거하는 클로저를 정의하고 실행하는 코드다. 여기서는 함수의 매개변수를 직접 지정하고, 함수처럼 익명으로 작성되었다.

```
fn main() {
    let trim_and_lowercase = |s: &str| -> String {
        s.trim().to_lowercase()
    };

    let original = "  Rust Programming  ";
    let processed = trim_and_lowercase(original);
    println!("원본: '{}'", original);
    println!("처리 후: '{}'", processed);
}
```

클로저는 본문이 단 한 줄인 경우 중괄호를 생략할 수도 있고, 반환 타입을 생략해도 컴파일러가 일반적으로 문제없이 추론한다. 다만 지나치게 복잡해지는 상황에서는 명시적 타입 선언이 더 가독성이 높을 수 있다.

함수 포인터와 달리 클로저는 스택에 저장되는 형태로, 실행 시간에 직접 할당되는 구조체로 취급될 수 있다. 클로저를 호출하기 위해서는 Fn, FnMut, FnOnce 트레이트가 각각 구현되어야 하는데, 이런 트레이트를 통해 클로저가 어떻게 외부 변수를 포획할지 결정된다. 예를 들어 외부 변수를 불변으로만 참조하는 경우는 Fn, 가변 참조가 필요한 경우는 FnMut, 소유권 자체를 가져야 하는 경우는 FnOnce로 취급된다. 이처럼 러스트의 클로저 시스템은 캡처해야 하는 변수에 대한 소유권 규칙을 엄격하게 관리한다.

요약하자면 러스트의 클로저는 다음과 같은 특징을 가진다. 별도의 함수 이름 없이 익명으로 정의 가능하다. 정의 위치의 스코프에 존재하는 변수를 캡처하여 사용할 수 있으며, 러스트 컴파일러는 클로저의 사용 맥락에 따라 자동으로 적절한 캡처 방식을 결정한다. 필요하다면 매개변수 타입과 반환 타입을 명시해 줄 수 있다. 이러한 특징들은 함수형 프로그래밍의 간결함과 편의성을 러스트의 엄격한 메모리 안전성 체계와 결합시키는 핵심 요소가 된다.
