# 튜플 구조체와 유닛 구조체

일반 구조체는 필드를 이름으로 구분하는 반면, 튜플 구조체는 튜플의 형태를 유지하면서 구조체로서의 특징을 지닌다. 즉, 튜플과 비슷하게 여러 값을 순서대로 저장하지만, 그 집합 자체에 대한 별도의 타입 이름을 부여할 수 있다. 예를 들어, 좌표를 표현하는 경우를 생각해보면 일반 구조체에서는 `x`, `y`, `z` 등의 필드를 사용하여 위치를 구분한다. 튜플 구조체로 표현하면 이름이 있는 타입이면서도 내부는 필드 이름이 없는 순서만으로 구분되는 특성을 가진다. 다음 예제를 통해 튜플 구조체를 정의하고 사용하는 방법을 살펴본다.

```
struct Coordinates(i32, i32, i32);

fn main() {
    let point = Coordinates(10, 20, 30);
    println!("x: {}, y: {}, z: {}", point.0, point.1, point.2);
}
```

위 예제에서 `Coordinates`는 튜플 구조체로서, 내부에 i32 형식의 필드를 세 개 가진다. 인스턴스를 생성할 때는 일반 튜플과 마찬가지로 괄호 안에 데이터를 순서대로 배치한다. 다만, 이 튜플 구조체는 새로운 타입 이름을 가지므로, 다른 튜플과 구분되는 고유한 자료형으로 동작한다. 필드에 접근할 때는 일반 튜플과 동일하게 `.` 뒤에 인덱스를 붙여 사용한다.

튜플 구조체는 주로 이름이 불필요한 간단한 필드 집합을 분리해서 사용하거나, 동일한 데이터 구조로부터 의미적으로 구분되는 새로운 타입을 만들고자 할 때 유용하다. 예를 들어, x, y, z 좌표계에서 서로 다른 용도로 사용되는 좌표 타입을 튜플 구조체로 정의하면, 컴파일 타임에 잘못된 타입 간의 대입이나 혼용을 방지할 수 있다.

구조체와 열거형을 다룰 때는 패턴 매칭에서도 튜플 구조체를 활용할 수 있다. 다음 예제는 좌표를 튜플 구조체로 받고, z 좌표값이 특정 조건을 만족할 때만 행동을 달리하는 모습을 보여준다.

```
struct Coordinates(i32, i32, i32);

fn describe_point(point: Coordinates) {
    match point {
        Coordinates(_, _, 0) => println!("Z좌표가 0이므로 평면 상에 있다."),
        Coordinates(x, _, z) if z > 0 => println!("위쪽 공간: x는 {}, z는 양수이다.", x),
        Coordinates(x, y, z) => println!("임의의 점: ({}, {}, {})", x, y, z),
    }
}

fn main() {
    let point1 = Coordinates(10, 20, 0);
    let point2 = Coordinates(15, 25, 5);
    let point3 = Coordinates(-10, -20, -5);

    describe_point(point1);
    describe_point(point2);
    describe_point(point3);
}
```

위 코드에서 `Coordinates(_, _, 0)`와 같이 패턴 매칭 구문에서 튜플 구조체의 필드를 직접 분해하여 조건에 맞춰 로직을 수행한다. `_`는 어떤 값이 와도 상관없다는 의미의 와일드카드이며, `if z > 0` 형태로 조건을 걸어서 추가적인 분기를 수행할 수도 있다.

유닛 구조체는 필드가 전혀 없는 구조체다. 필드가 없는 구조체는 사실상 튜플의 길이가 0개인 특별한 형태로 이해할 수 있다. 다음 예제는 유닛 구조체의 정의와 사용 방법을 보여준다.

```
struct Nothing;

fn main() {
    let n = Nothing;
    // n은 아무런 필드도 갖지 않으며 그 자체로 하나의 자료형이다
}
```

유닛 구조체는 흔히 특정 타입을 구분하기 위한 마커 역할을 수행할 때 사용한다. 예를 들어, 어떤 함수가 내부에서 특정한 제약을 만족했음을 보장하기 위해, 그 보증 상태를 나타내는 별도 구조체 타입을 생성하여 반환하도록 구성할 수도 있다. 이때 그 구조체가 굳이 다른 정보가 필요 없다면, 유닛 구조체가 적합하다. 반환 타입이 달라짐으로써 이후 로직에서 이 구조체를 받는 함수나 코드들이 “특정 제약을 만족한 상태만을 받는다”는 것을 컴파일 타임에 확실히 구분할 수 있게 된다.

튜플 구조체와 유닛 구조체 모두 일반적인 구조체와 달리 필드의 명시적인 이름이 없는 점이 특징이다. 튜플 구조체는 튜플 인덱스로 필드에 접근하며, 유닛 구조체는 아예 필드 자체가 없는 형태다. 두 타입 모두 Rust의 엄격한 타입 체계에서 의미 있는 역할을 담당한다. 단순하게 보면 “필드가 있는” 구조체와 “필드가 없는” 구조체 사이의 극단에 있는 여러 가지 변형으로 이해할 수 있으며, 각각의 쓰임새에 따라 목적이 명확할 때 적합하게 선택하여 사용하면 된다.
