Rust를 내 컴퓨터에 설치하기
지금까지는 Rust Playground에서 코드를 실행했어요. 이번 모듈부터는 내 컴퓨터에서 직접 프로그램을 만들어볼 거예요!
터미널에서 아래 명령어를 실행하면 Rust가 설치돼요.
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
Windows라면 rustup.rs에서 설치 파일을 다운로드하세요.
설치가 끝나면 확인해볼까요?
rustc --version
cargo --version
버전 번호가 나오면 성공이에요!
Cargo — Rust의 도구 모음
Cargo는 Rust의 빌드 시스템이자 패키지 매니저예요. 프로젝트 생성, 빌드, 실행, 외부 라이브러리 관리까지 모두 Cargo가 해줘요.
새 프로젝트를 만들어볼게요.
cargo new guessing_game
cd guessing_game
이 명령어를 실행하면 이런 폴더 구조가 만들어져요.
guessing_game/
├── Cargo.toml # 프로젝트 설정 파일
└── src/
└── main.rs # 코드 파일
src/main.rs를 열면 이미 "Hello, world!"가 들어있어요. cargo run으로 실행해보세요!
cargo run
동작하는 코드: 숫자 맞추기 게임
이제 본격적으로 게임을 만들어볼게요. 먼저 랜덤 숫자를 만들기 위해 rand 크레이트(crate)를 추가해야 해요. 크레이트는 다른 사람이 만든 라이브러리예요.
cargo add rand
이 명령어가 Cargo.toml에 rand를 자동으로 추가해줘요.
아래 코드를 src/main.rs에 붙여넣고 cargo run으로 실행해보세요!
use std::io;
use std::cmp::Ordering;
use rand::Rng;
fn main() {
println!("숫자 맞추기 게임!");
let secret = rand::thread_rng().gen_range(1..=100);
loop {
println!("숫자를 입력하세요 (1~100):");
let mut guess = String::new();
io::stdin().read_line(&mut guess).unwrap();
let guess: i32 = match guess.trim().parse() {
Ok(num) => num,
Err(_) => {
println!("숫자를 입력해주세요!");
continue;
}
};
match guess.cmp(&secret) {
Ordering::Less => println!("더 커요!"),
Ordering::Greater => println!("더 작아요!"),
Ordering::Equal => {
println!("정답!");
break;
}
}
}
}
실행하면 숫자를 입력하라는 메시지가 나와요. 숫자를 입력하면 정답보다 큰지 작은지 알려주고, 맞출 때까지 반복해요!
한 줄씩 이해하기
코드가 좀 길죠? 하나씩 뜯어볼게요.
1단계: 가져오기
use std::io;
use std::cmp::Ordering;
use rand::Rng;
use는 다른 곳에 있는 기능을 가져오는 키워드예요.
std::io— 사용자 입력/출력 기능std::cmp::Ordering— 두 값을 비교한 결과 (Less,Greater,Equal)rand::Rng— 랜덤 숫자를 만드는 기능 (우리가 추가한 크레이트)
2단계: 랜덤 숫자 생성
let secret = rand::thread_rng().gen_range(1..=100);
1부터 100 사이의 랜덤 숫자를 하나 만들어서 secret에 저장해요. 1..=100은 for 반복문에서 배운 범위 문법과 같아요!
3단계: 사용자 입력 받기
let mut guess = String::new();
io::stdin().read_line(&mut guess).unwrap();
String::new()로 빈 문자열을 만들고, read_line()으로 사용자가 입력한 텍스트를 저장해요. unwrap()은 "에러가 나면 프로그램을 멈춰라"라는 뜻이에요. 에러 처리는 나중에 제대로 배울 거예요.
4단계: 문자열을 숫자로 변환
let guess: i32 = match guess.trim().parse() {
Ok(num) => num,
Err(_) => {
println!("숫자를 입력해주세요!");
continue;
}
};
사용자가 입력한 건 문자열이에요. 숫자와 비교하려면 i32로 바꿔야 해요.
trim()— 입력 끝에 붙는 줄바꿈 문자를 제거parse()— 문자열을 숫자로 변환 시도match— 변환 결과에 따라 분기 (성공하면Ok, 실패하면Err)
같은 이름 guess를 다시 let으로 선언한 거 보이시나요? 모듈 02에서 배운 섀도잉이에요! 문자열 guess를 숫자 guess로 바꾼 거예요.
5단계: 비교하기
match guess.cmp(&secret) {
Ordering::Less => println!("더 커요!"),
Ordering::Greater => println!("더 작아요!"),
Ordering::Equal => {
println!("정답!");
break;
}
}
cmp()는 두 값을 비교해서 Less(작음), Greater(큼), Equal(같음) 중 하나를 돌려줘요. match로 각 경우에 맞는 메시지를 출력하고, 정답이면 break로 반복을 끝내요.
"왜?" — 여기까지 오셨으면 Rust 기본기를 갖춘 거예요!
이 프로그램에 지금까지 배운 것이 다 들어있어요.
- 변수와 가변성:
let,let mut - 타입:
i32,String - 함수 호출:
println!(),read_line(),parse() - 조건 분기:
match(if보다 강력한 분기 방법!) - 반복문:
loop+break,continue - 범위:
1..=100
처음엔 복잡해 보여도, 하나씩 뜯어보면 이미 아는 것들의 조합이에요. Phase 2에서는 소유권, 구조체, 에러 처리 같은 Rust만의 독특한 개념들을 배울 거예요. 기대하세요!
심화 학습
Cargo.toml — 프로젝트 설정 파일 살펴보기
Cargo.toml을 열어보면 이런 내용이 있어요.
[package]
name = "guessing_game"
version = "0.1.0"
edition = "2021"
[dependencies]
rand = "0.8"
[package]— 프로젝트 이름, 버전, Rust 에디션[dependencies]— 외부 크레이트 목록.cargo add rand를 실행하면 여기에 자동으로 추가돼요
자주 쓰는 Cargo 명령어도 알아둘게요.
| 명령어 | 하는 일 |
| -------------------- | ------------------------------------ |
| cargo new 이름 | 새 프로젝트 생성 |
| cargo run | 빌드 + 실행 (개발 중 가장 많이 사용) |
| cargo build | 빌드만 (실행은 안 함) |
| cargo check | 컴파일 가능한지 빠르게 검사 |
| cargo add 크레이트 | 외부 크레이트 추가 |
match — if보다 강력한 분기
이 게임에서 match가 두 번 나와요. match는 if/else if와 비슷하지만, 모든 경우를 빠짐없이 처리해야 해요.
fn main() {
let number = 3;
match number {
1 => println!("하나"),
2 => println!("둘"),
3 => println!("셋"),
_ => println!("다른 숫자"), // 나머지 모든 경우
}
}
_는 "그 외 나머지"를 뜻해요. match에 대해서는 Phase 2에서 훨씬 더 자세히 배울 거예요.
숫자가 아닌 값을 parse()하면 에러가 발생해요. 우리 게임에서는 match로 이걸 처리하고 있어요.
만약 match 대신 unwrap()을 썼다면?
// 이렇게 하면 숫자가 아닌 입력 시 프로그램이 멈춰요!
let guess: i32 = guess.trim().parse().unwrap();
"abc"를 입력하면 이런 에러가 나요.
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value:
ParseIntError { kind: InvalidDigit }'
해석: "숫자가 아닌 값을 숫자로 바꾸려 했어요"라는 뜻이에요. unwrap() 대신 match를 쓰면 에러 상황을 우아하게 처리할 수 있어요.
미니 프로젝트: 게임 업그레이드
기본 게임이 잘 돌아가면, 아래 기능을 하나씩 추가해보세요!
- 시도 횟수 세기: 몇 번 만에 맞췄는지 출력하기. 힌트:
mut변수로 카운터를 만드세요. - 범위 제한: 1~100 범위 밖의 숫자를 입력하면 "1에서 100 사이의 숫자를 입력해주세요!"라고 안내하기.
- 난이도 선택: 게임 시작 전에 범위를 선택할 수 있게 만들기. (예: 1~10, 1~100, 1~1000)
Q1. Cargo로 새 프로젝트를 만드는 명령어는?
- A)
cargo init project - B)
cargo new project - C)
cargo create project - D)
cargo start project
Q2. 아래 코드에서 guess.trim().parse()의 역할은?
let guess: i32 = guess.trim().parse().unwrap();
- A) 문자열을 대문자로 바꾼다
- B) 공백을 제거하고 숫자로 변환한다
- C) 문자열을 거꾸로 뒤집는다
- D) 문자열을 복사한다
Q3. match에서 _는 무엇을 의미할까요?
- A) 에러가 발생한다
- B) 아무것도 하지 않는다
- C) 나머지 모든 경우를 처리한다
- D) 반복을 멈춘다