난 러스트가 전파되기를 희망하는 프붕이다


개인적으로 러스트가 정말 좋다고 생각하지만

러스트의 사용률이 생각보다 높지가 않아 아쉬울 따름이다


그래서 직접 러스트를 전파하고자

이 시리즈를 쓰게 되었다


나도 아직 러스트를 배우는 단계이기 때문에

잘못된 개념이 있다면 짚어주면 감사할 것 같다


그럼 시작해 보겠다


// filename: main.rs fn main() { println!("Hello, Rust!"); }


진부해 빠진 헬로 코드다


그래도 진부함을 덜어내고자 월드를 빼고 러스트로 대체하였다


여기서 몇 가지 짚을 만한 사항을 알아보자


1. 러스트의 파일 확장명은 rs다


주석에 써놓았듯이 러스트의 파일 확장명은 rs이며, 러스트라는 뜻이다


2. 러스트는 fn main으로 시작한다


러스트는 라이브러리로 설정된 게 아닌 이상 fn main으로 시작한다


여기서 fn은 function의 약자이며, 함수라는 뜻이다


3. 러스트는 인라인 중괄호를 권장한다


러스트 공식 문서에도 나와 있지만

러스트는 인라인 중괄호를 권장한다


인라인 중괄호를 쓰면 시작줄과 끝줄을 하나로만 만들 수 있고

전체적인 코딩의 세로 길이도 짧아지게 되는 장점이 있다.


4. 러스트의 권장 들여쓰기는 스페이스 4번이다


탭은 포맷에 따라 2, 4, 8 등 다양한 길이가 될 수 있다는 단점이 있다.


스페이스를 사용하면 그런 차이를 없앨 수 있고,

러스트는 그중에서도 4칸을 사용하기로 선택하였다.


5. 느낌표는 매크로를 의미한다


함수와 매크로의 차이는, 함수는 런타임 때 호출되는 것이고

매크로는 컴파일 타임 때 다른 코드로 변경된다는 것이다


6. 러스트의 main 함수는 리턴이 의무가 아니다


기본적으로 리턴 부분이 없다는 것을 알 수 있다


함수에 리턴 값을 주려면 fn func() -> i32 처럼 화살표를 써야 한다



러스트의 특이점 중 하나는 자료형에 관한 부분을 뒤에 표기한다는 것이다


이는 변수도 마찬가지인데, 변수에 대해서도 얘기해 보도록 하겠다


러스트의 데이터 타입은 크게 두 가지로 나눌 수 있다


scalar type: 원소가 하나인 데이터 타입

compound type: 원소가 여러 개인 데이터 타입


scalar type 종류: 정수, 부동소수점, 불린, 캐릭터

compound type 종류: 배열, 투플, 벡터, 스트링


부호 있는 정수: i8, i16, i32, i64, i128, isize

부호 없는 정수: u8, u16, u32, u64, u128, usize

부동소수점 실수: f32, f64

불린: bool

캐릭터: char


보면 알겠지만 러스트의 장점은

자료형의 크기가 자료형 이름 자체에 명시돼 있다는 점이다

isize, usize는 운영체제가 32비트냐 64비트냐에 따라서 달라진다


bool은 당연히 1이고, 특이한 점은 char의 크기가 4바이트다

이는 유니코드에 대응하기 위하여 미리 크게 정한 것으로 보인다

좀 크다 싶을 수도 있겠지만,

문자열 관련 문제를 최소화하기 위해 이런 선택을 한 것으로 보인다


배열: let array[i32; 5] = [0, 1, 2, 3, 4];

투플: let tuple(i32, f32) = (10, 1.0);

벡터: let mut vector: Vec<i32> = vec![0, 1, 2, 3, 4];

스트링: let string: String = String::from("Hello, Rust!");


여기서 벡터 부분을 보면 let mut이라고 쓴 걸 볼 수 있는데

러스트에서 let만 쓰면 기본적으로 변수는 상수성을 지닌다

러스트에서는 immutable이라고 표현한다

let mut은 변경할 수 있으며, mutable이라는 뜻이다


배열은 크기가 고정돼 있으며, 메모리의 스택 공간에 저장된다

투플도 스택에 저장되는데, 원소마다 다양한 자료형을 가질 수 있다


벡터는 힙에 저장되며, 크기가 바뀔 수 있다

크기가 바뀔 수 있기 때문에 그에 어울리게 let mut을 저기서 소개한 것이다


스트링은 기본적으로 char로 이루어진 벡터다

그래서 힙에 저장되며, 원소별 접근도 가능하다

그래서 벡터와 본질적으로 크게 다른 점은 없다

하지만 스트링이기 때문에 스트링만의 다양한 메소드를 제공한다


마지막으로 struct와 enum에 대해 소개하고 끝내겠다


// 함수 중간에서도 선언 가능 struct MyStruct { _name: String, _age: u8, } let _my_struct = MyStruct { _name: String::from("John"), _age: 20, }; // 마찬가지로 함수 중간에서도 선언 가능 enum MyEnum { _A(i32), // tuple struct (with one element) _B(i32, f32), // tuple struct (with multiple elements) _C, // unit struct _D{ _x: i32, _y: i32 }, // struct } // enum의 다양한 사용 사례 let _my_enum = MyEnum::_A(1); // tuple struct (with single element) let _my_enum = MyEnum::_B(1, 1.0); // tuple struct (with multiple elements) let _my_enum = MyEnum::_C; // unit struct let _my_enum = MyEnum::_D{ _y: 1, _x: 2 }; // 순서가 바뀌어도 상관없음


struct는 다른 언어에서도 흔히 보이는 뻔한 struct지만,

러스트의 enum은 단순히 정수형이 아니라 좀 더 유연한 형태다


다른 언어에서의 union, 공용체와 비슷한 개념이다

특기할 만한 점은 저기 C 부분이 unit struct로 되어 있다는 점인데,


러스트에서 unit이라는 개념은 값이 그것밖에 없는 자료형을 말한다

main처럼 리턴값을 명시하지 않은 함수의 기본 자료형은 유닛 자료형이다

return (); 이런 식으로 괄호를 사용하여 명시적으로 리턴할 수도 있으나,

애초에 값이 그것밖에 없기 때문에 그냥 return으로 써도 상관없다


러스트는 기본적인 기능만 해도 사실 한도끝도 없이 다양하다

어디 손을 벌리지 않고

최대한 기본적인 기능 내에서 끝내려고 하다 보니 그렇게 된 듯하다

이뿐만 아니라 use 키워드를 사용해 포함할 수 있는 것까지 합치면

HashMap, HashSet 등 다양한 std 계열 자료구조까지 있고

설명 안 한 내용 중에도 템플릿, 매크로 등 여러 가지 것들이 있다


하지만 이번 글은 러스트의 기본적인 자료형만을

최대한 축약해서 보여주려고 한 것이기 때문에 생략하도록 하겠다


정리 (러스트의 기본적인 자료형)


  • scalar type
    • signed integer
      • i8
      • i16
      • i32
      • i64
      • i128
      • isize (32비트 운영체제에선 32비트, 64비트 운영체제에선 64비트)
    • unsigned integer
      • u8
      • u16
      • u32
      • u64
      • u128
      • usize
    • floating point
      • f32
      • f64
  • compound type
    • array
    • tuple
    • vector
    • string
  • custom type
    • struct
    • enum

러스트의 데이터 타입에 대해 알아보았으니
다음에는 조건문, 반복문 등 컨트롤 플로우에 대해서 알아보도록 하겠다


출처: 프로그램 갤러리 (러스트 얘기 환영)