Rust, ๊ธฐํ˜ธ

Jeonghak Choยท2025๋…„ 6์›” 22์ผ

Rust

๋ชฉ๋ก ๋ณด๊ธฐ
13/13

๐Ÿ“— RUST, ๊ธฐํ˜ธ

๐Ÿณ๏ธโ€๐ŸŒˆ [๊ถ๊ธˆํ•œ์ ]

  • Rust์˜ ๊ธฐํ˜ธ๊ฐ€ ๋ณต์žกํ•˜๋‹ค๊ณ  ๋А๊ปด์ง€๋Š” ์ด์œ 

๐Ÿ”—[๋ชฉ์ฐจ]


๐Ÿ“‹ ๊ฐœ์š”

Rust์˜ ๊ธฐํ˜ธ๊ฐ€ ๋ณต์žกํ•˜๋‹ค๊ณ  ๋А๊ปด์ง€๋Š” ์ด์œ ๋Š”, ์–ธ์–ด์˜ ํŠน์„ฑ๊ณผ ์ฒ ํ•™, ์•ˆ์ „์„ฑ๊ณผ ์„ฑ๋Šฅ์„ ๋™์‹œ์— ์ถ”๊ตฌํ•˜๋ ค๋Š” ์„ค๊ณ„ ๋ชฉํ‘œ์—์„œ ๋น„๋กฏ๋œ๋‹ค. Rust๋ฅผ ๋” ํŽธํ•˜๊ฒŒ ์ตํžˆ๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ต์ˆ™ํ•œ ๊ธฐํ˜ธ๋“ค์˜ ์˜๋ฏธ๋ฅผ ์ •ํ™•ํžˆ ํŒŒ์•…ํ•˜๊ณ  ๋‹ค์–‘ํ•œ ์˜ˆ์ œ๋ฅผ ํ†ตํ•ด ํŒจํ„ด์„ ๋ฐ˜๋ณต ํ•™์Šตํ•˜๋Š” ๊ฒƒ์ด ํšจ๊ณผ์ ์ด๋‹ค.

RUST ๊ธฐํ˜ธ์˜ ๋ณต์žก์„ฑ

์ €์ˆ˜์ค€๊ณผ ๊ณ ์ˆ˜์ค€์„ ๋™์‹œ์— ๋‹ค๋ฃจ๋Š” ์–ธ์–ด

Rust๋Š” ์‹œ์Šคํ…œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด๋กœ์„œ C/C++์ฒ˜๋Ÿผ ์ €์ˆ˜์ค€ ์ œ์–ด(ํฌ์ธํ„ฐ, ๋ฉ”๋ชจ๋ฆฌ, lifetimes ๋“ฑ)๋ฅผ ์ œ๊ณตํ•˜๋ฉด์„œ๋„, ๊ณ ์ˆ˜์ค€ ์–ธ์–ด์˜ ์ถ”์ƒํ™”(์ œ๋„ค๋ฆญ, trait, async ๋“ฑ)๋ฅผ ๊ฐ–์ถ”๊ณ  ์žˆ๋‹ค.
๊ทธ๋ž˜์„œ *, &, ->, , 'a, unsafe ๊ฐ™์€ ๊ธฐํ˜ธ์™€ ๊ฐœ๋…์ด ํ•จ๊ป˜ ์กด์žฌํ•œ๋‹ค.

fn foo<'a, T>(x: &'a T) -> &'a T  // lifetime, reference, generic ์ „๋ถ€

์•ˆ์ „์„ฑ (safety)์„ ๊ธฐํ˜ธ๋กœ ํ‘œํ˜„

Rust๋Š” ์ปดํŒŒ์ผ ํƒ€์ž„ ๋ฉ”๋ชจ๋ฆฌ ์•ˆ์ „์„ฑ์„ ์œ„ํ•ด ๊ฐœ๋…์„ ๊ธฐํ˜ธ๋กœ ๋“œ๋Ÿฌ๋‚ด๋Š” ๋ฐฉ์‹์„ ํƒํ–ˆ๋‹ค.

  • & โ†’ ์ฐธ์กฐ
  • &mut โ†’ ๊ฐ€๋ณ€ ์ฐธ์กฐ
  • 'a โ†’ ๋ผ์ดํ”„ํƒ€์ž„
  • ? โ†’ ์—๋Ÿฌ ์ „ํŒŒ
  • ! โ†’ ์ ˆ๋Œ€ ๋ฐ˜ํ™˜๋˜์ง€ ์•Š์Œ (never type)

C๋‚˜ Python์—์„œ๋Š” ์•”๋ฌต์ ์œผ๋กœ ์ฒ˜๋ฆฌ๋˜๋Š” ๊ฐœ๋…๋“ค์ด Rust์—์„œ๋Š” ๋ช…์‹œ์ ์œผ๋กœ ๋“œ๋Ÿฌ๋‚˜๊ธฐ ๋•Œ๋ฌธ์— ๊ธฐํ˜ธ๊ฐ€ ๋” ๋งŽ๊ณ  ๋ˆˆ์— ๋ˆ๋‹ค.

์ถ”๋ก ์— ์˜์กดํ•˜์ง€ ์•Š๊ณ  ๋ช…ํ™•์„ฑ์„ ์ถ”๊ตฌ

Rust๋Š” ๋ช…ํ™•ํ•˜๊ณ  ์˜๋„๋œ ํ‘œํ˜„์„ ์„ ํ˜ธํ•œ๋‹ค. ์ถ”๋ก ๋ณด๋‹ค๋Š” ํƒ€์ž…/๋™์ž‘/์—๋Ÿฌ ๋“ฑ์„ ๋ช…์‹œ์ ์œผ๋กœ ํ‘œํ˜„ํ•ด์•ผ ํ•œ๋‹ค.

let result: Result<i32, String> = some_function()?;  // ?๋กœ ์—๋Ÿฌ ์ „ํŒŒ
let closure = |x: i32| -> i32 { x + 1 };             // -> ๋ฆฌํ„ด ํƒ€์ž…

์ฝ”๋“œ ํ•ด์„์ด ์–ด๋ ต๋”๋ผ๋„, ์‹คํ–‰ ์‹œ ์˜ค๋ฅ˜๋ณด๋‹ค ์ปดํŒŒ์ผ ์‹œ ์˜ค๋ฅ˜๋ฅผ ์„ ํ˜ธํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๋ณต์žกํ•œ ๊ธฐํ˜ธ๋ฅผ ๊ฐ์ˆ˜ํ•œ๋‹ค.

ํ‘œํ˜„๋ ฅ์ด ๋†’์€ ๋ฌธ๋ฒ•

Rust๋Š” ๋‹ค์Œ์„ ๋™์‹œ์— ์ง€์›ํ•œ๋‹ค.

๊ธฐ๋Šฅ์˜ˆ์‹œ
ํŒจํ„ด ๋งค์นญmatch, if let, while let ๋“ฑ ๋‹ค์–‘ํ•œ ํŒจํ„ด ์‚ฌ์šฉ
ํŠธ๋ ˆ์ž‡ ๊ธฐ๋ฐ˜ ์ œ๋„ค๋ฆญ<T: Trait>
๋น„๋™๊ธฐ/๋™์‹œ์„ฑasync/await, .await
์†Œ์œ ๊ถŒ ๋ชจ๋ธ&, &mut, Box<T>, Rc<T>, Arc<T> ๋“ฑ

์ด๋Ÿฐ ํ‘œํ˜„๋“ค์„ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ํ‘œํ˜„ํ•˜๋ ค๋‹ค ๋ณด๋‹ˆ ๋‹ค์–‘ํ•œ ๊ธฐํ˜ธ๊ฐ€ ์ƒ๊ฒผ๋‹ค.

๊ฑฐ์˜ ๋ชจ๋“  ๊ธฐ๋Šฅ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๊ธฐ๋ฐ˜

C++์ด๋‚˜ Java์—์„œ๋Š” ์–ธ์–ด์— ๋‚ด์žฅ๋œ ๊ธฐ๋Šฅ๋„, Rust์—์„œ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๊ธฐ๋ฐ˜์œผ๋กœ ๋™์ž‘ํ•œ๋‹ค. ๊ทธ๋ž˜์„œ ์ ‘๊ทผ ๋ฐฉ์‹๋„ ๋‹ค๋ฅด๋‹ค.

Vec::new()
Option::map()
Result<T, E>::unwrap_or()

๊ฒฝ๋กœ ์—ฐ์‚ฐ์ž :: ๊ฐ™์€ ๊ธฐํ˜ธ ์‚ฌ์šฉ์ด ์žฆ์•„์ง„๋‹ค.

๐Ÿ“ฐ ๋‚ด์šฉ

Rust ๊ธฐํ˜ธ๋“ค

:: (๊ฒฝ๋กœ ์—ฐ์‚ฐ์ž)

๋ชจ๋“ˆ, ํ•จ์ˆ˜, ํƒ€์ž…, ์ƒ์ˆ˜ ๋“ฑ์„ ๊ฒฝ๋กœ๋กœ ์ ‘๊ทผํ•  ๋•Œ ์‚ฌ์šฉ

std::fs::File::open("file.txt")?;
let num = i32::from_str_radix("FF", 16)?;
  • std::fs::File โ†’ File ํƒ€์ž…์„ std::fs์—์„œ ๊ฐ€์ ธ์˜ด
  • i32::from_str_radix โ†’ i32์˜ ์—ฐ๊ด€ ํ•จ์ˆ˜ ํ˜ธ์ถœ

=> (ํŒจํ„ด ๋งค์นญ ๊ฒฐ๊ณผ)

match, if let, for ๋“ฑ์—์„œ ํŒจํ„ด์— ๋งค์นญ๋˜์—ˆ์„ ๋•Œ ์ˆ˜ํ–‰ํ•  ์ž‘์—…์„ ์ง€์ •

match x {
    1 => println!("one"),
    _ => println!("other"),
}

-> (ํ•จ์ˆ˜ ๋ฐ˜ํ™˜ ํƒ€์ž…)

ํ•จ์ˆ˜๋‚˜ ํด๋กœ์ €์˜ ๋ฆฌํ„ด ํƒ€์ž… ๋ช…์‹œ

fn add(a: i32, b: i32) -> i32 {
    a + b
}

? (์—๋Ÿฌ ์ „ํŒŒ ์—ฐ์‚ฐ์ž)

Result๋‚˜ Option์—์„œ ์˜ค๋ฅ˜๋ฅผ ๋งŒ๋‚˜๋ฉด ์ฆ‰์‹œ ๋ฐ˜ํ™˜

let file = File::open("config.txt")?; // ์‹คํŒจํ•˜๋ฉด ํ•จ์ˆ˜๋„ Err๋กœ ๋ฐ˜ํ™˜๋จ

! (๋งคํฌ๋กœ, Never ํƒ€์ž…)

(1) ๋งคํฌ๋กœ ํ˜ธ์ถœ

println!("Hello");
vec![1, 2, 3];

(2) Never ํƒ€์ž… (!)

fn panic_and_die() -> ! {
    panic!("crash");
}

.. (๋ฒ”์œ„, ๊ตฌ์กฐ์ฒด ํ•„๋“œ ์ƒ๋žต)

(1) ๋ฒ”์œ„ ์—ฐ์‚ฐ์ž

for i in 0..5 { }      // 0๋ถ€ํ„ฐ 4๊นŒ์ง€
for i in 0..=5 { }     // 0๋ถ€ํ„ฐ 5๊นŒ์ง€

(2) ๊ตฌ์กฐ์ฒด ํ•„๋“œ ์ƒ๋žต

let p = Point { x: 3, ..other_point };

(์ œ๋„ค๋ฆญ ํƒ€์ž…)

ํƒ€์ž…์„ ์ผ๋ฐ˜ํ™” (ํ•จ์ˆ˜, ๊ตฌ์กฐ์ฒด, ํŠธ๋ ˆ์ž‡ ๋“ฑ์—์„œ)

fn print_all<T: Debug>(v: Vec<T>) {
    println!("{:?}", v);
}

* (ํฌ์ธํ„ฐ ์—ญ์ฐธ์กฐ / ๊ณฑ์…ˆ)

(1) ์—ญ์ฐธ์กฐ

let x = 10;
let p = &x;
let y = *p; // p๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฐ’์„ ์–ป์Œ

(2) ๊ณฑ์…ˆ

let area = width * height;

& (์ฐธ์กฐ, ์ฐธ์กฐ์ž)

(1) ์ฐธ์กฐ ์ƒ์„ฑ

let s = String::from("hello");
let r = &s; // ์ฐธ์กฐ์ž

(2) ํŒจํ„ด ๋งค์นญ ์ฐธ์กฐ

match &x {
    &1 => println!("One"),
    _ => {}
}

as (ํ˜•๋ณ€ํ™˜)

let f = 42 as f64;
let c = b'A' as char;

| (ํด๋กœ์ €, ๋น„ํŠธ ์—ฐ์‚ฐ)

(1) ํด๋กœ์ € ์ธ์ž

let square = |x: i32| x * x;

(2) ๋น„ํŠธ ์—ฐ์‚ฐ

let flags = READ | WRITE;

RUST ๊ธฐํ˜ธ ์š”์•ฝ ํ…Œ์ด๋ธ”

๊ธฐํ˜ธ์šฉ๋„ ์š”์•ฝ
::๊ฒฝ๋กœ ํƒ์ƒ‰ (๋ชจ๋“ˆ, ํ•จ์ˆ˜, ํƒ€์ž… ๋“ฑ)
=>match ๋ถ„๊ธฐ ์กฐ๊ฑด
->ํ•จ์ˆ˜ ๋ฆฌํ„ด ํƒ€์ž…
?์˜ค๋ฅ˜ ์ž๋™ ์ „ํŒŒ
!๋งคํฌ๋กœ ํ˜ธ์ถœ / never ํƒ€์ž…
..๋ฒ”์œ„, ๊ตฌ์กฐ์ฒด ํ•„๋“œ ์ƒ๋žต
<T>์ œ๋„ค๋ฆญ ํƒ€์ž…
*์—ญ์ฐธ์กฐ ๋˜๋Š” ๊ณฑ์…ˆ
&์ฐธ์กฐ ์ƒ์„ฑ / ์ฐธ์กฐ ์ „๋‹ฌ
as๋ช…์‹œ์  ํ˜•๋ณ€ํ™˜
\ํด๋กœ์ € ์ธ์ž / ๋น„ํŠธ or ์—ฐ์‚ฐ์ž

โš ๏ธ ์•Œ๋ ค์ง„ ๋ฌธ์ œ ๋ฐ ํ•ด๊ฒฐ๋ฒ•

ํ˜ผ๋ž€์Šค๋Ÿฌ์šด ์ 

:: vs . vs ->

๊ฐ™์€ ํ•จ์ˆ˜๋ผ๋„ ์œ„์น˜์— ๋”ฐ๋ผ ::/.์ด ๋‹ฌ๋ผ์ง€๊ณ , ์ดˆ์‹ฌ์ž์—๊ฒ ์ง๊ด€์ ์ด์ง€ ์•Š์Œ

  • ::๋Š” ํƒ€์ž…/๋ชจ๋“ˆ ์ ‘๊ทผ

  • .๋Š” ๊ฐ’์˜ ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ

  • ->๋Š” ํ•จ์ˆ˜ ๋ฆฌํ„ด ํƒ€์ž…

  • ์˜ˆ์‹œ:

Vec::new();              // ํƒ€์ž…์—์„œ ์—ฐ๊ด€ ํ•จ์ˆ˜ ํ˜ธ์ถœ
let v = vec![1, 2, 3];
v.iter().map(|x| x + 1); // ๋ฉ”์„œ๋“œ ์ฒด์ด๋‹
fn foo() -> Result<()> { ... } // ํ•จ์ˆ˜ ๋ฐ˜ํ™˜

&, &mut, * โ€” ์ฐธ์กฐ์™€ ์—ญ์ฐธ์กฐ

C/C++์— ์ต์ˆ™ํ•œ ์‚ฌ๋žŒ์€ ๋ฐ›์•„๋“ค์ด๊ธฐ ์‰ฌ์šฐ๋‚˜, Python/Java ๊ฐœ๋ฐœ์ž์—๊ฒŒ๋Š” ๊ฐœ๋…์ ์œผ๋กœ ์–ด๋ ต๊ณ  ๊ธฐํ˜ธ๊ฐ€ ์ง๊ด€์ ์ด์ง€ ์•Š์Œ

  • &T: ์ฐธ์กฐ
  • &mut T: ๊ฐ€๋ณ€ ์ฐธ์กฐ
  • *x: ์—ญ์ฐธ์กฐ
let x = 5;
let r = &x;     // ์ฐธ์กฐ
let y = *r;     // ์—ญ์ฐธ์กฐ

'a โ€” ๋ผ์ดํ”„ํƒ€์ž„ ํ‘œ๊ธฐ

์ดˆ์‹ฌ์ž๋Š” "์ด๊ฑด ๋ญ˜ ์ฐธ์กฐํ•˜๋Š” ๊ธฐํ˜ธ์ธ๊ฐ€?" ํ•˜๋ฉฐ &์™€ ํ˜ผ๋™ํ•œ๋‹ค. ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์ถ”๋ก ์„ ํ•ด์ฃผ์ง€๋งŒ, ๋ช…์‹œ๊ฐ€ ํ•„์š”ํ•  ๋•Œ ํฐ ์ง„์ž…์žฅ๋ฒฝ์ด๋‹ค.

  • 'a, 'static, '_ ๊ฐ™์€ ๋ผ์ดํ”„ํƒ€์ž„ ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” ๋งค์šฐ ์ถ”์ƒ์ ์ด๋ฉฐ ๊ธฐํ˜ธํ™”๋˜์–ด ์žˆ์Œ
  • ์‹ค์ œ๋กœ ๊ฐ’์—๋Š” ์—†๊ณ , ํƒ€์ž…์—๋งŒ ์กด์žฌํ•จ

? โ€” ์—๋Ÿฌ ์ „ํŒŒ ์—ฐ์‚ฐ์ž

์˜๋ฏธ๋Š” ๊ฐ„๋‹จํ•˜์ง€๋งŒ ์ˆจ๊ฒจ์ง„ ๋ฐ˜ํ™˜ ํ๋ฆ„์„ ๋งŒ๋“ค๊ธฐ ๋•Œ๋ฌธ์— ์ดˆ์‹ฌ์ž๊ฐ€ ๋””๋ฒ„๊น…ํ•  ๋•Œ ์–ด๋ ค์›€

  • Result<T, E>์—์„œ๋งŒ ์ž‘๋™ํ•จ
  • Option์—๋„ ์“ธ ์ˆ˜ ์žˆ์ง€๋งŒ ๋ฌธ๋งฅ์ด ๋‹ค๋ฆ„

.. โ€” ๋ฒ”์œ„, ๊ตฌ์กฐ์ฒด ํ•„๋“œ ์ƒ๋žต, ํŒจํ„ด ํ™•์žฅ

ํ•œ ๊ธฐํ˜ธ์— ๋„ˆ๋ฌด ๋งŽ์€ ์˜๋ฏธ๊ฐ€ ์žˆ์–ด์„œ, ์ปจํ…์ŠคํŠธ ์—†์ด ๋ณด๋ฉด ํ—ท๊ฐˆ๋ฆผ

  • ์“ฐ๋Š” ์œ„์น˜๋งˆ๋‹ค ์˜๋ฏธ๊ฐ€ ๋‹ค๋ฆ„
๋ณต์‚ฌ
ํŽธ์ง‘
0..10         // ๋ฒ”์œ„
Point { x, ..p } // ๊ตฌ์กฐ์ฒด ํ•„๋“œ ์ฑ„์šฐ๊ธฐ
match x { 1..=3 => ... } // ํŒจํ„ด ๋งค์นญ

|, => โ€” ํด๋กœ์ € vs match

  • |x| x+1๊ณผ x => y๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋‚˜ ํ•จ์ˆ˜ํ˜• ์–ธ์–ด์—์„œ๋„ ๋น„์Šทํ•˜๊ฒŒ ๋ณด์ด์ง€๋งŒ, Rust์—์„œ๋Š” ์ „ํ˜€ ๋‹ค๋ฆ„
  • |๋Š” ๋น„ํŠธ ์—ฐ์‚ฐ์ž์ด๊ธฐ๋„ ํ•ด์„œ ํ˜ผ๋™
let f = |x| x + 1;      // ํด๋กœ์ €
match x { 1 => "one" }  // ํŒจํ„ด ๋งค์นญ

๐Ÿ› ๏ธ ํ•ด๊ฒฐ๋ฒ•

  • ์ดˆ๊ธฐ์—๋Š” ๊ธฐํ˜ธ๋ณด๋‹ค ํŒจํ„ด ์ค‘์‹ฌ์œผ๋กœ ํ•™์Šต

  • โ†’ ์˜ˆ: match, impl, async ๋ณ„๋กœ ์ž์ฃผ ์“ฐ์ด๋Š” ๊ธฐํ˜ธ ์ •๋ฆฌ

  • ์ปจํ…์ŠคํŠธ๋ฅผ ๊ตฌ๋ถ„ํ•˜๋Š” ํ›ˆ๋ จ

  • โ†’ &x๋Š” ๊ฐ’, &T๋Š” ํƒ€์ž…์—์„œ์˜ ์ฐธ์กฐ

  • โ†’ ::๋Š” ํƒ€์ž…์ด๋‚˜ ์—ฐ๊ด€ ํ•จ์ˆ˜, .๋Š” ์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ

  • IDE(์˜ˆ: rust-analyzer)์˜ ๋„์›€ ์ ๊ทน ํ™œ์šฉ

  • โ†’ ์–ด๋–ค ๊ธฐํ˜ธ๊ฐ€ ์–ด๋–ค ์˜๋ฏธ๋กœ ์‚ฌ์šฉ๋˜์—ˆ๋Š”์ง€ ๋งˆ์šฐ์Šค ์˜ค๋ฒ„๋กœ ํ™•์ธ

์‘์šฉ

  • ๐Ÿ“Œ N/A

0๊ฐœ์˜ ๋Œ“๊ธ€