본문으로 이동

미디어위키 1.45 안정화가 거의 끝났습니다. 다만 Flow 확장 기능 관련 이슈가 있어서 대체하는 작업을 수행할 계획입니다.

  1. 큰숲백과:청사진에서 위키 발전의 대략적인 방향성을 제시했습니다. 의견이 있으신 분은 큰숲백과토론:청사진에서 의견을 남겨주시면 좋겠습니다.
  2. 기능상의 오류로 지원하지 않고 있는 기능에 대해서는 큰숲백과토론:이슈 트래커에 요약했습니다. 참고하시기 바랍니다.
  3. 데이터베이스 덤프 받고싶으신 분은 큰숲백과 가입 후에 사용자토론:Bigforest에 의견 남겨주시면 ftp 주소, 계정, 비밀번호를 특수:EmailUser를 통해서 공개할 예정입니다.

Rust (프로그래밍 언어)/문법

큰숲백과, 나무를 보지 말고 큰 숲을 보라.
Senouis (토론 | 기여)님의 2023년 7월 16일 (일) 08:49 판

이 문서에서는 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 전처리기와 네임스페이스 처리와 같은 기능을 동시에 수행한다.

참고로 내장 함수는 이름 끝에 !에 붙어 있으며, println!으로 문자열을 한 줄 출력하는 함수 등이 있다.

변수와 상수, 기본 연산

다음 접두어를 붙여 변수나 상수 등을 정의할 수 있다.

  • const: 상수, 처음 정의한 뒤에 그 값은 물론이고, Trait로 가져온 메서드로도 내부의 데이터를 바꾸지 못한다.
  • static: 프로그램이 끝날 때까지 남아있는 변수. 특정 상황에서는 변경이 가능하며, 이 때문에 이런 종류의 변수를 다루는 것은 unsafe하여 메모리 관련 에러를 낼 수 있다.
  • let: 일반 변수 선언. 하지만 값을 변경하는 행위에 제한이 있어 Trait에 따라 정의된 메서드로만 바꾸는 것이 가능한 경우가 일반적이다.
  • let mut: 완전히 자유로운 변경이 가능한 변수 선언. 이런 변수에 RAM 메모리 관련 기능을 넣는 것은 unsafe한 경우가 있다.

mut 접두어는 변수를 다루는 데에 높은 자유도를 보장하지만, Rust의 개발 배경이기도 한 C언어 등의 기존 시스템 프로그래밍용 언어의 환장할 수준의 메모리 관리 난이도를 Rust에도 가져오는 모순적인 문제로 인해 가급적 덜 쓰는 것을 권장한다. 특히 RAM 영역을 다루는 Trait가 있다면 mut를 최대한 안 쓰려고 하는 것이 매우 중요하다.

사칙연산과 나머지는 C와 동일하게 +, -, *, /, %이다. 또 연산 후 이동인 +=, -=, *=, /=, %=도 있으나, C언어의 1 증감 연산자인 ++, --는 없다.

비교 연산자는 C언어처럼 <. >, ==, !=, <=, >=이 있다. 단, IEEE 754 부동소수점 타입의 변수는 직접 좌변과 우변에 변수를 두지 말고 두 변수의 차를 f32::EPSILON 또는 f64::EPSILON과 비교하는 식으로 하여 정밀도에 따른 오차로 발생하는 부정확한 비교 문제를 예방해야 한다.

데이터 자료형

let var1: u32 = 32;let var2 = 32.5_f32; 같이 변수의 데이터 타입을 지정하여 변수명 뒤에 콜론과 함께 붙이거나 초기화 수치 뒤에 언더바와 함께 붙인다. 지정 가능한 타입은 다음과 같다.

  • u8 : 부호 없는 8비트 정수
  • u16 : 부호 없는 16비트 정수
  • u32 : 부호 없는 32비트 정수
  • u64 : 부호 없는 64비트 정수
  • i8 : 부호 있는 8비트 정수
  • i16 : 부호 있는 16비트 정수
  • i32 : 부호 있는 32비트 정수
  • i64 : 부호 있는 64비트 정수
  • f32 : 32비트 IEEE 754 단정밀도 부동소수점 실수
  • f64 : 64비트 IEEE 754 배정밀도 부동소수점 실수
  • usize : CPU가 한 사이클에 처리 가능한 최대 비트 크기의 부호 없는 정수
  • isize : CPU가 한 사이클에 처리 가능한 최대 비트 크기의 부호 있는 정수

그 외에 숫자 앞에 0b로 2진법, 0o로 8진법, 0x로 16진법 수치를 나타내며, println! 내장 함수로 이런 포맷으로 출력하려고 한다면 {} 대신 각각 {:b}, {:o}. {:x} 구문을 쓰면 된다.

변수 타입 캐스팅은 변수 뒤에 as (변환하려는 타입)를 붙여서 서로 다른 타입의 변수를 비교할 수 있다.

Expression, Statement의 차이

조건문 및 반복문

Rust의 함수 구조와 메모리 관련 기능

match로 람다 함수 구현하기

enum

match와의 결합으로 모나드 구현

예외 처리

Generic

Trait와 오버로딩

모듈을 사용한 코드 분할

패키지에서 Crate 가져오기, 네임스페이스

주요 Crate

  • num : 실수 외에 복소수 연산 같은 것도 지원한다.
  • regex: 정규 표현식 라이브러리
  • time: 시스템 시간 라이브러리
  • rand: 임의의 숫자를 뽑는 Random Value 관련 기능