----------------
title : Rust 의 라이브타임 (lifetime) 에 관해서
cat_title : Rust 의 라이프타임 (lifetime) 에 관해서
path : /Rust
publish_date : 2023-09-07
is_published: false    
--------------

Rust 를 공부하면서 가장 생소했던 개념을 하나 고르라고 하자면, 대부분 라이프타임(lifetime) 을 고를 것입니다. 처음 C 언어를 배울 때 포인터를 배우면서 좌절했던 경험처럼 Rust 의 라이프타임을 배우면서 머리가 정말 지끈거렸던 기억이 납니다. 사실 C++ 에서 레퍼런스들의 scope 들에 대해서 다루면서 뭔가 C++ 에서 라이프타임 비스무리한 개념이 있었기는 합니다. 하지만 Rust 에서 처럼 명시적으로 이를 나타내지는 않았죠. 

Rust 에서는 레퍼런스들의 라이프타임들을 언어 상에서 관리함으로써 C++ 에서 고질적으로 발생하는 dangling reference 들로 인한 수 많인 메모리 버그들을 컴파일러 단에서 막을 수 있게 되었습니다. 하지만 **공짜 점심은 없다** 라는 말이 있듯이, Rust 에서는 코드 자체를 컴파일러의 *Borrow Checker* 의 입맛에 맞게 정확히 짜야 코드가 컴파일이 됩니다.   

따라서 C++ 에서는 라이프타임의 부재로 인해 수 많인 런타임 메모리 관련 버그들과 싸워야 했다면, Rust 에서는 컴파일 시에 **아니 도대체 이게 왜 컴파일이 안되지** 하는 자신과의 싸움을 하게 됩니다. 물론, 런타임 시에 발생하는 버그 보다 컴파일러 자체에서 아예 라이프타임 버그를 방지하는 것이 백만배 더 나은 일이지만, 라이프타임을 제대로 이해하지 않았다면 결국 컴파일러와 싸움에 패배해서 **아 그냥 됐고 전부 `.clone()` 해버릴꺼야** 하는 자신을 볼 수 있을 것입니다. 

이 글은 저처럼 라이프타임으로 고생하는 분들을 위해서 라이프타임의 이해에 도움이 될 만한 몇 가지 포인트들을 적어보고자 합니다.

### 라이프타임 이란

Rust 에서 라이프타임(lifetime) 이란, **어떤 레퍼런스가 반드시 유효한 영역** 이란 뜻입니다. 

한 가지 중요한 점은 라이프타임이 변수들의 스코프와는 전혀 관련이 없다는 점입니다. 

Every lifetime is a link between data (place in memory) and referent (shared/mutable reference) which grants access to it. We can imagine that lifetime is combination of two scopes, not one:

liveness scope - which delimits how long data exists, and
referential scope - which delimits how long referent can be used.


### 가장 간단한 예제

```rust
fn main() {
    let r; 

    {
        let x = 5; // (1)
        r = &x; // (2)
    }

    println!("r: {}", r); // 오류
}
```

Rust 책으로 공부하면서 라이프타임에 대해서 이야기 할 때 가장 첫 번째로 나오는 예시가 바로 위 코드 입니다. 위 코드를 컴파일 하게 되면

```error
error[E0597]: `x` does not live long enough
 --> src/main.rs:5:13
  |
4 |         let x = 5;
  |             - binding `x` declared here
5 |         r = &x;
  |             ^^ borrowed value does not live long enough
6 |     }
  |     - `x` dropped here while still borrowed
7 |     println!("r : {}", r);
  |                        - borrow later used here
```

위와 같이 친절하게 컴파일러가 코드에 오류가 있다고 알려줍니다. 보아하니, 레퍼런스 `r` 이 참조하는 `x` 가 `r` 보다 더 오래 생존하지 않는다고 나와 있네요. 이를 컴파일러의 라이프타임을 검사하는 *Borrow Checker* 가 어떻게 검사하는지 Rust 책은 다음과 같이 설명하고 있습니다. 

```rust
fn main() {
    let r;                // ---------+-- 'a
                          //          |
    {                     //          |
        let x = 5;        // -+-- 'b  |
        r = &x;           //  |       |
    }                     // -+       |
                          //          |
    println!("r: {}", r); //          |
}                         // ---------+
```

위 코드를 보면, `r` 의 라이프타임은 `'a` 이고, `x` 의 라이프타임은 `'b` 임을 알 수 있습니다. 그런데 `r` 이 `x` 를 참조하는 과정에서 borrow checker 는 레퍼런스가 참조하는 값의 라이프타임이 자신의 라이프타임 보다 긴지를 확인하게 됩니다. 따라서 위 경우 레퍼런스의 라이프타임 `'a` 보다 `x` 의 라이프타임 `'b` 이 더 짧기 때문에 Borrow checker 

### Lifetime 은 scope 가 아니다.

### Lifetime 은 continuous 할 필요가 없다.

### Lifetime ellision

# 라이프타임의 Mutability 에 관해

## 규칙 1. 어떤 immutable 한 레퍼런스의 라이프타임 안에서는 immutable 