3편까지는 변수와 자료형에 집중했다면, 이제 그 값들을 어떻게 조합하고 흐름을 제어할지 살펴봅니다. Rust의 함수는 fn 키워드로 정의하며, 표현식 기반 언어답게 if나 블록이 값을 돌려줄 수 있다는 점이 특징입니다. 4편에서는 함수 선언, 표현식 vs. 문(statement), 조건 분기, 반복문을 차근차근 정리합니다.
이번 글에서 새로 나오는 용어
- 표현식 (expression): 값을 만들어 내는 구문으로, Rust에서는 거의 모든 것이 표현식입니다.
- 문 (statement): 실행하지만 값을 돌려주지 않는 구문으로, 변수 선언 등이 여기에 해당합니다.
- loop 반복문: 조건 없이 무한 루프를 만들고
break로 빠져나오는 반복 구조입니다. - for 반복문: 이터러블을 순회하는 반복문으로, 배열·슬라이스 등에서 자주 사용합니다.
핵심 개념
- 함수는
fn 이름(매개변수: 타입) -> 반환타입 { ... }형태이며, 반환 타입을 생략하면()(unit)이 기본입니다. Rust는 동적 타입 언어와 달리 매개변수 타입을 함수 정의에 명시해야 하므로, 함수 시그니처만 봐도 어떤 값이 오가는지 더 분명하게 읽을 수 있습니다. - 블록
{}은 마지막 표현식의 값을 반환하므로,5 + 3같은 표현식 뒤에는 세미콜론을 붙이지 않아야 값이 돌아옵니다. if자체가 표현식이므로let grade = if score >= 90 { "A" } else { "B" };처럼 변수에 바로 대입할 수 있습니다.- 반복문은
loop,while,for세 가지를 우선 익히며,break와continue로 흐름을 제어합니다.
코드로 따라하기
1. 함수 기본 형태
fn main() {
greet("Mathbong");
let doubled = double(21);
println!("두 배: {doubled}");
}
fn greet(name: &str) {
println!("안녕하세요, {name}!");
}
fn double(value: i32) -> i32 {
value * 2 // 세미콜론 X: 표현식 반환
}
double 함수의 마지막 줄에 세미콜론을 붙이면 ()가 반환되므로 타입 오류가 발생합니다. Rust가 표현식 기반 언어라는 사실을 떠올리면 이유를 금방 이해할 수 있습니다.
예를 들어 아래 두 함수는 겉보기에는 비슷하지만 결과가 다릅니다.
fn add_ok(a: i32, b: i32) -> i32 {
a + b
}
fn add_wrong(a: i32, b: i32) -> i32 {
a + b;
0
}
첫 번째 함수는 마지막 표현식 a + b를 그대로 반환합니다. 반면 세미콜론이 붙으면 그 줄은 값을 돌려주지 않는 문이 되므로, 마지막 반환값을 따로 다시 적어야 합니다.
2. 표현식 vs. 문
fn main() {
let statement = {
let helper = 2;
helper * 3
}; // 블록 표현식 → 값 6
let condition = true;
let result = if condition { 10 } else { 0 };
println!("statement = {statement}, result = {result}");
}
블록 { ... } 안에서도 마지막 표현식이 값으로 반환됩니다. if 표현식은 모든 분기에서 같은 타입을 돌려줘야 한다는 점만 주의하면 됩니다.
3. if 조건문
fn main() {
let score = 87;
if score >= 90 {
println!("A 등급");
} else if score >= 80 {
println!("B 등급");
} else {
println!("C 이하");
}
}
Rust의 조건식에는 반드시 bool 타입이 필요합니다. 따라서 if score와 같은 파이썬 스타일의 truthy 체크는 허용되지 않습니다.
4. 반복문
fn main() {
let mut count = 0;
loop {
count += 1;
if count == 3 {
println!("loop 탈출");
break;
}
}
let mut n = 3;
while n > 0 {
println!("while: {n}");
n -= 1;
}
let numbers = [10, 20, 30];
for value in numbers {
println!("for: {value}");
}
}
loop는 명시적으로break를 호출해야 종료됩니다.break value;형태로 값을 반환해 변수에 대입할 수도 있습니다.while은 조건이 true인 동안 반복합니다.for는Iterator구현체를 순회하므로, 배열이나 범위 같은 값을 한 칸씩 꺼내 처리합니다. 예를 들어0..5는 0부터 4까지를 뜻하고,1..=5는 1부터 5까지를 뜻합니다.
왜 중요한가
- 함수와 제어 흐름을 이해해야 이후 ownership 규칙을 함수 경계에서 어떻게 적용할지 설명할 수 있습니다.
- 표현식 기반 사고방식은
if와match, 블록 반환 등을 자연스럽게 받아들이게 하고, 나중에?연산자나 클로저를 배울 때도 도움이 됩니다. - 반복문 패턴을 익혀 두면 나중에 이터레이터나 패턴 매칭으로 확장할 때 비교 기준을 세울 수 있습니다.
CodeSandbox로 이어서 실습하기
아래 샌드박스는 CodeSandbox의 Rust starter입니다. 이번 글의 핵심 코드를 src/main.rs에 옮기고, cargo check와 cargo run 결과를 나란히 보면서 컴파일 메시지와 실행 출력을 비교해 보세요.
💬 댓글
이 글에 대한 의견을 남겨주세요