Rust (프로그래밍 언어)/문법
이 문서에서는 Rust 프로그래밍 언어로 프로그램을 개발하기 위한 프로세스와 언어 문법을 다룬다.
일단 Rust는 객체지향 프로그래밍(Object Oriented Programming)을 목적으로 만든 언어가 아니다. 따라서 C언어의 class 관련 기능은 물론이고, 캡슐화/다형성/상속에 직접 대응하는 기능이 언어 차원에서는 없다. Rust의 대표 특징 중 하나인 Trait 개념은 오히려 Javascript의 Prototype에 가까운 형태이나, Rust의 등호 기호(=)의 동작이 복사가 아닌 단방향 데이터 이동임을 생각하면 Trait는 Prototype과는 또 다르며, C++ 언어의 인터페이스와도 유사한 측면이 있는 등 Rust만의 독특한 특징으로 꼽힌다.
Cargo 기반 개발 환경 세팅 및 프로그램 기본 구조
물론 rustc로 직접 rs 파일을 컴파일할 수 있지만, 보통은 Rust의 공식 패키지 매니저인 cargo로 프로젝트를 생성한다.
cargo 사용법과 toml 파일
먼저 cargo new (프로젝트 명칭)으로 프로젝트를 생성한다.
프로젝트를 테스트할 때에는 cargo run으로 컴파일 및 실행을 동시에 하며, 배포할 때는 cargo build를 사용한다.
외부 라이브러리를 가져올 때는 cargo add (패키지 명칭)로 (프로젝트 명칭).toml 파일에 라이브러리 의존성을 추가한다.
rs 파일의 기본 구조
use std::time::{Duration, SystemTime};
use std::thread::sleep;
fn main() {
let now = SystemTime::now();
// we sleep for 2 seconds
sleep(Duration::new(2, 0));
match now.elapsed() {
Ok(elapsed) => {
// it prints '2'
println!("{}", elapsed.as_secs());
}
Err(e) => {
// an error occurred!
println!("Error: {e:?}");
}
}
}위 코드는 Rust의 SystemTime 구조체 예제에서 가져왔다. main 함수를 정의하면 거기가 프로그램의 진입점이 되고, use로 C++언어의 #include 전처리기와 네임스페이스 처리와 같은 기능을 동시에 수행한다.
변수와 상수, 기본 연산
다음 접두어를 붙여 변수나 상수 등을 정의할 수 있다.
- const: 상수, 처음 정의한 뒤에 그 값은 물론이고, Trait로 가져온 메서드로도 내부의 데이터를 바꾸지 못한다.
- static: 프로그램이 끝날 때까지 남아있는 변수. 특정 상황에서는 변경이 가능하며, 이 때문에 이런 종류의 변수를 다루는 것은 unsafe하여 메모리 관련 에러를 낼 수 있다.
- let: 일반 변수 선언. 하지만 값을 변경하는 행위에 제한이 있어 Trait에 따라 정의된 메서드로만 바꾸는 것이 가능한 경우가 일반적이다.
- let mut: 완전히 자유로운 변경이 가능한 변수 선언. 이런 변수에 RAM 메모리 관련 기능을 넣는 것은 unsafe한 경우가 있다.
mut 접두어는 변수를 다루는 데에 높은 자유도를 보장하지만, Rust의 개발 배경이기도 한 C언어 등의 기존 시스템 프로그래밍용 언어의 환장할 수준의 메모리 관리 난이도를 Rust에도 가져오는 모순적인 문제로 인해 가급적 덜 쓰는 것을 권장한다. 특히 RAM 영역을 다루는 Trait가 있다면 mut를 최대한 안 쓰려고 하는 것이 매우 중요하다.