Rust ํ•™์Šต ๊ฐ€์ด๋“œ

์นดํ…Œ๊ณ ๋ฆฌ๋ณ„๋กœ ์ •๋ฆฌ๋œ Rust ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ฐ€์ด๋“œ

๐Ÿ“– ๊ธฐ์ดˆ ๋ฌธ๋ฒ•

๐Ÿ”‘

์†Œ์œ ๊ถŒ๊ณผ ๋นŒ๋ฆผ โ€” Rust๊ฐ€ GC ์—†์ด ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•

์ปดํŒŒ์ผ ํƒ€์ž„์— ๋ฉ”๋ชจ๋ฆฌ ์•ˆ์ „์„ฑ์„ ๋ณด์žฅํ•˜๋Š” Rust์˜ ํ•ต์‹ฌ ๊ทœ์น™

Rust์˜ ์†Œ์œ ๊ถŒ ์‹œ์Šคํ…œ์€ GC ์—†์ด ๋ฉ”๋ชจ๋ฆฌ ์•ˆ์ „์„ฑ์„ ๋ณด์žฅํ•œ๋‹ค. ๊ฐ’ ํ•˜๋‚˜์— ์†Œ์œ ์ž ํ•˜๋‚˜, ๋นŒ๋ ค์ค„ ๋•Œ๋Š” ์ฝ๊ธฐ ์ „์šฉ ์—ฌ๋Ÿฌ ๊ฐœ ๋˜๋Š” ์“ฐ๊ธฐ ์ „์šฉ ํ•˜๋‚˜๋งŒ ํ—ˆ์šฉ.

โณ

๋ผ์ดํ”„ํƒ€์ž„ โ€” Rust ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์ฐธ์กฐ์˜ ์œ ํšจ ๋ฒ”์œ„๋ฅผ ์ถ”์ ํ•˜๋Š” ๋ฐฉ๋ฒ•

'a๊ฐ€ ๋ญ”์ง€ ํ•œ ๋ฒˆ์— ์ดํ•ดํ•˜๊ธฐ

๋ผ์ดํ”„ํƒ€์ž„์€ ์ฐธ์กฐ๊ฐ€ ์œ ํšจํ•œ ๋ฒ”์œ„๋ฅผ ์ปดํŒŒ์ผ๋Ÿฌ์—๊ฒŒ ์•Œ๋ ค์ฃผ๋Š” ์ฃผ์„์ด๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ์ƒ๋žต(elision) ๊ฐ€๋Šฅํ•˜์ง€๋งŒ, ์—ฌ๋Ÿฌ ์ฐธ์กฐ๊ฐ€ ์–ฝํž ๋•Œ ๋ช…์‹œ์ ์œผ๋กœ ์จ์•ผ ํ•œ๋‹ค.

๐ŸŽฏ

ํŒจํ„ด ๋งค์นญ โ€” match์™€ if let์œผ๋กœ ๋ถ„๊ธฐํ•˜๊ธฐ

switch/case์˜ ์ƒ์œ„ ํ˜ธํ™˜, Rust ์ฝ”๋“œ์˜ ํ•ต์‹ฌ ํ‘œํ˜„ ๋ฐฉ์‹

Rust์˜ match๋Š” ๊ฐ’์„ ๋ถ„ํ•ดํ•˜๋ฉด์„œ ๋™์‹œ์— ๋ถ„๊ธฐํ•œ๋‹ค. ๋ชจ๋“  ๊ฒฝ์šฐ๋ฅผ ๋น ์ง์—†์ด ์ฒ˜๋ฆฌํ•ด์•ผ ํ•˜๋Š”(exhaustive) ์ปดํŒŒ์ผ๋Ÿฌ ๊ฐ•์ œ ๋•๋ถ„์— ๋ˆ„๋ฝ ์—†๋Š” ๋ถ„๊ธฐ๊ฐ€ ๋ณด์žฅ๋œ๋‹ค.

โš ๏ธ

Result์™€ ? ์—ฐ์‚ฐ์ž โ€” Rust์˜ ์—๋Ÿฌ ์ฒ˜๋ฆฌ ํŒจํ„ด

try-catch ์—†์ด ์—๋Ÿฌ๋ฅผ ํƒ€์ž…์œผ๋กœ ๋‹ค๋ฃจ๋Š” ๋ฐฉ๋ฒ•

Rust์—๋Š” ์˜ˆ์™ธ(exception)๊ฐ€ ์—†๋‹ค. ๋Œ€์‹  Result<T, E> ํƒ€์ž…์œผ๋กœ ์„ฑ๊ณต/์‹คํŒจ๋ฅผ ๋ช…์‹œํ•˜๊ณ , ? ์—ฐ์‚ฐ์ž๋กœ ์—๋Ÿฌ๋ฅผ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์ „ํŒŒํ•œ๋‹ค.

๐Ÿงฌ ํƒ€์ž… ์‹œ์Šคํ…œ

๐Ÿงฉ

Trait๊ณผ ์ œ๋„ค๋ฆญ โ€” Rust์˜ ๋‹คํ˜•์„ฑ

์ธํ„ฐํŽ˜์ด์Šค + ์ œ๋„ค๋ฆญ์ด ํ•ฉ์ณ์ง„ Rust์˜ ์ถ”์ƒํ™” ๋„๊ตฌ

Trait์€ Java์˜ ์ธํ„ฐํŽ˜์ด์Šค์™€ ๋น„์Šทํ•˜์ง€๋งŒ ๋” ๊ฐ•๋ ฅํ•˜๋‹ค. ์ œ๋„ค๋ฆญ๊ณผ ๊ฒฐํ•ฉํ•˜๋ฉด ์ปดํŒŒ์ผ ํƒ€์ž„์— ํƒ€์ž…์ด ํ™•์ •๋˜๋Š”(monomorphization) ์ œ๋กœ ์ฝ”์ŠคํŠธ ์ถ”์ƒํ™”๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.

๐Ÿ”€

Enum, Option, Result โ€” Rust์˜ ๋Œ€์ˆ˜์  ๋ฐ์ดํ„ฐ ํƒ€์ž…

null ์—†๋Š” ์„ธ๊ณ„๋ฅผ ๋งŒ๋“œ๋Š” ํƒ€์ž… ์‹œ์Šคํ…œ

Rust์—๋Š” null์ด ์—†๋‹ค. ๋Œ€์‹  Option<T>์ด ๊ฐ’์˜ ๋ถ€์žฌ๋ฅผ, Result<T, E>๊ฐ€ ์—ฐ์‚ฐ์˜ ์‹คํŒจ๋ฅผ ํƒ€์ž…์œผ๋กœ ํ‘œํ˜„ํ•œ๋‹ค. enum์ด ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด์„ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ€๋Šฅํ•œ ์„ค๊ณ„๋‹ค.

๐Ÿ“ฆ

Box, Rc, Arc, RefCell โ€” ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ ๊ฐ€์ด๋“œ

์†Œ์œ ๊ถŒ ๊ทœ์น™์„ ์œ ์—ฐํ•˜๊ฒŒ ์šฐํšŒํ•˜๋Š” ๋„๊ตฌ๋“ค

์†Œ์œ ๊ถŒ ๊ทœ์น™๋งŒ์œผ๋กœ ํ•ด๊ฒฐ ์•ˆ ๋˜๋Š” ํŒจํ„ด(์žฌ๊ท€ ํƒ€์ž…, ๊ณต์œ  ์†Œ์œ ๊ถŒ, ๋‚ด๋ถ€ ๊ฐ€๋ณ€์„ฑ)์ด ์žˆ๋‹ค. ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๊ฐ€ ์ด ๊ฐญ์„ ๋ฉ”์šด๋‹ค.

๐Ÿ”ง ์‹ค์ „ ํŒจํ„ด

๐Ÿ—บ๏ธ

Rust๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ๊ฒƒ๋“ค โ€” ์ดˆ๊ธ‰๋ถ€ํ„ฐ ์ƒ๊ธ‰๊นŒ์ง€ ํ”„๋กœ์ ํŠธ ๋กœ๋“œ๋งต

Hello World ๋‹ค์Œ์— ๋ญ˜ ๋งŒ๋“ค์ง€ ๋ง‰๋ง‰ํ•  ๋•Œ

Rust ๋ฌธ๋ฒ•์„ ๋ฐฐ์› ๋Š”๋ฐ ๋ญ˜ ๋งŒ๋“ค์–ด์•ผ ํ• ์ง€ ๋ชจ๋ฅด๊ฒ ๋‹ค๋ฉด. ๋‚œ์ด๋„๋ณ„๋กœ ์‹ค์ œ๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ํ”„๋กœ์ ํŠธ๋ฅผ ์ •๋ฆฌํ–ˆ๋‹ค. CLI ๋„๊ตฌ๋ถ€ํ„ฐ ์›น ์„œ๋ฒ„, ๊ฒŒ์ž„ ์—”์ง„๊นŒ์ง€.

๐Ÿ’ป

Rust๋กœ CLI ๋„๊ตฌ ๋งŒ๋“ค๊ธฐ

clap + serde๋กœ ๋น ๋ฅด๊ฒŒ ๋งŒ๋“œ๋Š” ์‹ค์ „ ์ปค๋งจ๋“œ๋ผ์ธ ๋„๊ตฌ

Rust๋Š” CLI ๋„๊ตฌ ์ œ์ž‘์— ํŠนํžˆ ๊ฐ•ํ•˜๋‹ค. ์‹ฑ๊ธ€ ๋ฐ”์ด๋„ˆ๋ฆฌ๋กœ ์ปดํŒŒ์ผ๋˜๊ณ , ์‹œ์ž‘ ์‹œ๊ฐ„์ด ๋น ๋ฅด๋ฉฐ, clap/serde ์ƒํƒœ๊ณ„๊ฐ€ ํƒ„ํƒ„ํ•˜๋‹ค.

๐ŸŒ

Rust โ†’ WASM โ€” ๋ธŒ๋ผ์šฐ์ €์—์„œ Rust ๋Œ๋ฆฌ๊ธฐ

wasm-pack + wasm-bindgen์œผ๋กœ JS์—์„œ Rust ํ•จ์ˆ˜ ํ˜ธ์ถœํ•˜๊ธฐ

Rust๋Š” WASM ํƒ€๊ฒŸ์œผ๋กœ ์ปดํŒŒ์ผํ•˜๋ฉด ๋ธŒ๋ผ์šฐ์ €์—์„œ ๋„ค์ดํ‹ฐ๋ธŒ ์†๋„๋กœ ์‹คํ–‰๋œ๋‹ค. wasm-bindgen์ด JS โ†” Rust ๊ฐ„ ํƒ€์ž… ๋ณ€ํ™˜์„ ์ž๋™ ์ฒ˜๋ฆฌํ•œ๋‹ค.

๐Ÿ”—

FFI โ€” Rust์—์„œ C ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ˜ธ์ถœํ•˜๊ธฐ

extern "C", bindgen, unsafe์˜ ์‹ค์ „ ์‚ฌ์šฉ๋ฒ•

Rust๋Š” C ABI์™€ ์ง์ ‘ ํ˜ธํ™˜๋œ๋‹ค. extern "C" ๋ธ”๋ก์œผ๋กœ C ํ•จ์ˆ˜๋ฅผ ์„ ์–ธํ•˜๊ณ  unsafe์—์„œ ํ˜ธ์ถœํ•œ๋‹ค. VOICEVOX Engine์ด Core๋ฅผ ctypes๋กœ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ๋„ ์ด ํŒจํ„ด์˜ ์—ญ๋ฐฉํ–ฅ(Rustโ†’C ABI ๋…ธ์ถœ)์ด๋‹ค.

๐Ÿ’Ž Rubyist๋ฅผ ์œ„ํ•œ Rust

๐Ÿ“Œ

๋ณ€์ˆ˜์™€ ๋ถˆ๋ณ€์„ฑ โ€” Ruby์˜ ์ž์œ ๋กœ์šด ์žฌํ• ๋‹น์ด ์‚ฌ๋ผ์ง„ ์ด์œ 

let, mut, shadowing, const โ€” Ruby ๋ณ€์ˆ˜์™€ 1:1 ๋น„๊ต

Ruby์—์„œ ๋ณ€์ˆ˜๋Š” ์–ธ์ œ๋“  ์žฌํ• ๋‹นํ•  ์ˆ˜ ์žˆ๋‹ค. Rust๋Š” ๊ธฐ๋ณธ์ด ๋ถˆ๋ณ€์ด๋‹ค. mut, shadowing, const์˜ ์ฐจ์ด๋ฅผ Ruby ์ฝ”๋“œ์™€ ๋น„๊ตํ•˜๋ฉฐ ์ •๋ฆฌํ–ˆ๋‹ค.

๐Ÿท๏ธ

ํƒ€์ž… ์‹œ์Šคํ…œ โ€” ๋™์  ํƒ€์ž…์˜ ์ž์œ ๋ฅผ ํฌ๊ธฐํ•˜๋ฉด ์–ป๋Š” ๊ฒƒ

Ruby์˜ duck typing vs Rust์˜ ์ •์  ํƒ€์ž… ์ถ”๋ก 

Ruby๋Š” duck typing์ด๋‹ค. "quack ํ•˜๋ฉด ์˜ค๋ฆฌ." Rust๋Š” ์ปดํŒŒ์ผ ํƒ€์ž„์— ๋ชจ๋“  ํƒ€์ž…์„ ๊ฒฐ์ •ํ•œ๋‹ค. ์ถ”๋ก ์ด ๊ฐ•๋ ฅํ•ด์„œ ๋Œ€๋ถ€๋ถ„ ์ง์ ‘ ์“ธ ํ•„์š”๋Š” ์—†์ง€๋งŒ, ํ•œ ๋ฒˆ ์ •ํ•ด์ง€๋ฉด ์ ˆ๋Œ€ ์•ˆ ๋ฐ”๋€๋‹ค.

๐Ÿ”ง

ํ•จ์ˆ˜์™€ ๋ฉ”์„œ๋“œ โ€” def๊ฐ€ fn์ด ๋˜๋ฉด ๋ญ๊ฐ€ ๋‹ฌ๋ผ์ง€๋Š”๊ฐ€

๋ฐ˜ํ™˜ ํƒ€์ž…, ์„ธ๋ฏธ์ฝœ๋ก , ๊ทธ๋ฆฌ๊ณ  Ruby์™€ ๊ฐ™์€ "๋งˆ์ง€๋ง‰ ์‹์ด ๋ฐ˜ํ™˜๊ฐ’" ๊ทœ์น™

Ruby์˜ def โ†’ Rust์˜ fn. ์ธ์ž ํƒ€์ž…๊ณผ ๋ฐ˜ํ™˜ ํƒ€์ž…์„ ๋ช…์‹œํ•ด์•ผ ํ•˜๊ณ , ์„ธ๋ฏธ์ฝœ๋ก  ํ•˜๋‚˜๋กœ ๋ฐ˜ํ™˜๊ฐ’ ์—ฌ๋ถ€๊ฐ€ ๊ฒฐ์ •๋œ๋‹ค. ๊ทธ ์™ธ์—๋Š” Ruby์™€ ์ƒ๊ฐ๋ณด๋‹ค ๋น„์Šทํ•˜๋‹ค.

๐Ÿ—๏ธ

๊ตฌ์กฐ์ฒด์™€ impl โ€” Ruby์˜ class๊ฐ€ Rust์—์„œ ๋‘ ์กฐ๊ฐ์œผ๋กœ ๋‚˜๋‰œ๋‹ค

struct๋กœ ๋ฐ์ดํ„ฐ, impl๋กœ ๋ฉ”์„œ๋“œ, trait๋กœ ๋‹คํ˜•์„ฑ

Ruby์˜ class๋Š” ๋ฐ์ดํ„ฐ์™€ ๋ฉ”์„œ๋“œ๋ฅผ ํ•œ ๊ณณ์— ๋ฌถ๋Š”๋‹ค. Rust๋Š” struct(๋ฐ์ดํ„ฐ)๊ณผ impl(๋ฉ”์„œ๋“œ)๋กœ ๋ถ„๋ฆฌํ•˜๊ณ , ์ƒ์† ๋Œ€์‹  trait์œผ๋กœ ๊ณตํ†ต ํ–‰์œ„๋ฅผ ์ •์˜ํ•œ๋‹ค.

๐ŸŽฏ

Enum๊ณผ ํŒจํ„ด ๋งค์นญ โ€” Symbol๊ณผ case/when์˜ ๊ฐ•๋ ฅํ•œ ์ง„ํ™”ํŒ

Rust์˜ enum์€ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด์„ ์ˆ˜ ์žˆ๋‹ค โ€” Ruby์—๋Š” ์—†๋Š” ๊ฐœ๋…

Ruby์˜ Symbol์ด๋‚˜ ์ƒ์ˆ˜ ๊ทธ๋ฃน์— ํ•ด๋‹นํ•˜๋Š” Rust์˜ enum์€ ๊ฐ ๋ณ€ํ˜•(variant)์— ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด์„ ์ˆ˜ ์žˆ๋‹ค. match๋Š” case/when์˜ ๊ฐ•ํ™”ํŒ์ธ๋ฐ, ๋ชจ๋“  ์ผ€์ด์Šค๋ฅผ ๋น ์ง์—†์ด ์ฒ˜๋ฆฌํ•ด์•ผ ํ•œ๋‹ค.

โ“

Option<T> โ€” nil์ด ์‚ฌ๋ผ์ง„ ์„ธ๊ณ„์—์„œ ์‚ด์•„๋‚จ๊ธฐ

Ruby์˜ nil๊ณผ &. ์—ฐ์‚ฐ์ž๊ฐ€ Rust์—์„œ๋Š” ์–ด๋–ป๊ฒŒ ๋ฐ”๋€Œ๋Š”๊ฐ€

Ruby์˜ nil์€ ์–ด๋””์„œ๋“  ํŠ€์–ด๋‚˜์˜จ๋‹ค. Rust์—๋Š” nil์ด ์—†๋‹ค. ๊ฐ’์ด ์—†์„ ์ˆ˜ ์žˆ์œผ๋ฉด Option<T>์„ ์จ์•ผ ํ•˜๊ณ , ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ None ์ฒ˜๋ฆฌ๋ฅผ ๊ฐ•์ œํ•œ๋‹ค.

โš ๏ธ

Result์™€ ์—๋Ÿฌ ์ฒ˜๋ฆฌ โ€” begin/rescue๊ฐ€ ์‚ฌ๋ผ์ง„ ์ž๋ฆฌ

์˜ˆ์™ธ ๋Œ€์‹  ๋ฐ˜ํ™˜๊ฐ’์œผ๋กœ ์—๋Ÿฌ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” Rust์˜ ๋ฐฉ์‹

Ruby๋Š” ์˜ˆ์™ธ๋ฅผ ๋˜์ง€๊ณ  rescue๋กœ ์žก๋Š”๋‹ค. Rust๋Š” ์˜ˆ์™ธ๊ฐ€ ์—†๋‹ค. ๋Œ€์‹  Result<T, E>๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ , ? ์—ฐ์‚ฐ์ž๋กœ ์—๋Ÿฌ๋ฅผ ์ „ํŒŒํ•œ๋‹ค.

๐Ÿ”„

์ดํ„ฐ๋ ˆ์ดํ„ฐ์™€ ํด๋กœ์ € โ€” Rubyist๊ฐ€ ๊ฐ€์žฅ ํŽธํ•˜๊ฒŒ ๋А๋ผ๋Š” ์˜์—ญ

select/map/reduce๊ฐ€ filter/map/fold๋กœ ๋ฐ”๋€Œ์—ˆ์„ ๋ฟ

Ruby์˜ Enumerable ๋ฉ”์„œ๋“œ๊ฐ€ ๊ฑฐ์˜ ๊ทธ๋Œ€๋กœ Rust์— ์žˆ๋‹ค. ์ด๋ฆ„๋งŒ ์•ฝ๊ฐ„ ๋‹ค๋ฅด๊ณ  ์ฒด์ด๋‹ ํŒจํ„ด๋„ ๊ฐ™๋‹ค. Rubyist๊ฐ€ Rust์—์„œ ๊ฐ€์žฅ ๋น ๋ฅด๊ฒŒ ์ ์‘ํ•˜๋Š” ๋ถ€๋ถ„.

๐Ÿ“

String vs &str โ€” Ruby์—๋Š” ์—†๋Š” ๋ฌธ์ž์—ด์˜ ๋‘ ์–ผ๊ตด

์†Œ์œ ํ•˜๋Š” ๋ฌธ์ž์—ด๊ณผ ๋นŒ๋ฆฌ๋Š” ๋ฌธ์ž์—ด์˜ ์ฐจ์ด

Ruby์—์„œ ๋ฌธ์ž์—ด์€ String ํ•˜๋‚˜๋‹ค. Rust์—๋Š” String(์†Œ์œ )๊ณผ &str(๋นŒ๋ฆผ) ๋‘ ์ข…๋ฅ˜๊ฐ€ ์žˆ๋‹ค. ์ฒ˜์Œ์— ํ˜ผ๋ž€์Šค๋Ÿฝ์ง€๋งŒ, ์†Œ์œ ๊ถŒ ๊ฐœ๋…๊ณผ ์—ฐ๊ฒฐ๋˜๋Š” ํ•ต์‹ฌ.

๐Ÿ“ฆ

์ปฌ๋ ‰์…˜ โ€” Array์™€ Hash๊ฐ€ Vec๊ณผ HashMap์ด ๋˜๋ฉด

ํƒ€์ž…์ด ๊ณ ์ •๋œ ์„ธ๊ณ„์˜ ๋ฐฐ์—ด๊ณผ ํ•ด์‹œ๋งต

Ruby์˜ Array์™€ Hash๊ฐ€ Rust์—์„œ๋Š” Vec<T>์™€ HashMap<K, V>์ด ๋œ๋‹ค. ๊ฐ€์žฅ ํฐ ์ฐจ์ด๋Š” ํ•œ ๊ฐ€์ง€ ํƒ€์ž…๋งŒ ๋‹ด์„ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ.

๐Ÿ—๏ธ

์†Œ์œ ๊ถŒ โ€” Ruby์˜ GC๊ฐ€ ํ•ด์ฃผ๋˜ ์ผ์„ ์ง์ ‘ ํ•˜๊ธฐ

Rubyist๊ฐ€ ๊ฐ€์žฅ ์–ด๋ ค์›Œํ•˜๋Š” Rust์˜ ํ•ต์‹ฌ ๊ฐœ๋…

Ruby์—์„œ๋Š” GC๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์•Œ์•„์„œ ์ •๋ฆฌํ•œ๋‹ค. Rust์—์„œ๋Š” ์†Œ์œ ๊ถŒ ๊ทœ์น™์ด GC๋ฅผ ๋Œ€์ฒดํ•œ๋‹ค. ๊ฐ’์„ ๋„˜๊ธฐ๋ฉด ์›๋ณธ์ด ์‚ฌ๋ผ์ง€๋Š” move ๊ฐœ๋…์ด ํ•ต์‹ฌ์ด๋‹ค.

๐Ÿ“ฆ

Cargo โ€” Bundler + Rake๊ฐ€ ํ•˜๋‚˜๋กœ ํ•ฉ์ณ์ง„ ๊ฒƒ

Gemfile โ†’ Cargo.toml, bundle exec โ†’ cargo run

Ruby ์ƒํƒœ๊ณ„์—์„œ Bundler(์˜์กด์„ฑ)์™€ Rake(๋นŒ๋“œ/ํƒœ์Šคํฌ)๋ฅผ ๋”ฐ๋กœ ์“ฐ์ง€๋งŒ, Rust๋Š” Cargo ํ•˜๋‚˜๋กœ ์ „๋ถ€ ํ•œ๋‹ค. ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ, ๋นŒ๋“œ, ํ…Œ์ŠคํŠธ, ์˜์กด์„ฑ ๊ด€๋ฆฌ, ๋ฐฐํฌ๊นŒ์ง€.