본문 바로가기

Rust

[Rust] 기초 문법

안녕하세요.

Rust Programming의 기초 문법에 대해 알아보겠습니다


💿 데이터 타입

Rust는 컴파일 타임에 데이터 타입이 결정되어야 합니다.

타입을 명시적으로 지정하거나, 컴파일이 타입을 추론할 수 있게 작성하면 됩니다.

fn main() {
    let x = 42; // i32로 타입 추론
    let y: f64 = 3.14; // f64 타입을 명시적으로 지정

    println!("x = {}, y = {}", x, y);
}

💿 자료 구조

튜플

여러 개의 값을 하나의 변수에 저장할 수 있는 자료형입니다.

서로 다른 타입의 값도 함께 포함할 수 있습니다.

fn main() {
    let person: (i32, f64, &str) = (30, 72.5, "Alice");
    println!("Age: {}, Weight: {}, Name: {}", person.0, person.1, person.2);
}

 

배열

선언과 동시에 배열 size가 고정됩니다.

  • 배열은 [T; N] 형태로 선언
  • T는 타입, N은 크기
fn main() {
    let arr: [i32; 3] = [1, 2, 3]; // 크기 3인 i32 배열
    println!("{:?}", arr); // [1, 2, 3]

    // arr[3] = 4; // 컴파일 에러: 크기 초과
}

 

+) size를 수정하고 싶으면?

→ Vector 사용

fn main() {
    // 벡터 선언
    let mut vec: Vec<i32> = Vec::new(); // 빈 벡터
    vec.push(1); // 요소 추가
    vec.push(2);
    vec.push(3);
    println!("{:?}", vec); // [1, 2, 3]

    // 크기 늘리기
    vec.push(4);
    println!("{:?}", vec); // [1, 2, 3, 4]

    // 크기 줄이기
    vec.pop(); // 마지막 요소 제거
    println!("{:?}", vec); // [1, 2, 3]
}

💿 변수와 가변성

불변성

모든 변수는 기본적으로 불변성 입니다.

fn main() {
    let x = 10; // 불변 변수 x
    println!("x의 초기값: {}", x);

    x = 15 // 컴파일 에러
}

 

 

mut 키워드를 추가하면 가변성이 가능합니다.

fn main() {
    let mut y = 10; // 가변 변수 y
    println!("y의 초기값: {}", y);

    y = 20; // 가변 변수이므로 재할당 가능
    println!("y의 수정된 값: {}", y);

    y += 5; // 가변 변수에 연산 적용
    println!("y의 최종 값: {}", y);
}

 

섀도잉

let을 그냥 한번 더 사용해서 변수를 덮을 수 있습니다.

(타입을 다르게 지정할 수도 있습니다.)

let var = 1;
let var = var + 1;
let var = "Hi";

💿 함수

반환 값의 타입은 화살표 ( →) 로 선언합니다.

fn main() {
    let result = add(3, 5);
    println!("3 + 5 = {}", result);
}

fn add(a: i32, b: i32) -> i32 {
    a + b // 세미콜론 없이 반환 (Rust의 암묵적 반환)
}

 

let과 {}를 함께 사용하면 익명 함수 사용이 가능합니다.

  • | | → 매개변수
fn main() {
    let y = 10;
    let add_y = |x: i32| { x + y }; // y를 캡처
    let result = add_y(5);
    println!("5 + {} = {}", y, result); // 5 + 10 = 15
}
fn main() {
    let mut counter = 0;
    let mut increment = || { counter += 1; }; // 가변 참조로 counter 캡처
    increment(); // 호출 1
    increment(); // 호출 2
    println!("카운터 값: {}", counter); // 카운터 값: 2
}

💿 제어문

if

코틀린처럼 변수에 값을 바로 집어넣을 수도 있습니다.

fn main() {
    let number = 42;
    let result = if number > 0 {
        "양수"
    } else {
        "음수 또는 0"
    };
    println!("{}은 {}", number, result); // 42은 양수
}

 

match

switch와 비슷합니다.

fn main() {
    let number = 5;
    let result = match number {
        0 => "영",
        1..=10 => "1에서 10 사이", // 범위 패턴
        _ => "그 외",
    };
    println!("결과: {}", result); // 결과: 1에서 10 사이
}

 

반복문

loop, while, for 등이 있습니다.

for문 예제만 보도록 하겠습니다.

fn main() {
    let vec = vec![1, 2, 3, 4];

    for val in &vec { // 참조로 순회
        println!("값: {}", val);
    }
}

💿 구조체

튜플과 비슷하지만, 구성 요소를 명명할 수 있어 유연합니다.

  • 파이썬처럼 첫 번째 파라미터는 언제나 &self 입니다.
struct Book {
    title: String,
    pages: u32,
}

impl Book {
    fn summary(&self) -> String {
        format!("{} ({}페이지)", self.title, self.pages)
    }
}

fn main() {
    let book = Book {
        title: String::from("Rust 배우기"),
        pages: 300,
    };
    println!("{}", book.summary()); // Rust 배우기 (300페이지)
}

💿 열거형

enum으로 열거형을 표현할 수 있습니다.

enum Direction {
    North,
    South,
    East,
    West,
}

fn main() {
    let dir = Direction::East;
    match dir {
        Direction::North => println!("북쪽"),
        Direction::South => println!("남쪽"),
        Direction::East => println!("동쪽"),
        Direction::West => println!("서쪽"),
    }
}

 

조금 더 복잡한 방식으로 사용하기도 합니다.

enum Message {
    Quit,                    // 데이터 없음
    Move { x: i32, y: i32 }, // 명명된 필드 (구조체 스타일)
    Write(String),           // 단일 값 (튜플 스타일)
    ChangeColor(i32, i32, i32), // 튜플 형태
}

fn main() {
    let msg = Message::Write(String::from("안녕!"));

    match msg {
        Message::Quit => println!("종료"),
        Message::Move { x, y } => println!("이동: ({}, {})", x, y),
        Message::Write(text) => println!("메시지: {}", text),
        Message::ChangeColor(r, g, b) => println!("색상: ({}, {}, {})", r, g, b),
    }
}

 

enum에도 메서드를 사용할 수 있습니다.

enum TrafficLight {
    Red,
    Yellow,
    Green,
}

impl TrafficLight {
    fn time(&self) -> u32 {
        match self {
            TrafficLight::Red => 60,
            TrafficLight::Yellow => 10,
            TrafficLight::Green => 45,
        }
    }
}

fn main() {
    let light = TrafficLight::Green;
    println!("초록불 지속 시간: {}초", light.time());
}