# Slice와 Range

Rust에서 슬라이스(Slice)는 배열(array), 벡터(vector)와 같은 연속된 메모리 상의 요소들에 대한 '조각'을 참조하는 방법이다. 슬라이스는 컴파일 타임에 크기가 고정된 배열과 달리 런타임에 크기가 결정되며, 본질적으로 시작 위치와 길이에 대한 포인터 역할을 한다. 이러한 슬라이스는 소유권을 가져가지 않고, 기존 컬렉션의 유효 구간만을 참조하므로, 데이터의 일부분만 안전하게 읽거나 수정하고자 할 때 유용하다. Rust 컴파일러는 슬라이스를 사용할 때 메모리 안전성과 범위 검사를 수행하며, 이를 통해 불법적인 메모리 접근 가능성을 최소화한다.

슬라이스를 얻는 가장 흔한 방법 중 하나는 배열 혹은 벡터에 대하여 슬라이싱 구문(\[start..end])을 사용하는 것이다. 이 구문에서 start 인덱스는 포함되고 end 인덱스는 포함되지 않는다. 예를 들어 배열에서 특정 범위를 가져오거나, 벡터 안의 데이터 일부만 참조할 때 사용된다. 아래 예시는 배열로부터 슬라이스를 얻는 모습이다.

```
fn main() {
    let array = [10, 20, 30, 40, 50];
    let slice_all = &array[..];      // 전체 배열에 대한 슬라이스
    let slice_part = &array[1..4];   // 인덱스 1부터 3까지에 대한 슬라이스 (20, 30, 40)
    
    println!("전체 슬라이스: {:?}", slice_all);
    println!("부분 슬라이스: {:?}", slice_part);
}
```

슬라이스는 참조이므로 이를 사용해 값을 변경하거나 읽을 수 있다. 이때 변경 가능 여부는 불변 참조(\&T)인지 가변 참조(\&mut T)인지에 따라 달라진다. 가변 참조를 통해 슬라이스를 생성하면 슬라이스의 영역 안에 있는 원본 데이터의 수정이 가능하다. 단, 러스트의 빌로우십 규칙(Borrow Checker)이 적용되어, 슬라이스가 유효한 범위 내에서만 사용되도록 컴파일 단계에서 검사한다.

슬라이스는 배열이나 벡터뿐만 아니라, String과 같은 다른 컬렉션 타입에서도 유사하게 동작한다. 예를 들어 String에 대해서도 \&str 형태로 슬라이스를 사용할 수 있으며, UTF-8 문자의 경계에 유의해야 한다. \&str 슬라이스를 얻을 때는 잘못된 바이트 인덱스 경계로 인해 프로그램이 패닉에 빠지지 않도록 Rust에서 자동으로 검사한다.

Range는 범위를 표현하는 표준 라이브러리의 핵심 기능 중 하나로, 간단한 반복부터 슬라이싱 구문까지 다양한 곳에서 사용된다. Range는 a..b, a..=b, ..b, a.., .. 와 같은 표기 방식으로 나타내며, 각 표기 방식에 따라 포함 범위가 달라진다. 예를 들어 a..b는 a 이상 b 미만 범위를 나타내고, a..=b는 a 이상 b 이하 범위를 나타낸다. 슬라이싱 구문에서도 이러한 Range 문법을 사용하므로, 슬라이스를 생성할 때 start..end 또는 start..=end 등의 표현을 그대로 적용할 수 있다.

슬라이스를 만들 때 start 부분이 생략되면 0부터, end 부분이 생략되면 컬렉션의 끝까지로 간주한다. 예시로 \[..end] 형태는 0부터 end 직전까지, \[start..] 형태는 start부터 끝까지의 슬라이스를 의미한다. 또한 Range는 반복문과 함께 사용될 때도 매우 직관적이다. for 루프에서 0..5는 0 이상 5 미만의 정수를 순회하고, 1..=5는 1 이상 5 이하의 정수를 순회한다. 아래 예시를 통해 범위를 어떻게 활용할 수 있는지 확인할 수 있다.

```
fn main() {
    for i in 0..5 {
        println!("i: {}", i);
    }

    for j in 1..=3 {
        println!("j: {}", j);
    }
}
```

슬라이싱 구문에서는 0..5를 사용하여 인덱스 0부터 4까지에 해당하는 부분 배열을 참조할 수 있으며, 2..=4를 사용하면 인덱스 2부터 4까지(포함)의 요소를 참조할 수 있다. 다만 주의해야 할 점은 슬라이스를 통해 참조하려는 인덱스 범위가 실제 배열이나 벡터의 유효 범위를 넘어서면 런타임에 패닉이 발생한다는 것이다.

슬라이스와 Range는 함께 결합되어 Rust 프로그래밍에서 안전하고 직관적인 연속 데이터 접근 방식을 제공한다. 슬라이스는 기존 컬렉션의 메모리 공간을 효율적으로 재활용하며, Range는 어떤 범위를 쉽게 지정하고 순회할 수 있도록 도와준다. 러스트의 엄격한 소유권 및 빌로우십 규칙과 결합되어, 슬라이스와 Range는 메모리 안전성을 확보하면서도 높은 성능을 유지할 수 있게 한다. 이러한 기능들은 대규모 시스템 프로그래밍부터 간단한 스크립트성 작업까지, 폭넓은 환경에서 유용하게 활용된다.
