# 표준 라이브러리 구조

Rust는 안전성과 성능, 그리고 표현력을 극대화하기 위해 체계적이고 계층화된 표준 라이브러리를 제공한다. 표준 라이브러리(std)는 필요한 모든 기능을 한 곳에 몰아넣기보다는, 언어가 가지는 핵심 요소부터 메모리 할당 기능, 운영 체제 의존적인 기능 등을 분리해둔다. 이러한 구조는 다양한 플랫폼에서 Rust를 동작시킬 수 있게 하며, 상황에 따라 특정 계층만 사용하도록 선택할 수도 있게 해준다. 대표적으로 가장 바닥을 담당하는 core 크레이트, 동적 메모리 할당을 담당하는 alloc 크레이트, 그리고 운영 체제 종속 기능까지 포함한 std 크레이트가 하나의 층을 이룬다.

core 크레이트는 Rust 언어의 최소한의 기능만을 담아낸다. 예를 들어, Option, Result, Iterator, panic 같은 언어 차원의 필수 타입, trait, 함수가 여기에 속한다. core는 동적 메모리 할당을 전혀 사용하지 않으며 운영 체제에 대한 의존성도 없다. 그래서 임베디드 같은 환경에서 std 없이도 Rust를 사용할 수 있도록 해주는 기반을 제공한다.

alloc 크레이트는 동적 메모리 할당 기능을 추가로 제공한다. Vec, String 같은 컬렉션이 동작하려면 힙(Heap)을 이용한 메모리 할당이 필요하다. 하지만 alloc에는 운영 체제가 제공하는 기본 I/O나 스레드, 동시성 등은 전혀 포함되지 않는다. 따라서 alloc을 사용한다는 것은 단순히 힙을 사용하는 컬렉션 유형을 지원한다는 의미일 뿐이다.

std 크레이트는 운영 체제가 제공하는 기능까지 포함하여 가장 범용적으로 쓰이는 계층이다. 여기에는 파일 I/O, 네트워킹, 스레드, 동시성, 운영 체제 의존 기능 등이 들어 있다. 대부분의 일반적인 프로그램은 std를 사용하며, 표준 라이브러리에서 제공하는 기능을 충분히 활용한다. Rust 입문자들이 흔히 보게 되는 String, Vec, HashMap\<K, V>, Rc, Arc 등은 std를 통해 접근 가능하다. 그러나 no\_std 환경을 지원해야 하는 상황(임베디드, 커널 모듈, 특정 OS가 없는 시스템 등)에서는 std가 아닌 core 또는 alloc만 사용하도록 제한하는 방식을 택하기도 한다.

Rust 컴파일러는 std 크레이트를 암묵적으로 포함하지만, 이 과정에서 별도의 설정이 없다면 자동으로 std가 제공된다. 만약 no\_std를 명시하거나, 실행 환경이 호환되지 않는 경우에는 std 없이도 Rust 코드를 작성할 수 있다. 이런 시스템에서도 필요한 경우에는 alloc을 활성화하여 동적 메모리 할당 기반의 컬렉션을 사용할 수 있다. 즉, std에 들어 있는 많은 기능이 여러 계층으로 분산되어 있기에, 자신이 필요한 기능만 최소한으로 의존할 수 있는 유연함이 Rust의 장점이다.

std 모듈 내부에서는 다양한 이름공간이 계층적으로 구성되어 있다. 가장 많이 쓰이는 것은 std::io, std::collections, std::sync, std::thread, std::net 등이 있다. I/O 기능들은 std::io에 모여 있어 파일이나 표준 입력/출력 스트림, 버퍼링, 다양한 I/O 에러 처리를 제공한다. 동시성 관련 기능들은 std::thread나 std::sync에 위치하며, 스레드를 생성하고 Mutex, RwLock, Condvar 같은 동기화 도구를 이용할 수 있도록 해준다. 컬렉션은 std::collections에서 VecDeque, BinaryHeap, BTreeMap, HashMap 등을 포함하며, 상황과 요구 사항에 따라 다양한 자료구조를 손쉽게 사용할 수 있게 설계되어 있다.

Rust가 제공하는 표준 라이브러리는 대부분의 경우에 매우 빠르며 안전하다. 예를 들어 HashMap은 해시 충돌에 대비하는 기법을 사용하고, Vec은 메모리 재할당을 최소화하는 정책과 안정성을 위한 범위 검사 등을 기본적으로 수행한다. 그리고 모든 컬렉션은 반복자 API와 호환되어 고차 함수를 활용한 함수형 스타일의 데이터 처리도 지원한다. 아래는 표준 컬렉션인 Vec을 사용하는 간단한 예시다.

```
fn main() {
    let mut numbers = Vec::new();
    numbers.push(10);
    numbers.push(20);
    numbers.push(30);

    for num in numbers.iter() {
        println!("{}", num);
    }
}
```

이 예시에서 Vec::new() 메서드는 빈 벡터를 생성하고, push로 원소를 삽입한다. numbers.iter()를 통해 불변 참조의 반복자를 얻을 수 있고, 여기서 꺼낸 값들을 하나씩 출력한다. 이처럼 std가 제공하는 컬렉션은 일상적인 사용에 필요한 대부분의 기능을 안전하고 편리한 메서드 형태로 제공한다.

컬렉션뿐만 아니라 std는 표준 프렐류드(prelude)를 제공하여 자주 사용되는 타입과 함수를 자동으로 가져온다. 예를 들어 Option, Result, Some, None, Ok, Err 같은 타입이나 일부 트레이트는 사용 시에 별도의 use 구문 없이도 쓸 수 있다. 반면에 HashMap, BTreeMap 등은 std::collections에서 명시적으로 use 구문을 통해 불러와야 한다. 이러한 구조적 구분은 모듈의 책임을 명확히 하고, namespace 오염을 방지하며, 필수적 요소와 선택적 요소를 구분짓는 데 유용하다.

Rust의 표준 라이브러리는 언어 전체의 일관성을 잘 유지하면서도, 다양한 환경에서 공통적으로 동작할 수 있도록 확장성과 호환성을 제공한다. 이 계층적 구조는 필요한 기능만을 선택적으로 활용할 수 있게 하고, 메모리와 런타임 환경이 제한적인 곳에서도 Rust를 쓸 수 있게 해준다. 결국 Rust 개발자로서 표준 라이브러리를 이해하고 적절히 사용하는 것은 효율적이고 안전한 코드를 작성하는 데 매우 중요한 부분이다.
