# 메서드와 연관 함수

Rust에서 메서드(Method)는 특정 구조체 인스턴스(또는 열거형 인스턴스)와 밀접하게 연관된 함수로서, 첫 번째 매개변수로 self(또는 \&self, \&mut self)를 받는다. 이는 인스턴스에 내장된 데이터를 직접 다루거나 해당 인스턴스에 관련된 로직을 구현하는 데 사용된다. 반면 연관 함수(Associated Function)는 self를 매개변수로 받지 않으며, 타입 자체와 관련된 함수 로직을 구현하거나 새로운 인스턴스를 생성하는 ‘생성자’와 유사한 기능을 수행할 수 있다. 이런 메서드와 연관 함수는 모두 impl(implementation) 블록 내에 정의된다.

메서드는 주로 구조체의 필드를 읽거나 수정하고, 인스턴스에 따른 동작을 정의할 때 사용한다. 메서드를 정의할 때 self의 형태에 따라 호출 시점의 소유권과 가변성을 조절할 수 있다. \&self는 불변 참조로서 인스턴스 값을 읽을 수만 있고, \&mut self는 가변 참조로서 인스턴스 값을 변경할 수 있으며, self 자체를 매개변수로 받으면 해당 메서드가 인스턴스의 소유권까지 가져가서 내부 데이터를 완전히 소유한다. 이러한 선택권 덕분에 Rust는 다양한 상황에서 엄격하고 명확한 소유권 및 대여(ownership and borrowing) 규칙을 만족시키면서도 유연한 메서드 설계를 지원한다.

연관 함수는 특정 인스턴스가 없어도 호출할 수 있는 함수라는 점에서, 다른 언어의 정적 메서드(Static Method)와 유사하다. self 인자가 없기 때문에 인스턴스 내부 데이터에 직접 접근할 수는 없지만, 내부적으로 새로운 인스턴스를 생성하거나 타입과 관련된 유틸리티 기능을 제공하기에 용이하다. 관례상 많이 사용되는 예로는 new라는 이름의 연관 함수를 두어 “생성자”와 같은 역할을 하도록 하는 것이다.

아래 예시는 구조체에 대한 메서드와 연관 함수를 모두 포함한다.

```
struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    // 연관 함수: Rectangle 타입의 새 인스턴스를 생성
    fn new(width: u32, height: u32) -> Self {
        Self { width, height }
    }

    // 연관 함수: 정해진 크기로 초기화된 정사각형을 생성
    fn square(size: u32) -> Self {
        Self {
            width: size,
            height: size,
        }
    }

    // 메서드: &self 불변 참조를 사용하여 면적을 구함
    fn area(&self) -> u32 {
        self.width * self.height
    }

    // 메서드: &mut self 가변 참조를 사용하여 크기를 두 배로 늘림
    fn double_size(&mut self) {
        self.width *= 2;
        self.height *= 2;
    }

    // 메서드: self 자체를 받아 소유권을 가져가고, 넓이만 반환
    fn consume_and_return_area(self) -> u32 {
        self.width * self.height
    }
}

fn main() {
    // 연관 함수 new를 사용해 인스턴스 생성
    let mut rect = Rectangle::new(30, 50);
    println!("현재 직사각형 면적: {}", rect.area());

    // 메서드 double_size를 사용해 크기를 두 배로 늘림
    rect.double_size();
    println!("두 배로 늘린 직사각형 면적: {}", rect.area());

    // consume_and_return_area를 호출하면 rect의 소유권이 넘어감
    let area = rect.consume_and_return_area();
    println!("소유권을 소비하면서 얻은 면적: {}", area);

    // 새로운 정사각형을 생성하는 연관 함수 square 사용
    let square = Rectangle::square(10);
    println!("정사각형 면적: {}", square.area());
}
```

위 코드에서 Rectangle 구조체의 impl 블록은 메서드와 연관 함수를 모두 포함한다. new와 square는 self 매개변수를 가지지 않으므로 인스턴스가 없어도 호출할 수 있는 연관 함수이다. 반대로 area, double\_size, consume\_and\_return\_area와 같은 메서드들은 자기 자신을 의미하는 self(또는 그 형태) 매개변수를 통해 인스턴스에 접근한다.

메서드는 보통 . 연산자를 이용해 인스턴스에 붙여서 호출한다. 예를 들어 rect.area() 같이 작성하면 area 메서드가 rect 인스턴스 데이터를 사용해 계산을 수행한다. 반면 연관 함수는 Rectangle::new(...)처럼 더블 콜론(::)을 사용하여 타입 이름 뒤에 연관 함수 이름을 붙여 호출한다. 이는 호출 시 인스턴스가 전혀 필요하지 않다는 점을 명확히 보여준다.

연관 함수는 생성자 역할로도 많이 쓰이지만, 그 외에도 타입이 제공할 여러 가지 정적 기능을 구현할 수 있다. 예를 들어 문자열에서 변환해 오는 로직을 제공하는 from\_str 같은 함수를 연관 함수로 선언할 수 있고, 무작위 값을 생성하는 random 같은 함수를 둬서 내부적으로 랜덤 라이브러리를 호출하여 새로운 인스턴스를 만들도록 할 수도 있다.

Rust가 별도의 생성자 문법을 제공하지 않기 때문에, 이런 식으로 “new”라는 이름을 사용해 생성용 연관 함수를 구현하는 것이 사실상 관례처럼 자리 잡았다. “new”라는 이름에 한정하지 않고, 필요에 따라 이름을 바꿀 수 있지만, 일반적으로는 명확성을 위해 new를 쓰고 그 외 연관 함수는 역할에 맞는 이름을 붙이는 편이다.

impl 블록은 하나의 구조체(또는 열거형)에 대해 여러 개 작성할 수도 있으므로, 필요에 따라 메서드와 연관 함수를 여러 블록에 걸쳐 자유롭게 정의할 수 있다. 다만, 외부에서 사용해야 하는 함수라면 pub 키워드를 붙여야 모듈 경계를 넘어 접근이 가능하다.

메서드와 연관 함수는 구조체 또는 열거형이 제공해야 하는 기능을 명확하게 구분하여 제공한다는 점에서 매우 중요하다. 인스턴스가 필요한 동작을 메서드로, 인스턴스가 필요 없는 동작이나 생성 로직을 연관 함수로 나누어 작성하면 코드의 의도가 분명해지고, 호출 시점에 어디에 속한 로직인지 명확해진다. 이를 통해 Rust가 가진 소유권 및 참조 모델과 결합하여, 안전하면서도 직관적인 API 설계를 가능하게 해준다.
