# 구문과 문장

러스트에서 코드를 구성할 때는 구문(syntax)과 문장(statement)을 명확히 구분해야 한다. 구문이란 언어가 정해 놓은 모든 문법적 규칙의 총체이고, 문장은 그러한 구문에 따라 코드 상에서 수행되는 최소 단위의 역할을 한다. 러스트는 표현식(expression)과 문장을 엄격하게 구별하는 것으로 유명하며, 이는 함수의 반환 타입부터 제어 흐름까지 광범위한 영향력을 미친다.

러스트에서 눈여겨볼 핵심은 “표현식은 값을 생성하지만, 문장은 별도의 값을 생성하지 않는다”라는 점이다. 대부분의 전통적인 언어에서 표현식과 문장이 섞여 있기 때문에 이를 의식하지 않고 코드를 작성하더라도 큰 문제가 생기지 않는다. 하지만 러스트에서는 두 개념을 엄밀히 구분함으로써, 프로그램 작성 시 더욱 명시적이고 의도적인 코딩을 하게끔 유도한다.

코드 상에서 표현식과 문장을 구분하기 위해서는 세미콜론의 쓰임을 주의 깊게 살펴봐야 한다. 러스트에서 세미콜론(;)은 표현식을 문장으로 ‘종결’시키는 역할을 한다. 즉, 원래는 어떤 값을 생성하는 표현식이었다가, 세미콜론을 붙이면 문장이 되며 값을 반환하지 않게 된다. 이러한 특성은 함수나 블록 내에서 마지막에 세미콜론이 없는 표현식을 명시적으로 반환값으로 삼는 러스트의 특징에도 영향을 준다.

다음 예시는 표현식과 문장의 차이를 보여준다.

```
fn main() {
    let x = 5;            // let x = 5는 문장이다. 여기서 5는 표현식이지만 세미콜론으로 문장이 됨
    let y = {
        let z = 3;        // let z = 3 역시 문장
        z + 1             // z + 1은 세미콜론이 없으므로 '표현식'이고, 블록의 반환값이 됨
    };
    println!("x = {}, y = {}", x, y);
}
```

위 코드에서 let x = 5;는 문장이며, let z = 3;도 문장이다. 반면에 블록 마지막에 위치한 z + 1은 세미콜론이 붙지 않았으므로 표현식이다. 이 블록 전체는 최종 표현식인 z + 1의 값, 즉 4를 반환하며, y는 4라는 값을 얻는다.

표현식을 문장처럼 사용할 때 세미콜론을 붙이게 되면 그 표현식은 더 이상 반환값을 가지지 않는다. 이는 함수를 작성할 때 return을 명시하는 것과 블록 마지막 표현식을 그대로 사용하는 것 사이의 차이점을 이해할 때 중요해진다.

```
fn return_expression() -> i32 {
    10          // 세미콜론이 없으므로 이 블록의 표현식이 10이고, 함수의 반환값도 10이 됨
}

fn return_statement() -> i32 {
    10;         // 세미콜론을 붙였으므로 이 블록은 값을 반환하지 않고, 에러가 발생
    // 만약 마지막에 '10;'이 아닌 어떤 문장이 필요하다면, 
    // 명시적으로 'return 10;'을 사용하거나, 블록 마지막에 표현식을 남겨야 함
}
```

위 코드에서 return\_expression 함수는 10이라는 표현식을 그대로 반환하지만, return\_statement 함수의 경우 블록 내부에 세미콜론으로 끝나는 문장이 들어가 있으므로 아무 값도 반환하지 못한다. 러스트에서는 반환 타입이 명시된 함수에서 반환값이 없으면 컴파일 오류가 발생한다.

이처럼 구문과 문장을 엄격하게 구분하는 것은 함수형 언어에서 종종 보이는 특징으로서, 순수하게 값을 만들어내는 블록과 그렇지 않은 블록을 직관적으로 판단할 수 있게 해준다. 또한 이러한 구조는 제어 흐름에서 가독성과 예측 가능성을 높여준다.

블록 자체는 표현식이 될 수도 있고, 내부에 문장을 여러 개 넣어도 마지막에 세미콜론이 없는 표현식이 존재하면 그 블록 전체가 해당 값을 반환한다. 이때 내부에서 사용하는 let 바인딩이나 if-else, 반복문 등의 구문은 러스트 문법에 맞춰 엄격하게 사용해야 하며, 언제 세미콜론이 붙는지에 따라 프로그램 흐름과 반환값이 달라질 수 있으므로 주의 깊게 살펴봐야 한다.

변수 바인딩 자체도 문장이지만, 바인딩 우변에 오는 식(Expression)은 값으로 평가될 수 있다. 예를 들어 let x = 3 + 2는 3 + 2가 표현식으로서 5라는 값을 생성하고, 최종적으로 let x = 5; 형태가 되어 문장이 된다. 따라서 코드를 작성할 때 이 구분을 정확히 이해해 두면, 불필요하게 세미콜론을 사용하는 실수를 줄이고 보다 의도에 맞는 코드를 구성할 수 있다.

마지막으로 러스트의 if 구문도 표현식으로 사용할 수 있다. 다른 언어에서 if 구문이 주로 문장으로만 동작하는 것과 달리, 러스트에서 if는 값을 반환할 수 있는 표현식이 될 수 있다. 예를 들어 아래와 같이 사용할 수 있다.

```
fn main() {
    let number = 6;
    let result = if number % 2 == 0 {
        "짝수"
    } else {
        "홀수"
    };
    println!("결과: {}", result);
}
```

위 코드에서 if number % 2 == 0 { "짝수" } else { "홀수" }는 전체가 하나의 표현식이며, 선택된 값이 result에 할당된다. 세미콜론을 붙이지 않았기 때문에 "짝수" 혹은 "홀수" 문자열이 그대로 반환되어 result에 대입된다. 만약 세미콜론을 붙였다면 문장이 되어 값을 반환하지 못해 컴파일 오류가 발생한다.

이처럼 러스트의 구문과 문장 개념은 코드 구조와 제어 흐름을 더욱 명확하게 만들어 준다. 표현식과 문장의 차이를 숙지하면 함수의 반환값을 자연스럽게 처리할 수 있고, 블록을 유연하게 구성하여 가독성과 안전성을 높일 수 있다. 이 모든 구문과 문장의 구분은 러스트가 지향하는 안전성과 일관성, 그리고 예측 가능한 메커니즘을 뒷받침하는 중요한 기둥이 된다.
