콘텐츠로 이동

Rust 문법

이제 Rust를 실행할 수 있게 됐으니, 잠깐 속도를 늦추고 프로그램의 각 부분이 실제로 무슨 뜻인지 살펴볼게요. 가장 작은 예제를 하나 골라서 한 조각씩 뜯어볼 거예요.

fn main() {
println!("안녕하세요, 세상!");
}

실행 결과:

안녕하세요, 세상!
▶ 직접 실행해 보기
fn main() {
// 여기에 있는 코드가 실행돼요
}

모든 Rust 프로그램은 main이라는 함수에서 시작해요. 프로그램을 실행하면 Rust는 main을 찾아서 그 안의 코드를 실행해요.

  • fn은 함수(이름이 붙은 코드 묶음)를 정의하는 키워드예요.
  • main은 함수의 이름이에요. 이 이름은 특별해서, 프로그램의 시작점(entry point)이 돼요.
  • ()에는 함수의 입력값이 들어가요. 여기서는 비어 있어요. main은 입력을 받지 않거든요.
  • { } 중괄호는 본문(body), 즉 함수에 속한 코드를 감싸요.

본문 안의 각 명령은 보통 구문(statement)이고, 구문은 세미콜론 ;으로 끝나요.

fn main() {
let x = 5;
let y = 10;
println!("{}", x + y);
}

실행 결과:

15
▶ 직접 실행해 보기

세미콜론이 필요한 곳에 세미콜론을 빼먹는 건 초보자가 가장 많이 하는 실수 중 하나예요. 그래도 걱정 마세요. 컴파일러가 정확히 그 자리를 짚어 줄 거예요.

Rust 코드는 두 종류의 조각으로 이루어져 있어요. 그리고 이 차이는 다른 언어보다 Rust에서 훨씬 중요해요.

  • 구문(statement)은 무언가를 하지만 값을 돌려주지 않아요. let x = 5;는 구문이에요.
  • 표현식(expression)은 값을 만들어 내요. 5, x + 1, x * 2는 모두 표현식이에요.

많은 사람이 놀라는 부분이 여기예요. 중괄호 { }로 감싼 코드 블록도 표현식이에요. 블록의 값은 세미콜론 없이 쓴 마지막 줄이에요.

fn main() {
let x = 5;
let y = {
let doubled = x * 2; // 블록 안의 구문
doubled + 1 // 세미콜론 없음: 이게 블록의 값이에요
};
println!("y의 값은 {y}");
}

실행 결과:

y의 값은 11
▶ 직접 실행해 보기

블록은 안에 있는 구문을 실행한 다음 doubled + 1, 즉 11을 돌려주고, 그 값이 y가 돼요. 닫는 } 뒤에 세미콜론이 있는 것도 눈여겨보세요. let y = ...; 줄 전체는 여전히 구문이에요.

doubled + 1 뒤에 세미콜론을 붙이면 그건 더 이상 블록의 값이 아니게 돼요. 그러면 블록은 “아무것도 없음”(Rust에서는 ()로 써요)을 돌려주고, println!은 그걸 출력할 수 없어서 컴파일이 안 돼요. 이 “마지막 줄에는 세미콜론을 붙이지 않는다” 규칙은 함수가 값을 반환하는 방식과 똑같아요. 함수 페이지와 표현식으로서의 if에서 다시 보게 될 거예요.

println!을 자세히 보세요. 끝에 붙은 느낌표는 오타가 아니에요. !는 이게 일반 함수가 아니라 매크로(macro)라는 표시예요.

매크로를 지금 완벽하게 이해할 필요는 없어요. 이것만 기억하세요. !가 보이면 매크로예요. 지금 당장 쓸 매크로는 텍스트를 출력하는 println! 하나뿐이에요.

fn main() {
println!("이건 매크로 호출이에요");
}

println! 안의 중괄호 {}는 자리 표시자(placeholder)예요. 텍스트 뒤에 넘겨준 값으로 채워져요.

fn main() {
let name = "Ferris";
let age = 10;
println!("{}는 {}살이에요", name, age);
}

실행 결과:

Ferris는 10살이에요
▶ 직접 실행해 보기

중괄호 안에 변수 이름을 바로 쓸 수도 있어요. 이쪽이 더 깔끔할 때가 많아요.

println!("{name}는 {age}살이에요");

Rust는 Python처럼 들여쓰기에 의미를 두지 않아요. 블록이 어디서 시작하고 끝나는지는 중괄호 { }로 알아요. 들여쓰기는 그저 사람이 코드를 읽기 쉽게 하려고 하는 거예요.

그렇긴 해도 커뮤니티에는 표준 스타일이 있고, Rust에는 그 스타일을 자동으로 맞춰 주는 도구가 들어 있어요.

Terminal window
cargo fmt

cargo fmt를 실행하면 코드가 공식 스타일로 다시 정리돼요. 습관처럼 쓰는 걸 추천해요.

코드 안에 Rust가 무시하는 메모를 남길 수 있어요. 이걸 주석(comment)이라고 하고, //로 시작해요.

fn main() {
// 이건 주석이에요. Rust는 건너뛰어요
println!("안녕하세요!"); // 줄 끝에도 주석을 달 수 있어요
}

주석은 다음 페이지에서 더 자세히 다뤄요.

변수 두 개 a = 7, b = 3을 만들고 7 + 3 = 10을 출력해 보세요. 덧셈은 Rust에게 맡기세요. 힌트: println!에는 {} 자리 표시자를 여러 개 넣을 수 있고, 텍스트 뒤에 오는 값들이 순서대로 채워져요.

정답 보기
fn main() {
let a = 7;
let b = 3;
println!("{} + {} = {}", a, b, a + b);
}

실행 결과:

7 + 3 = 10
▶ 직접 실행해 보기

어떤 가게에서 개당 4인 물건을 3개 팔고, 배송비로 2를 더 받아요. { } 블록으로 total을 계산해 보세요. 블록 안에서 subtotal을 만들고, subtotal + 2를 돌려주면 돼요. 그리고 합계: 14를 출력하세요. 힌트: 블록의 마지막 줄에는 세미콜론이 없어야 해요.

정답 보기
fn main() {
let price = 4;
let quantity = 3;
let total = {
let subtotal = price * quantity;
subtotal + 2 // 배송비
};
println!("합계: {total}");
}

실행 결과:

합계: 14
▶ 직접 실행해 보기
  • 모든 프로그램은 main 함수에서 시작해요.
  • 코드는 중괄호 { } 안에 들어가고, 대부분의 구문은 ;로 끝나요.
  • 구문은 무언가를 하고, 표현식은 값을 만들어요. 블록에서 ; 없이 쓴 마지막 줄이 그 블록의 값이에요.
  • println!처럼 !가 붙어 있으면 매크로예요.
  • println! 안의 {}는 넘겨준 값으로 채워지는 자리 표시자예요.
  • 들여쓰기는 읽기 쉽게 하려는 거예요. cargo fmt를 실행하면 자동으로 정리돼요.

이해도 점검

1. Rust 프로그램에서 main 함수의 특별한 점은 무엇일까요?

2. println 뒤의 !는 무슨 뜻일까요?

3. let y = { let a = 2; a + 1 }; 다음에 y의 값은 무엇일까요?

점수: 0 / 3