โ† Articles

๐Ÿฆ€ ๋Ÿฌ์ŠคํŠธ์˜ ๋ฉ‹์ง์„ ๋ชจ๋ฅด๋Š” ๋‹น์‹ ์€ ๋ถˆ์Œํ•ด์š”

๋†’์€ ์„ฑ๋Šฅ๊ณผ ์‹ ๋ขฐ๋ฅผ ํ™•๋ณดํ•˜๊ธฐ ์œ„ํ•œ ์–ธ์–ด

Table of Contents

๋‚ด๊ฐ€ ๋งŒ๋‚˜์˜จ ๊ฐœ๋ฐœ์ž๋“ค์€ ๋Œ€์ฒด๋กœ ์ž์‹ ์ด ์‚ฌ์šฉํ•˜๋Š” ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์— ๋”ฑํžˆ ๋งŒ์กฑํ•˜์ง€ ์•Š์•˜๋Š”๋ฐ (๊ทน๋‹จ์ ์œผ๋กœ๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์™€ PHP๊ฐ€ ์žˆ๋‹ค.) ์œ ๋… ๋Ÿฌ์ŠคํŠธ ๊ฐœ๋ฐœ์ž๋“ค์€ ์ ๊ทน์ ์œผ๋กœ ๋Ÿฌ์ŠคํŠธ๋ฅผ ์ถ”์ฒœํ–ˆ๋‹ค.

ํ•˜์ง€๋งŒ ๊ทธ๋ƒฅ ๊ทธ๋Ÿฐ ์–ธ์–ด๊ฐ€ ์žˆ๊ตฌ๋‚˜ ์ •๋„๋กœ ์ƒ๊ฐํ•˜๊ณ  ์žˆ์—ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ๋Ÿฌ์ŠคํŠธ 2018 ์—๋””์…˜ ๋ฐœํ‘œ ์ดํ›„ ๊ทผ 1๋…„๊ฐ„ ๋Ÿฌ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์›น์–ด์…ˆ๋ธ”๋ฆฌ๋กœ ์ปดํŒŒ์ผํ•  ์ˆ˜ ์žˆ๋‹ค๋“ ์ง€, deno์˜ ์ฝ”์–ด๊ฐ€ ๋Ÿฌ์ŠคํŠธ๋กœ ์ž‘์„ฑ๋๋‹ค๋“ ์ง€ํ•˜๋Š” ์ด์•ผ๊ธฐ๋“ค์ด ๋‰ด์Šคํ”ผ๋“œ๋ฅผ ๊ฐ€๋“ ์ฑ„์› ๋‹ค. ์‹ฌ์ง€์–ด ์Šคํ”„๋ฆฐํŠธ ์„œ์šธ 6์›” ๋ชจ์ž„์—์„œ RustPython์˜ ์ธ๊ธฐ๋ฅผ ๋ณธ ๋’ค๋กœ๋Š” ๋Ÿฌ์ŠคํŠธ๊ฐ€ ๋งˆ์น˜ ํ”ผํ•  ์ˆ˜ ์—†๋Š” ์‹œ๋Œ€์˜ ํ๋ฆ„์ฒ˜๋Ÿผ ๋Š๊ปด์กŒ๋‹ค.

๋ฌด์—‡๋ณด๋‹ค ๋Ÿฌ์ŠคํŠธ ์ปค๋ฎค๋‹ˆํ‹ฐ์˜ ๋น„๊ณต์‹ ๋งˆ์Šค์ฝ”ํŠธ์ธ Ferris๊ฐ€ ๊ท€์—ฌ์›Œ์„œ ๋ฐ˜์€ ๋จน๊ณ  ๋“ค์–ด๊ฐ„๋‹ค.[1] ๋Ÿฌ์ŠคํŠธ ์‚ฌ์šฉ์ž๋Š” ๊ฐ‘๊ฐ๋ฅ˜๋ฅผ ๋œปํ•˜๋Š” 'Crustaceanโ€™์—์„œ ๋”ฐ์™€ 'Rustanceanโ€™์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค. (ํ•œ๊ตญ์—์„œ๋Š” '๋Ÿฌ์Šคํ† ๋ž‘์Šคโ€™๊ฐ€ ๋งŽ์ด ์“ฐ์ด๋Š”๋ฐ ๋” ์ ์ ˆํ•œ ๊ฒƒ ๊ฐ™๊ธฐ๋„ ํ•˜๋‹คโ€ฆ) ์ฐธ๊ณ ๋กœ Ferris๋ฅผ ๋ถ€๋ฅผ ๋•Œ๋Š” ์  ๋” ์ค‘๋ฆฝ์ ์ธ "they/them"์„ ์‚ฌ์šฉํ•œ๋‹ค.[2] ์ด๊ฒƒ๋งˆ์ € ๋ฉ‹์ง€๋‹ค.

๋Ÿฌ์ŠคํŠธ๋Š” ์‹ ์ƒ ์–ธ์–ด์ธ ๋งŒํผ ์—…๋ฐ์ดํŠธ๋ฅผ ๊ฑฐ์น˜๋ฉฐ ํฌ๊ฒŒ ๋ณ€ํ™”ํ•ด์™”๋‹ค. ๊ฐ์ข… ๋ธ”๋กœ๊ทธ๋‚˜ ์Šคํƒ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ ๋“ฑ, ์›น์ƒ์˜ ๋งŽ์€ ์ž๋ฃŒ๋“ค์ด ์ด์   ์œ ํšจํ•˜์ง€ ์•Š๋‹ค. ๊ทธ๋ž˜์„œ ์‹œ๊ฐ„์ด ์ง€๋‚˜๋„ ์•„๋งˆ ํฌ๊ฒŒ ๋ฐ”๋€Œ์ง€ ์•Š์„ ๊ฒƒ ๊ฐ™์€ ๋ฌธ๋ฒ•์  ํŠน์ง•๊ณผ ๋Ÿฌ์ŠคํŠธ์˜ ์ฃผ์š” ์ปจ์…‰์ธ ์˜ค๋„ˆ์‹ญ(Ownership)์„ ์ค‘์‹ฌ์œผ๋กœ ๋Ÿฌ์ŠคํŠธ์˜ ์•ˆ์ „์„ฑ์„ ๊ฐ•์กฐํ•ด๋ณด๋ ค ํ•œ๋‹ค.

๊ธ‰์„ฑ์žฅํ•˜๋Š” ์–ธ์–ด

๋Ÿฌ์ŠคํŠธ๋Š” 2006๋…„ ๋ชจ์งˆ๋ผ์˜ ๊ฐœ๋ฐœ์ž ๊ทธ๋ ˆ์ด๋˜ ํ˜ธ์–ด(Graydon Hoare)์˜ ์‚ฌ์ด๋“œ ํ”„๋กœ์ ํŠธ์—์„œ ์ถœ๋ฐœํ–ˆ๋‹ค. ์ดํ›„ ๋ชจ์งˆ๋ผ๊ฐ€ ๊ณต์‹์ ์œผ๋กœ ๋Ÿฌ์ŠคํŠธ๋ฅผ ํ›„์›ํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ๊ณ , 2015๋…„ 1.0 ๋ฒ„์ „์„ ๋ฆด๋ฆฌ์ฆˆํ–ˆ๋‹ค. ๋ชจ์งˆ๋ผ์˜ ์ •์ฑ…์— ๋”ฐ๋ผ ๋Ÿฌ์ŠคํŠธ๋Š” ์˜คํ”ˆ์†Œ์Šค ํ”„๋กœ์ ํŠธ๋กœ ์ง„ํ–‰๋œ๋‹ค. ์ฝ”์–ด ํŒ€์ด ์ „์ฒด์ ์ธ ๋ฐฉํ–ฅ์„ ๋ฆฌ๋“œํ•˜์ง€๋งŒ ๋ˆ„๊ตฌ๋‚˜ ๋Ÿฌ์ŠคํŠธ ๊ฐœ๋ฐœ์— ๊ธฐ์—ฌํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๊ณ  ์žˆ์œผ๋ฉฐ, RFC(Request For Comments) ๋ฌธ์„œ์™€ ๋Ÿฌ์ŠคํŠธ ์ €์žฅ์†Œ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

๋Ÿฌ์ŠคํŠธ๋Š” ๊ณต๊ฐœ ์ดํ›„ ๊พธ์ค€ํžˆ ๋†’์€ ์ธ๊ธฐ๋ฅผ ์–ป์–ด์™”๋‹ค. ์Šคํƒ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ ์„œ๋ฒ ์ด์—์„œ ๋งค๋…„ ์‚ฌ๋ž‘๋ฐ›๋Š” ์–ธ์–ด 1์œ„๋ฅผ ์ฐจ์ง€ํ•˜๊ณ  ์žˆ๊ณ , 2019๋…„ ๊ธฐ์ค€ ๊นƒํ—ˆ๋ธŒ์—์„œ์˜ ๋Ÿฌ์ŠคํŠธ ์‚ฌ์šฉ๋ฅ ์€ 2018๋…„ ๋Œ€๋น„ 235% ์ฆ๊ฐ€ํ–ˆ๋‹ค.[3] ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋งŽ์€ ๊ธฐ์—…๋“ค์ด ํ”„๋กœ๋•์…˜์—๋„ ๋Ÿฌ์ŠคํŠธ๋ฅผ ์ ์šฉํ•˜๊ณ  ์žˆ๋‹ค. ๋ชจ์งˆ๋ผ์˜ ๋ธŒ๋ผ์šฐ์ € ์—”์ง„ ํ”„๋กœ์ ํŠธ ์„œ๋ณด๊ฐ€ ๋Ÿฌ์ŠคํŠธ๋กœ ์ž‘์„ฑ๋˜์—ˆ๊ณ , ํŽ˜์ด์Šค๋ถ์˜ ์•”ํ˜ธํ™”ํ ๋ฆฌ๋ธŒ๋ผ์˜ ์ฝ”์–ด๋„ ๋Ÿฌ์ŠคํŠธ๋กœ ๊ตฌํ˜„๋˜์—ˆ๋‹ค. ๊ตญ๋‚ด์—์„œ๋Š” ์Šคํฌ์นด๊ฐ€ POS ํ†ตํ•ฉ SDK์— ๋Ÿฌ์ŠคํŠธ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.[4]

์‹ฌํ”Œํ•œ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ

๋Ÿฌ์ŠคํŠธ๋ฅผ ์ฒ˜์Œ ์‹œ์ž‘ํ•  ๋•Œ ๋Š๋‚€ ์ฒซ ๋ฒˆ์งธ ์žฅ์ ์€ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์ด ๋‹จ์ˆœํ•˜๋‹ค๋Š” ๊ฒƒ์ด์—ˆ๋‹ค. ๋จผ์ € ๋Ÿฌ์ŠคํŠธ ํˆด์ฒด์ธ ์ธ์Šคํ†จ๋Ÿฌ rustup์„ ๋‹ค์šด๋กœ๋“œํ•œ๋‹ค.

$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

rustup์€ ๋Ÿฌ์ŠคํŠธ ์ปดํŒŒ์ผ๋Ÿฌ์ธ rustc์™€ ํŒจํ‚ค์ง€ ๋งค๋‹ˆ์ €์ธ ์นด๊ณ (Cargo)๋ฅผ ์„ค์น˜ํ•œ๋‹ค. ๋Ÿฌ์ŠคํŠธ ๊ฐœ๋ฐœ์€ ๋นŒ๋“œ, ํ…Œ์ŠคํŠธ, ๋ฌธ์„œํ™”, ๋ฐฐํฌ ๋ชจ๋“  ๊ฒƒ์„ ์นด๊ณ ๋กœ ์ปค๋ฒ„ํ•  ์ˆ˜ ์žˆ๋‹ค. cargo new ๋ช…๋ น์œผ๋กœ ์ƒˆ ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ํ”„๋กœ์ ํŠธ ๋””๋ ‰ํ† ๋ฆฌ์˜ Cargo.toml ํŒŒ์ผ์— ๋””ํŽœ๋˜์‹œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ํฌ๋ ˆ์ดํŠธ(Crate)๋ผ๊ณ  ๋ถ€๋ฅด๋Š” ์™ธ๋ถ€ ํŒจํ‚ค์ง€๋ฅผ ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ๋˜ํ•œ cargo build ๋ช…๋ น์œผ๋กœ ํ”„๋กœ์ ํŠธ๋ฅผ ๋นŒ๋“œํ•˜๋ฉฐ, cargo run ๋ช…๋ น์œผ๋กœ ์ปดํŒŒ์ผ, ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

$ cargo new hello_world --bin
$ cd hello_world
$ cargo build
$ cargo run

๋Ÿฌ์ŠคํŠธ์˜ ํ‘œ์ค€ ์Šคํƒ€์ผ ๊ฐ€์ด๋“œ๋ฅผ ๋”ฐ๋ฅด๋Š” ํฌ๋งคํ„ฐ rustfmt, ์ฝ”๋“œ ์ƒ์˜ ์‹ค์ˆ˜์™€ ๊ฐœ์„ ์ ์„ ์ œ์•ˆํ•ด์ฃผ๋Š” ๋ฆฐํ„ฐ clippy์™€ ๊ฐ™์€ ๋„๊ตฌ๋„ rustup์„ ์ด์šฉํ•˜๋ฉด ์‰ฝ๊ฒŒ ํˆด์ฒด์ธ์— ์ถ”๊ฐ€ํ•ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ธฐ๋ณธ์ ์ธ ์ปดํฌ๋„ŒํŠธ๋“ค์€ ๋ฏธ๋ฆฌ ์„ค์น˜ํ•ด๋‘๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

$ rustup update
$ rustup component add rustfmt clippy rls rust-analysis rust-src

๋žญ๊ท€์ง€ ์„œ๋ฒ„๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์–ด๋–ค ๋„๊ตฌ๋ฅผ ์“ฐ๋“  ๋†’์€ ์ˆ˜์ค€์˜ ์‹ฌ๋ณผ ํƒ์ƒ‰, ํฌ๋งคํŒ…, ์ž๋™์™„์„ฑ ๋“ฑ์˜ ๊ฐœ๋ฐœํ™˜๊ฒฝ์„ ๋ณด์žฅ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค. IntelliJ, VSCode ๋“ฑ IDE๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์„ค์น˜ํ•ด ๊ฐœ๋ฐœ์„ ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, Rust Playground์—์„œ ๋Ÿฌ์ŠคํŠธ๋ฅผ ์„ค์น˜ํ•˜์ง€ ์•Š๊ณ  ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ด๋ณผ ์ˆ˜๋„ ์žˆ๋‹ค.

์•ˆ์ „ํ•œ ๋ฌธ๋ฒ•

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋‚˜ ํŒŒ์ด์ฌ๊ณผ ๊ฐ™์€ ์–ธ์–ด์— ๋น„ํ•˜๋ฉด ๋Ÿฌ์ŠคํŠธ์˜ ๋ฌธ๋ฒ•์€ ๊ต‰์žฅํžˆ ์—„๊ฒฉํ•˜๋‹ค. ๊ฐ„๋‹จํ•œ ์˜ˆ์‹œ๋ฅผ ๋ณด์ž.

fn main() {
    let x: i8 = 10;
    let y: i8 = 20;

    println!("{}", x + y); // "30"
}

๋Ÿฌ์ŠคํŠธ ํ”„๋กœ๊ทธ๋žจ์˜ ์—”ํŠธ๋ฆฌ ํฌ์ธํŠธ๋Š” main ํ•จ์ˆ˜๋‹ค. ๋ณ€์ˆ˜๋Š” let ํ‚ค์›Œ๋“œ๋กœ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๋ ‡๊ฒŒ ์„ ์–ธ๋œ ๋ณ€์ˆ˜๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ถˆ๋ณ€(Immutable)ํ•˜์—ฌ ๊ฐ’์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋‹ค. ๊ฐ€๋ณ€์ ์ธ(Mutable) ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•˜๋ ค๋ฉด mut ํ‚ค์›Œ๋“œ๋ฅผ ๋ช…์‹œํ•ด์•ผ ํ•œ๋‹ค.

fn main() {
    let mut x: i8 = 10;
    x = x + 20; // 30

    println!("{}", x); // "30"
}

const ํ‚ค์›Œ๋“œ๋กœ ์ƒ์ˆ˜๋ฅผ ์„ ์–ธํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ๋ถˆ๋ณ€ ๋ณ€์ˆ˜์™€ ๋‹ค๋ฅด๊ฒŒ ์ƒ์ˆ˜๋Š” ์ƒ์ˆ˜ ํ‘œํ˜„์‹์œผ๋กœ๋งŒ ์ดˆ๊ธฐํ™”ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ํ•จ์ˆ˜์˜ ๊ฒฐ๊ณผ ๋“ฑ ๋Ÿฐํƒ€์ž„์— ๊ณ„์‚ฐ๋˜๋Š” ๊ฐ’์œผ๋กœ ์ดˆ๊ธฐํ™” ํ•  ์ˆ˜ ์—†๋‹ค.

์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด ์•Œ ์ˆ˜ ์žˆ์ง€๋งŒ, ๋Ÿฌ์ŠคํŠธ๋Š” ์ •์  ํƒ€์ž… ์–ธ์–ด๋‹ค. ์„ ์–ธ ์‹œ์— ๊ฐ’์„ ํ• ๋‹นํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ ํƒ€์ž…์„ ๋ช…์‹œํ•ด์•ผ ํ•œ๋‹ค. i8, i32๋Š” 8๋น„ํŠธ, 32๋น„ํŠธ ์ •์ˆ˜ ํƒ€์ž…์„ ์˜๋ฏธํ•œ๋‹ค. f32๋Š” 32๋น„ํŠธ ๋ถ€๋™์†Œ์ˆ˜์  ํƒ€์ž…, bool์€ ๋ถˆ๋ฆฌ์–ธ ํƒ€์ž…์„ ๋œปํ•œ๋‹ค. ๊ทธ ์™ธ ํŠœํ”Œ(let x: (i32, f64) = (10, 3.14))๊ณผ ๋ฐฐ์—ด(let x = [1, 2, 3])๋„ ์ง€์›ํ•œ๋‹ค.

๋Ÿฌ์ŠคํŠธ์—์„œ ๊ตฌ๋ฌธ(Statement)์€ ํŠน์ • ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•˜์ง€๋งŒ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š๋Š” ๋ช…๋ น์„ ๋งํ•œ๋‹ค. ํ•œํŽธ ํ‘œํ˜„์‹(Expression)์€ ๊ฒฐ๊ณผ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ช…๋ น์„ ๋งํ•œ๋‹ค. ๊ตฌ๋ฌธ ๋ธ”๋ก์˜ ๊ฐ’์€ ๋ธ”๋ก ๋‚ด์˜ ๋งˆ์ง€๋ง‰ ํ‘œํ˜„์‹์œผ๋กœ ๊ฒฐ์ •๋œ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ํ•จ์ˆ˜ ์ •์˜๋„ ํ•˜๋‚˜์˜ ๊ตฌ๋ฌธ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋งˆ์ง€๋ง‰ ํ‘œํ˜„์‹์ด ํ•จ์ˆ˜์˜ ๋ฐ˜ํ™˜๊ฐ’์ด ๋œ๋‹ค.

fn square(x: i32) -> i32 {
    x * x
}

๋ณ€์ˆ˜ ์„ ์–ธ๋„ ๊ตฌ๋ฌธ์ด๋‹ค. ๋”ฐ๋ผ์„œ ์šฐ๋ณ€์— ํ‘œํ˜„์‹์„ ๋„ฃ์„ ์ˆ˜ ์žˆ๋‹ค:

let x = 1;
let y = {
    let x = 2;
    x + 1
};

x + 1 ๋’ค์— ์„ธ๋ฏธ์ฝœ๋ก ์ด ๋ถ™์ง€ ์•Š์€ ์ด์œ ๋Š” ์ด๊ฒƒ์ด ํ‘œํ˜„์‹์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์„ธ๋ฏธ์ฝœ๋ก ์„ ๋ถ™์ด๋ฉด ๊ตฌ๋ฌธ์ด ๋œ๋‹ค. ๊ฐ™์€ ์›๋ฆฌ๋กœ ์•„๋ž˜์™€ ๊ฐ™์€ ๋ฌธ๋ฒ•๋„ ํ—ˆ์šฉ๋œ๋‹ค:

let y = if x == 1 {
        10
    } else if x > 1 {
        20
    } else {
        30
    };

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋กœ ๊ฐ™์€ ํ‘œํ˜„์„ ํ•˜๋ ค๋ฉด ๊ฐ€๋ณ€ ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•ด์•ผ ํ•œ๋‹ค. ์•„๋‹ˆ๋ฉด ์ค‘์ฒฉ ์‚ผํ•ญ ์กฐ๊ฑด ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š”๋ฐ, ๊ถŒ์žฅ๋˜๋Š” ํŒจํ„ด์€ ์•„๋‹ˆ๋‹ค.

let y = 0;
if (x === 1) {
  y = 10;
} else if (x > 1) {
  y = 20;
} else {
  y = 30
}

ํƒ€ ์–ธ์–ด์˜ switch์™€ ๋น„์Šทํ•œ match๋ผ๋Š” ์ปจํŠธ๋กค ํ”Œ๋กœ์šฐ ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

match x {
    1 => println!("one"),
    3 => println!("three"),
    5 => println!("five"),
    _ => (),
}

๋Ÿฌ์ŠคํŠธ ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ๋ฌธ๋ฒ•์ด ์กฐ๊ธˆ์ด๋ผ๋„ ์ž˜๋ชป๋˜๋ฉด ์—๋Ÿฌ๋ฅผ ๋‚ธ๋‹ค. ์ด๋Ÿฌํ•œ ์—„๊ฒฉํ•จ์ด ๋Ÿฌ์ŠคํŠธ์˜ ๋Ÿฌ๋‹ ์ปค๋ธŒ๋ฅผ ๋†’์ด๊ธฐ๋„ ํ•˜์ง€๋งŒ, ๋™์‹œ์— ํ‘๋งˆ๋ฒ•์„ ์“ฐ๊ณ  ์‹ถ์€ ํ”„๋กœ๊ทธ๋ž˜๋จธ์˜ ํญ์ฃผ๋ฅผ ๋ง‰๋Š” ์—ญํ• ๋„ ํ•œ๋‹ค. ๋˜ํ•œ ๋Ÿฌ์ŠคํŠธ์— ์ต์ˆ™ํ•˜์ง€ ์•Š์€ ์‚ฌ๋žŒ๋„ ์ปดํŒŒ์ผ๋Ÿฌ ๋ง์„ ์ž˜ ๋“ฃ๋‹ค๋ณด๋ฉด ๊ธฐ๋ณธ์€ ๋˜์–ด ์žˆ๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“ค์–ด์ค€๋‹ค. ๋‹คํ–‰ํžˆ ๋Ÿฌ์ŠคํŠธ ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ์•„์ฃผ ์นœ์ ˆํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ปดํŒŒ์ผ์— ์‹คํŒจํ•˜๋ฉด ์–ด๋Š ๋ถ€๋ถ„์ด ์™œ ์ž˜๋ชป๋๊ณ , ์–ด๋–ป๊ฒŒ ๊ณ ์ณ์•ผํ•˜๋Š”์ง€ ์•Œ๋ ค์ฃผ๋‹ˆ๊นŒ ๊ฒ๋จน์„ ํ•„์š”๋Š” ์—†๋‹ค.

์•ˆ์ „ํ•œ Nullable

๋Œ€๋ถ€๋ถ„์˜ ์–ธ์–ด์—์„œ null๊ฐ’์„ non-null๊ฐ’์œผ๋กœ ์‚ฌ์šฉํ•˜๋ ค ํ•  ๋•Œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. ๋Ÿฌ์ŠคํŠธ์—๋Š” null์ด ์—†๋‹ค. ๋Œ€์‹  ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์ œ๊ณตํ•˜๋Š” Option ์—ด๊ฑฐํ˜•์˜ ๋ฉค๋ฒ„๋กœ None๊ณผ Some์ด ์žˆ๋‹ค.

enum Option<T> {
    Some(T),
    None,
}

Option ํƒ€์ž…์€ ์–ด๋–ค ๊ฐ’์ด ์กด์žฌํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋Š” ์ƒํ™ฉ์— ๋Œ€์‘ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•œ๋‹ค. Option์˜ ๋ฉค๋ฒ„์ธ None์€ ๊ฐ’์ด ์กด์žฌํ•˜์ง€ ์•Š์Œ์„ ์˜๋ฏธํ•œ๋‹ค. ๋ฐ˜๋Œ€๋กœ Some์€ ๊ฐ’์ด ์กด์žฌํ•˜๋Š” ๊ฒฝ์šฐ์˜ T ํƒ€์ž… ๊ฐ’์„ ์˜๋ฏธํ•œ๋‹ค. Option์€ match๋ฅผ ์ด์šฉํ•ด ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๋‹ค. nullableํ•œ ๊ฐ’์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด Option ํƒ€์ž…์„ ๋ฐ›๋Š” ํ•จ์ˆ˜ plus_one์ด ์žˆ๋‹ค:

fn plus_one(x: Option<i32>) -> Option<i32> {
    match x {
        None => None,
        Some(i) => Some(i + 1),
    }
}

let one: Option<i32> = Some(1);
let two = plus_one(one); // Some(2)
let none = plus_one(None); // None

Option<i32> ํƒ€์ž… ํŒŒ๋ผ๋ฏธํ„ฐ x๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด ๊ทธ๋Œ€๋กœ None์„ ๋ฐ˜ํ™˜ํ•˜๊ณ , ๊ฐ’์ด ์กด์žฌํ•˜๋ฉด 1์„ ๋”ํ•œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค. match๋กœ Option ํƒ€์ž…์„ ๋น„๊ตํ•  ๋•Œ๋Š” ๋ฐ˜๋“œ์‹œ Some๊ณผ None์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ๋ฅผ ๋ชจ๋‘ ํ•ด์•ผํ•œ๋‹ค. ๋˜ํ•œ Option<T> ํƒ€์ž…์„ T ํƒ€์ž…๊ณผ ์—ฐ์‚ฐํ•˜๋ ค๋ฉด Option<T>๋ฅผ T๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ณผ์ •์„ ๊ฑฐ์ณ์•ผ ํ•œ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด T ํƒ€์ž…๊ณผ ์—ฐ์‚ฐํ•˜๋Š” ๋Œ€์ƒ์ด ์กด์žฌํ•œ๋‹ค๋Š” ์‚ฌ์‹ค์„ ๋ณด์žฅ ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋ณ€์ˆ˜์— ๋‹จ์ˆœํžˆ null์„ ํ• ๋‹นํ•ด ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ํ›จ์”ฌ ์•ˆ์ „ํ•˜๋‹ค.

์•ˆ์ „ํ•œ ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ

๋Ÿฌ์ŠคํŠธ๋Š” ์˜ค๋„ˆ์‹ญ์ด๋ผ๋Š” ๋ฐฉ์‹์œผ๋กœ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค. C์—์„œ๋Š” malloc์ด๋‚˜ free๊ฐ™์€ ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ์ง์ ‘ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ• ๋‹น, ํ•ด์ œํ•œ๋‹ค. ์ž๋ฐ”์—์„œ๋Š” ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ(Garbage collector)๊ฐ€ ๋Œ๋ฉฐ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ •๋ฆฌํ•œ๋‹ค. (Java๋Š” ์–ด๋–ป๊ฒŒ Garbage Collection์„ ํ• ๊นŒ? ) ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ด€๋ฆฌํ•˜๋ฉด ์‹ค์ˆ˜ํ•  ์œ„ํ—˜์ด ๋„ˆ๋ฌด ํฌ๊ณ , ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ๋ฅผ ์ด์šฉํ•˜๋ฉด ํ”„๋กœ๊ทธ๋žจ ์„ฑ๋Šฅ์ด ์ €ํ•˜๋œ๋‹ค. ์ด๋Ÿฐ ์ ์—์„œ ์˜ค๋„ˆ์‹ญ์ด๋ผ๋Š” ์ƒˆ๋กœ์šด ๋ฐฉ์‹์˜ ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ ๋ฐฉ์‹์€ ํ˜์‹ ์ ์ด๋‹ค.

์˜ค๋„ˆ์‹ญ์€ ๋ง๊ทธ๋Œ€๋กœ ๊ฐ’์— ๋Œ€ํ•œ ๋ณ€์ˆ˜์˜ ์†Œ์œ ๊ถŒ์— ๊ด€ํ•œ ๊ฒƒ์ด๋ฉฐ, ์˜ค๋„ˆ์‹ญ์—๋Š” ์„ธ ๊ฐ€์ง€ ์›์น™์ด ์žˆ๋‹ค:

  • ๊ฐ ๊ฐ’์€ ์˜ค๋„ˆ(Owner)๋ผ๊ณ  ๋ถˆ๋ฆฌ๋Š” ๋ณ€์ˆ˜๋ฅผ ๊ฐ–๋Š”๋‹ค.
  • ํ•œ ๋ฒˆ์— ํ•˜๋‚˜์˜ ์˜ค๋„ˆ๋งŒ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋‹ค.
  • ์˜ค๋„ˆ๊ฐ€ ์Šค์ฝ”ํ”„๋ฅผ ๋ฒ—์–ด๋‚˜๋ฉด ๊ฐ’์ด ๋ฒ„๋ ค์ง„๋‹ค.

Copy

let x = 5;
let y = x; // `y` is 5, and `x` is still valid

์œ„ ์ฝ”๋“œ๋Š” ์ •์ˆ˜ 5๋ฅผ ๋ณ€์ˆ˜ x์— ๋ฐ”์ธ๋”ฉ(Binding)ํ•œ ๋’ค, x ๊ฐ’์˜ ๋ณต์‚ฌ๋ณธ์„ y์— ๋ฐ”์ธ๋”ฉํ•œ๋‹ค. ๋‘ ๊ฐ’์€ ๋ชจ๋‘ 5๋‹ค. ๊ฐ’์„ '๋ณต์‚ฌโ€™ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์ •์ˆ˜, ๋ถˆ๋ฆฌ์–ธ ๋“ฑ ์Šคํƒ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€๋ถ€๋ถ„์˜ ์›์‹œ ํƒ€์ž… ๊ฐ’์€ ๋ณต์‚ฌ๋œ๋‹ค. ์ด์ฒ˜๋Ÿผ ์Šคํƒ ๋ฉ”๋ชจ๋ฆฌ ๋ฐ์ดํ„ฐ๋Š” ํฌ๊ธฐ๊ฐ€ ๊ณ ์ •๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ’์„ ๋ณต์‚ฌํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ํž™ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํƒ€์ž…์€ ๊ทธ๋ ‡์ง€ ์•Š๋‹ค.

Move

let s1 = String::from("hello");
let s2 = s1; // `s2` is "hello", and `s1` is no longer valid

s1์— String::from("hello")๋ฅผ ํ• ๋‹นํ–ˆ๋‹ค. let s = "hello"์ฒ˜๋Ÿผ ๋ฌธ์ž์—ด ๋ฆฌํ„ฐ๋Ÿด(String literal)์„ ํ• ๋‹นํ•˜๋Š” ๊ฒƒ๊ณผ๋Š” ๋‹ค๋ฅด๋‹ค. ๋ฌธ์ž์—ด ๋ฆฌํ„ฐ๋Ÿด์€ ํ”„๋กœ๊ทธ๋žจ์— ํ•˜๋“œ์ฝ”๋”ฉ๋˜๋ฉฐ, ๋ฌธ์ž์—ด์„ ์ž๋ฅด๊ฑฐ๋‚˜ ์ด์–ด ๋ถ™์ด๋Š” ๋“ฑ์˜ ๋ณ€๊ฒฝ์„ ํ•  ์ˆ˜ ์—†๋‹ค. ๋ฐ˜๋ฉด String ํƒ€์ž…์€ ํž™ ๋ฉ”๋ชจ๋ฆฌ์— ํ• ๋‹น๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋Ÿฐํƒ€์ž„์— ๋ฌธ์ž์—ด์„ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด์–ด์„œ s2์— s1์„ ํ• ๋‹นํ–ˆ๋‹ค. s2๊ฐ€ "hello"์ธ ๊ฒƒ์€ ์ž๋ช…ํ•˜๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์ด์ œ s1์€ ์œ ํšจํ•˜์ง€ ์•Š๋‹ค. ์˜ค๋„ˆ์‹ญ์ด '์ด๋™โ€™ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. String ํƒ€์ž…์€ ๋ฉ”๋ชจ๋ฆฌ ํฌ์ธํ„ฐ(ptr), ๊ธธ์ด(len), ์šฉ๋Ÿ‰(capacity) ์„ธ ์ •๋ณด๋ฅผ ์Šคํƒ ๋ฉ”๋ชจ๋ฆฌ์— ๋‹ด๋Š”๋‹ค. ์ฒ˜์Œ์— s1์˜ ํฌ์ธํ„ฐ๋Š” ํž™ ๋ฉ”๋ชจ๋ฆฌ์— ์žˆ๋Š” ๋ฐ์ดํ„ฐ "hello"์˜ 0๋ฒˆ ์ธ๋ฑ์Šค๋ฅผ ๊ฐ€๋ฆฌ์ผฐ๋‹ค.

let s1 = String::from("hello");

println!("{:?}", s1.as_ptr()); // "0x56397fd89a40"

+----------+---+        +---+---+
| ptr      | ---------->| 0 | h |
+----------+---+        +---+---+
| len      | 5 |        | 1 | e |
+----------+---+        +---+---+
| capacity | 5 |        | 2 | l |
+----------+---+        +---+---+
       s1               | 3 | l |
                        +---+---+
                        | 4 | o |
                        +---+---+

๋˜ ๋‹ค๋ฅธ ๋ณ€์ˆ˜ s2๋ฅผ ๋งŒ๋“ค์–ด s2์— s1์„ ํ• ๋‹นํ•˜๋ฉด ์Šคํƒ์˜ s1 ๋ฐ์ดํ„ฐ๊ฐ€ ๋ณต์‚ฌ๋œ๋‹ค. ์ด๋•Œ ํž™์— ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋Š” ๋ณต์‚ฌ๋˜์ง€ ์•Š๋Š”๋‹ค. ๋‹จ์ง€ s1๊ณผ ๊ฐ™์€ ํฌ์ธํ„ฐ๋ฅผ ๊ฐ€์ง„ s2๊ฐ€ ๋งŒ๋“ค์–ด์ง„๋‹ค.

let s1 = String::from("hello");
let s2 = s1;

+----------+---+         +---+---+
| ptr      | -------+--->| 0 | h |
+----------+---+    |    +---+---+
| len      | 5 |    |    | 1 | e |
+----------+---+    |    +---+---+
| capacity | 5 |    |    | 2 | l |
+----------+---+    |    +---+---+
       s1           |    | 3 | l |
                    |    +---+---+
+----------+---+    |    | 4 | o |
| ptr      | -------+    +---+---+
+----------+---+
| len      | 5 |
+----------+---+
| capacity | 5 |
+----------+---+
       s2

ํ•ฉ๋‹นํ•œ ๋™์ž‘๊ฐ™์ง€๋งŒ ์—ฌ๊ธฐ์—” ํ•จ์ •์ด ์žˆ๋‹ค. ๋Ÿฌ์ŠคํŠธ๋Š” ๋ณ€์ˆ˜๊ฐ€ ์Šค์ฝ”ํ”„๋ฅผ ๋ฒ—์–ด๋‚ฌ์„ ๋•Œ ์ž๋™์œผ๋กœ drop ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด ํž™ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ •๋ฆฌํ•œ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์œ„์™€ ๊ฐ™์ด s1๊ณผ s2๊ฐ€ ๊ฐ™์€ ํž™ ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋ฉด s1์ด ์Šค์ฝ”ํ”„๋ฅผ ๋ฒ—์–ด๋‚ฌ์„ ๋•Œ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ํ•œ ๋ฒˆ ํ•ด์ œ๋˜๊ณ , ๊ทธ ๋’ค์— s2๊ฐ€ ์Šค์ฝ”ํ”„๋ฅผ ๋ฒ—์–ด๋‚  ๋•Œ ๊ฐ™์€ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„๋ฅผ ๋‹ค์‹œ ํ•ด์ œํ•˜๊ฒŒ ๋œ๋‹ค. ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋‘ ๋ฒˆ ํ•ด์ œํ•˜๋ฉด ๋ฉ”๋ชจ๋ฆฌ ๋ณ€ํ˜•(Corruption)์„ ์ผ์œผํ‚ฌ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๋Š” ๋ณด์•ˆ ์ทจ์•ฝ์ ์œผ๋กœ ์ด์–ด์ง„๋‹ค.

๊ทธ๋ž˜์„œ ๋Ÿฌ์ŠคํŠธ๋Š” ํ• ๋‹น๋œ ์Šคํƒ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋ณต์‚ฌํ•  ๋•Œ ๊ธฐ์กด์— ํ• ๋‹นํ•œ ๋ณ€์ˆ˜ s1์„ ๋ฌดํšจํ™”ํ•œ๋‹ค. ๋”ฐ๋ผ์„œ s2 ๋ณ€์ˆ˜๋งŒ์ด ํž™ ๋ฉ”๋ชจ๋ฆฌ ๋ฐ์ดํ„ฐ "hello"๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค.

let s1 = String::from("hello");
let s2 = s1;

println!("{:?}", s1.as_ptr()); // error[E0382]: borrow of moved value: `s1`
println!("{:?}", s2.as_ptr()); // "0x56397fd89a40"

                         +---+---+
                    +--->| 0 | h |
                    |    +---+---+
                    |    | 1 | e |
                    |    +---+---+
                    |    | 2 | l |
                    |    +---+---+
                    |    | 3 | l |
                    |    +---+---+
+----------+---+    |    | 4 | o |
| ptr      | -------+    +---+---+
+----------+---+
| len      | 5 |
+----------+---+
| capacity | 5 |
+----------+---+
       s2

์ด์ œ s2๊ฐ€ ์Šค์ฝ”ํ”„๋ฅผ ๋ฒ—์–ด๋‚  ๋•Œ ํ•œ ๋ฒˆ๋งŒ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ•ด์ œํ•˜๋ฉด ๋œ๋‹ค. ์ด๋ฅผ s1์˜ ์˜ค๋„ˆ์‹ญ์ด s2๋กœ ์ด๋™ํ–ˆ๋‹ค๊ณ  ๋งํ•œ๋‹ค. ํž™ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” String ํƒ€์ž…์ด๋‚˜ Vec ํƒ€์ž… ๋“ฑ ๋น„์›์‹œ ํƒ€์ž…๋“ค์€ ์˜ค๋„ˆ์‹ญ์ด ์ด๋™ํ•œ๋‹ค. ์ด๋Ÿฐ ํƒ€์ž…๋“ค์— ๋Œ€ํ•ด ๊นŠ์€ ๋ณต์‚ฌ๋ฅผ ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด clone ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

ํ•จ์ˆ˜ ์ธ์ž๋กœ ๊ฐ’์„ ๋„˜๊ธธ ๋•Œ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์˜ค๋„ˆ์‹ญ์ด ์ด๋™ํ•œ๋‹ค:

let s = String::from("hello");
takes_ownership(s);
// `s` is no longer valid here

๋ณ€์ˆ˜ s๊ฐ€ takes_ownership ํ•จ์ˆ˜์˜ ์ธ์ž๋กœ ๋„˜์–ด๊ฐ€๋ฉด์„œ ์˜ค๋„ˆ์‹ญ๋„ ์ด๋™ํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ๊ฐ’์„ ๋„˜๊ธด ์ดํ›„์—๋Š” s๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค. ๋ฐ˜๋Œ€๋กœ ํ•จ์ˆ˜์—์„œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•  ๋•Œ๋„ ์˜ค๋„ˆ์‹ญ์ด ์ด๋™ํ•œ๋‹ค.

References & Borrowing

ํ•จ์ˆ˜์˜ ์ธ์ž๋กœ ๊ฐ’์„ ๋„˜๊ธฐ๋˜, ์˜ค๋„ˆ์‹ญ์„ ์ด๋™์‹œํ‚ค๊ณ  ์‹ถ์ง€ ์•Š์„ ๋•Œ๋Š” ๊ฐ’์˜ ์ฐธ์กฐ(Reference)๋งŒ ๋„˜๊ฒจ์ฃผ๋ฉด ๋œ๋‹ค. ์ด๋ฅผ ๋นŒ๋ฆผ(Borrowing)์ด๋ผ๊ณ  ํ•œ๋‹ค.

fn main() {
    let s1 = String::from("hello");
    let len = get_length(&s1);
    println!("{}: {}", s1, len); // "hello: 5"
}

fn get_length(s2: &String) -> usize {
    s2.len()
}

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด get_length ๋‚ด์—์„œ s2์˜ ํฌ์ธํ„ฐ๊ฐ€ s1์„ ๊ฐ€๋ฆฌํ‚ค๊ณ , s1์€ ํž™ ๋ฉ”๋ชจ๋ฆฌ์˜ โ€œhelloโ€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ฒŒ ๋œ๋‹ค. ํ•จ์ˆ˜๊ฐ€ ์ฐธ์กฐ๋งŒ ๋ฐ›์•˜๊ธฐ ๋•Œ๋ฌธ์— ํ•จ์ˆ˜ ํ˜ธ์ถœ ์ดํ›„์—๋„ s1์€ ์œ ํšจํ•˜๋‹ค.

fn main() {
    let s1 = String::from("hello");
    let len = get_length(&s1);
    println!("{:?}", s1.as_ptr()); // "0x5581762b0a40"
}

fn get_length(s2: &String) -> usize {
    println!("{:?}", s2.as_ptr()); // "0x5581762b0a40"
    s2.len()
}

+----------+---+        +----------+---+        +---+---+
| ptr      | ---------->| ptr      | ---------->| 0 | h |
+----------+---+        +----------+---+        +---+---+
       s2               | len      | 5 |        | 1 | e |
                        +----------+---+        +---+---+
                        | capacity | 5 |        | 2 | l |
                        +----------+---+        +---+---+
                               s1               | 3 | l |
                                                +---+---+
                                                | 4 | o |
                                                +---+---+

๋งŒ์•ฝ ์ฐธ์กฐ๋ฅผ ์ด์šฉํ•ด ๊ฐ’์„ ๋ฐ”๊พธ๊ณ  ์‹ถ๋‹ค๋ฉด ๊ฐ€๋ณ€ ์ฐธ์กฐ(Mutable reference)๋ฅผ ๋นŒ๋ ค์•ผ ํ•œ๋‹ค:

fn main() {
    let mut hello = String::from("hello");
    change(&mut hello);
    println!("{}", hello); // "hello, world"
}

fn change(s: &mut String) {
    s.push_str(", world");
}

&mut ํ‚ค์›Œ๋“œ๋ฅผ ์ด์šฉํ•ด ๊ฐ€๋ณ€ ์ฐธ์กฐ๋ฅผ ๋„˜๊ธฐ๋ฉด change ํ•จ์ˆ˜ ์•ˆ์—์„œ ์ธ์ž๋กœ ๋ฐ›์€ ๊ฐ’์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋ฅผ ๊ฐ€๋ณ€ ๋นŒ๋ฆผ(Mutable borrowing)์ด๋ผ๊ณ  ํ•œ๋‹ค. change ํ•จ์ˆ˜์—์„œ ๊ฐ€๋ณ€ ์ฐธ์กฐ๋กœ ๋ฐ›์€ ๋ฌธ์ž์—ด s ๋’ค์— โ€œ, worldโ€ ๋ฌธ์ž์—ด์„ ๋ง๋ถ™์—ฌ ๋ฐ˜ํ™˜ํ–ˆ๋Š”๋ฐ, ๊ฒ‰์œผ๋กœ ๋ณด๋ฉด ํž™ ๋ฉ”๋ชจ๋ฆฌ์˜ โ€œhelloโ€ ๋ฐ์ดํ„ฐ ๋’ค์— ๋ฌธ์ž์—ด์„ ๊ทธ๋Œ€๋กœ ๋ถ™์ธ ๊ฒƒ ๊ฐ™๋‹ค. ํ•˜์ง€๋งŒ ์ด๋ฏธ ํ• ๋‹นํ•œ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์„ ๋งˆ์Œ๋Œ€๋กœ ๋Š˜๋ฆด ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์‹ค์ œ๋กœ๋Š” ํž™ ๋ฉ”๋ชจ๋ฆฌ์— ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ๋ฅผ ๋งŒ๋“ค๊ณ  ํฌ์ธํ„ฐ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ๋ฅผ ๋ฐ”๊ฟ” ๊ฐ’์„ ์žฌํ• ๋‹นํ•ด์•ผ ํ•œ๋‹ค.

let mut s = String::from("hello");
println!("{:?}", s.as_ptr()); // "0x55765a598a40"

s.push_str(", world");
println!("{:?}", s.as_ptr()); // "0x55765a598ba0"

                                          0   1   2   3   4
+----------+----+        +----------------+---+---+---+---+---+
| ptr      |  -------+   | 0x55765a598a40 | h | e | l | l | o |
+----------+----+    |   +----------------+---+---+---+---+---+
| len      | 12 |    |
+----------+----+    |                    0   1   2   3   4   5   6   7   8
| capacity | 12 |    |   +----------------+---+---+---+---+---+---+---+---+---+
+----------+----+    +-->| 0x55765a598ba0 | h | e | l | l | o | , |   | w | o | ...
        s                +----------------+---+---+---+---+---+---+---+---+---+

๊ทธ๋Ÿฐ๋ฐ ๊ฐ’์„ ์ถ”๊ฐ€ํ•  ๋•Œ๋งˆ๋‹ค ๋งค๋ฒˆ ํž™ ๋ฉ”๋ชจ๋ฆฌ์— ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ๋ฅผ ๋งŒ๋“ค๋ฉด ์„ฑ๋Šฅ์— ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธฐ๊ธฐ ๋•Œ๋ฌธ์— ๋Ÿฌ์ŠคํŠธ๋Š” ๋ฏธ๋ž˜๋ฅผ ๋Œ€๋น„ํ•ด ์ฒ˜์Œ๋ถ€ํ„ฐ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์„ ์กฐ๊ธˆ ํฌ๊ฒŒ ์žก์•„ ๋‘”๋‹ค.[5]

let mut s = String::from("hello");
println!("{:?}", s.as_ptr()); // "0x55765a598a40"

s.push_str(", world");
println!("{:?}", s.as_ptr()); // "0x55765a598a40"

                                          0   1   2   3   4         10  11  12  13
+----------+----+        +----------------+---+---+---+---+---+     +---+---+---+---+
| ptr      |  ---------->| 0x55765a598a40 | h | e | l | l | o | ... | l | d |   |   | ...
+----------+----+        +----------------+---+---+---+---+---+     +---+---+---+---+
| len      | 12 |
+----------+----+
| capacity | 26 |
+----------+----+
        s

capacity๊ฐ€ 26์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ๋ณด๋‹ค ์ ์€ ๊ฐœ์ˆ˜์˜ ๋ฌธ์ž๋ฅผ ์ถ”๊ฐ€ํ•  ๋•Œ๋Š” ํฌ์ธํ„ฐ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ํž™ ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ๋‚˜ capacity์˜ ๊ฐ’์ด ๋ณ€ํ•˜์ง€ ์•Š๋Š”๋‹ค. ์ฆ‰, ์žฌํ• ๋‹น์ด ํ•„์š”ํ•˜์ง€ ์•Š๋‹ค.

๊ฐ€๋ณ€ ์ฐธ์กฐ๋ฅผ ๋นŒ๋ ค์ค„ ๋•Œ ์ฃผ์˜ํ•  ์ ์€ ํ•œ ์Šค์ฝ”ํ”„ ์•ˆ์—์„œ ๊ฐ€๋ณ€ ์ฐธ์กฐ๋Š” ํ•œ ๋ฒˆ๋งŒ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

let mut s = String::from("hello");

let r1 = &mut s;
let r2 = &mut s;

r1.push_str(", world"); // error[E0499]: cannot borrow `s` as mutable more than once at a time

r1์— ๊ฐ€๋ณ€ ์ฐธ์กฐ๋ฅผ ๋นŒ๋ ค์ค€ ๋‹ค์Œ, ๋ฐ”๋กœ r2์— ๊ฐ€๋ณ€ ์ฐธ์กฐ๋ฅผ ๋นŒ๋ ค์คฌ๊ธฐ ๋•Œ๋ฌธ์— r2๊ฐ€ ์•„๋‹Œ r1์„ ์ด์šฉํ•ด ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜๋ ค ํ•˜๋ฉด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. ๋Ÿฌ์ŠคํŠธ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์—๋Ÿฌ์˜ ์ด์œ ์™€ ์œ„์น˜๋ฅผ ์นœ์ ˆํ•˜๊ฒŒ ์•Œ๋ ค์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ์‰ฝ๊ฒŒ ๊ณ ์น  ์ˆ˜ ์žˆ๋‹ค.

error[E0499]: cannot borrow `s` as mutable more than once at a time
 --> src/main.rs:5:14
  |
4 |     let r1 = &mut s;
  |              ------ first mutable borrow occurs here
5 |     let r2 = &mut s;
  |              ^^^^^^ second mutable borrow occurs here
6 |
7 |     r1.push_str(", world");
  |     -- first borrow later used here

์ด๋Ÿฐ ์ œ์•ฝ์„ ๋งŒ๋“ฆ์œผ๋กœ์จ ๋Ÿฌ์ŠคํŠธ๋Š” ์ปดํŒŒ์ผ ํƒ€์ž„์— ๊ฒฝ์Ÿ ์ƒํƒœ(Race condition)๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ฒฝ์Ÿ ์ƒํƒœ๋Š” (1)๋‘ ๊ฐœ ์ด์ƒ์˜ ํฌ์ธํ„ฐ๊ฐ€ ๋™์‹œ์— ๊ฐ™์€ ๋ฐ์ดํ„ฐ์— ์ ‘๊ทผํ•˜๋ฉฐ (2)์ตœ์†Œ ํ•˜๋‚˜์˜ ํฌ์ธํ„ฐ๊ฐ€ ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ์„ ์‹œ๋„ํ•˜๊ณ  (3)๋ฐ์ดํ„ฐ๋ฅผ ๋™๊ธฐํ™”ํ•˜๋Š” ๋ฉ”์ปค๋‹ˆ์ฆ˜์ด ์—†๋Š” ๊ฒฝ์šฐ์— ์ถฉ์กฑ๋œ๋‹ค. ๋ฐ์ดํ„ฐ ๊ฒฝ์Ÿ์€ ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๋ฌธ์ œ๋ฅผ ์ผ์œผํ‚ค๋ฉฐ, ๋Ÿฐํƒ€์ž„์— ์•Œ์•„๋‚ด๊ธฐ๋„ ํž˜๋“ค๋‹ค.

์˜ค๋„ˆ์‹ญ ๋ชจ๋ธ์˜ ์ตœ๋Œ€ ์žฅ์ ์ด๋ผ๋ฉด ์ปดํŒŒ์ผ ํƒ€์ž„์— ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ฅ˜๋ฅผ ์žก์„ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•œ๋‹ค. ๋‹ค๋ฅธ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ์ž˜๋ชป๋œ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์„ ์ฐธ์กฐํ•ด์„œ ๋Ÿฐํƒ€์ž„ ์ค‘์— ์„ธ๊ทธ๋จผํŠธ ํดํŠธ๊ฐ€ ์ผ์–ด๋‚˜๊ณ  ํ”„๋กœ๊ทธ๋žจ์ด ์ฃฝ๋Š” ์ผ์ด ํ—ˆ๋‹คํ–ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋Ÿฌ์ŠคํŠธ์—์„  ์ผ๋‹จ ์ปดํŒŒ์ผ๋งŒ ์ž˜ ๋˜๋ฉด ๋Ÿฐํƒ€์ž„์— ํ”„๋กœ๊ทธ๋žจ์ด ์˜ˆ์ƒ์น˜ ๋ชปํ•˜๊ฒŒ ์ฃฝ๋Š” ์ผ์ด ๊ฑฐ์˜ ์—†์œผ๋ฉฐ, ์ฝ”๋“œ ๋ ˆ๋ฒจ์—์„œ ์•ˆ์ „์„ ๋ณด์žฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋Ÿฐํƒ€์ž„ ์˜ค๋ฒ„ํ—ค๋“œ ์—ญ์‹œ ์—†๋‹ค. ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋™์‹œ์„ฑ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ ์ผ์–ด๋‚˜๋Š” ๋งŽ์€ ์ด์Šˆ๋ฅผ ํ”ผํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

์•ˆ์ „์„ ์œ„ํ•œ ์—๋Ÿฌ ํ•ธ๋“ค๋ง

panic! ๋งคํฌ๋กœ๋Š” ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ์ถœ๋ ฅํ•˜๊ณ  ํ”„๋กœ๊ทธ๋žจ์˜ ์Šคํƒ์„ ๋˜๋Œ๋ฆฐ ๋’ค ์ข…๋ฃŒ์‹œํ‚จ๋‹ค. ์ด๋ฅผ ์ด์šฉํ•˜๋ฉด ํ”„๋กœ๊ทธ๋žจ์„ ์ค‘๋‹จํ•ด์•ผ ํ•  ์ •๋„๋กœ ์‹ฌ๊ฐํ•œ ๋ฌธ์ œ๊ฐ€ ์˜ˆ์ƒ๋  ๋•Œ ์˜๋„์ ์œผ๋กœ ์—๋Ÿฌ๋ฅผ ์ผ์œผํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.

panic!("crash and burn"); // thread 'main' panicked at 'crash and burn'

ํ•˜์ง€๋งŒ ๋ชจ๋“  ์—๋Ÿฌ๊ฐ€ ํ”„๋กœ๊ทธ๋žจ์„ ์ค‘๋‹จํ•ด์•ผ ํ•  ์ •๋„๋กœ ์‹ฌ๊ฐํ•œ ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ์—๋Ÿฌ๋ฅผ ์œ ์—ฐํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ๋Ÿฌ์ŠคํŠธ๋Š” Result ์—ด๊ฑฐํ˜•์„ ์ œ๊ณตํ•œ๋‹ค.

enum Result<T, E> {
    Ok(T),
    Err(E),
}

ํ•จ์ˆ˜์˜ ๊ฒฐ๊ณผ๋ฅผ Result๋กœ ๋ฐ˜ํ™˜ํ•˜๋ฉด ํ•จ์ˆ˜์˜ ํ˜ธ์ถœ์ฒ˜์—์„œ๋Š” match๋ฅผ ์ด์šฉํ•ด ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋ฅผ ํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค.

let file = File::open("data");
let file = match file {
    Ok(f) => f,
    Err(error) => panic!("Failed to open the file: {:?}", error)
};

data ํŒŒ์ผ์„ ์—ฌ๋Š” open ๋ฉ”์†Œ๋“œ๊ฐ€ ์ž˜ ๋™์ž‘ํ–ˆ์œผ๋ฉด ์˜คํ”ˆํ•œ ํŒŒ์ผ์„ ๊ทธ๋Œ€๋กœ file์— ํ• ๋‹นํ•˜๊ณ , ๋ฌธ์ œ๊ฐ€ ์žˆ์œผ๋ฉด panic! ๋งคํฌ๋กœ๋ฅผ ํ†ตํ•ด ์—๋Ÿฌ๋ฅผ ์ผ์œผํ‚จ๋‹ค. ์—๋Ÿฌ์˜ ์ข…๋ฅ˜์— ๋”ฐ๋ผ ์ค‘์ฒฉํ•ด์„œ ๋ถ„๊ธฐํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ์•„๋ž˜ ์ฝ”๋“œ๋Š” ํŒŒ์ผ ์—ด๊ธฐ๋ฅผ ์‹œ๋„ํ–ˆ์„ ๋•Œ ํ•ด๋‹น ํŒŒ์ผ์ด ์—†์œผ๋ฉด ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๋ฉฐ, ๊ทธ ์™ธ์—๋Š” ์—๋Ÿฌ๋ฅผ ์ผ์œผํ‚จ๋‹ค.

let file = File::open("data");
let file = match file {
      Ok(f) => f,
      Err(error) => match error.kind() {
          ErrorKind::NotFound => match File::create("data") {
              Ok(fc) => fc,
              Err(e) => panic!("Failed to create file: {:?}", e),
          },
          other_error => panic!("Failed to open file: {:?}", other_error),
      },
  };

Result ํƒ€์ž…์€ ์ข€ ๋” ๊ฐ„๋‹จํ•œ ์—๋Ÿฌ ํ•ธ๋“ค๋ง์„ ์œ„ํ•ด unwrap ๋ฉ”์†Œ๋“œ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

let file = File::open("data").unwrap();

unwrap ๋ฉ”์†Œ๋“œ๋Š” Result๊ฐ€ Ok๋ฉด Ok์˜ ๊ฐ’์„ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜ํ•˜๊ณ , Err์ด๋ฉด panic! ๋งคํฌ๋กœ๋ฅผ ํ˜ธ์ถœํ•ด ์—๋Ÿฌ๋ฅผ ์ผ์œผํ‚จ๋‹ค. unwrap๊ณผ ๋น„์Šทํ•˜์ง€๋งŒ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ์ง์ ‘ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋Š” expect ๋ฉ”์†Œ๋“œ๋„ ์žˆ๋‹ค.

let file = File::open("data").expect("Failed to open the data file");

unwrap์„ ๋‚จ์šฉํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค๋Š” expect๋ฅผ ์ด์šฉํ•ด ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ๊ตฌ์ฒด์ ์œผ๋กœ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. ํ•จ์ˆ˜ ์•ˆ์—์„œ ํ•จ์ˆ˜์˜ ํ˜ธ์ถœ์ฒ˜๋กœ ์—๋Ÿฌ๋ฅผ ์ „ํŒŒํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ๊ฐ„๋‹จํžˆ ?๋ฅผ ๋ถ™์—ฌ์ฃผ๋ฉด ๋œ๋‹ค.

fn open_file() -> Result<File, io::Error> {
    let file = File::open("data")?;
    // do stuff with `file`
    Ok(file)
}

์œ„ ์ฝ”๋“œ๋Š” open์˜ Result๊ฐ€ Ok๋ฉด Ok์˜ ๊ฐ’์„ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜ ๋’ค ๋‹ค์Œ ๋‚ด์šฉ์„ ๊ณ„์† ์ง„ํ–‰ํ•œ๋‹ค. ๋ฐ˜๋Œ€๋กœ Err์ด๋ฉด Err์„ ๋ฐ˜ํ™˜ํ•˜๊ณ  ํ•จ์ˆ˜๋ฅผ ๋น ์ ธ ๋‚˜์˜จ๋‹ค. ? ์—ฐ์‚ฐ์ž๋Š” ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ํ•จ์ˆ˜์˜ ๊ฒฐ๊ณผ๋กœ Err์„ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ˜๋“œ์‹œ Result ํƒ€์ž…์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์— ์ฃผ์˜ํ•ด์•ผ ํ•œ๋‹ค.

No Silver Bullet

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

ํ˜„์žฌ๋กœ์จ ๋Ÿฌ์ŠคํŠธ์˜ ๊ฐ€์žฅ ํฐ ๋‹จ์ ์€ ์‹ ์ƒ ์–ธ์–ด์ด๋‹ค ๋ณด๋‹ˆ ์ž๋ฃŒ๊ฐ€ ๋งŽ์ง€ ์•Š๊ณ , ๊ทธ๋‚˜๋งˆ ์žˆ๋Š” ๊ฒƒ๋„ ์ง€๊ธˆ์€ ์œ ํšจํ•˜์ง€ ์•Š์€ ์ •๋ณด๋ผ๋Š” ์ ์ด๋‹ค. ์‹ฌ์ง€์–ด ๋™๋ช…์˜ ๊ฒŒ์ž„์ด ์žˆ์–ด์„œ โ€œrust langโ€ ๋˜๋Š” "๋Ÿฌ์ŠคํŠธ ์–ธ์–ด"๋กœ ๊ฒ€์ƒ‰ํ•˜์ง€ ์•Š๋Š” ์ด์ƒ ๊ฒ€์ƒ‰๋„ ์ž˜ ์•ˆ ๋œ๋‹ค. ์ด๋Ÿฐ ์ƒํ™ฉ๊ณผ ๋™์‹œ์— ์–ธ์–ด ์ž์ฒด๋„ ๋Ÿฌ๋‹์ปค๋ธŒ๊ฐ€ ์žˆ๋Š” ํŽธ์ด๋‹ค. ์‚ฌ๋žŒ์˜ ์‹ค์ˆ˜๋ฅผ ์–ธ์–ด ์ฐจ์›์—์„œ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค์–‘ํ•œ ์ œ์•ฝ ์‚ฌํ•ญ์ด ์žˆ๊ณ , ์˜ค๋„ˆ์‹ญ ๋“ฑ ๋Ÿฌ์ŠคํŠธ์˜ ํ•ต์‹ฌ ๊ฐœ๋…์ด ์ƒ์†Œํ•˜๊ฒŒ ๋‹ค๊ฐ€์˜ค๊ธฐ ๋•Œ๋ฌธ์ด๊ธฐ๋„ ํ•˜๋‹ค.

๋Ÿฌ์ŠคํŠธ๋Š” ๋น„์Šทํ•œ ๋ชฉํ‘œ๋ฅผ ๊ฐ€์ง„ Go ์–ธ์–ด์™€ ์ž์ฃผ ๋น„๊ต๋˜๊ณค ํ•œ๋‹ค. Go๋Š” ๋‹จ์ˆœํ•œ ๋ฌธ๋ฒ•๊ณผ Go ๋ฃจํ‹ด์„ ์ด์šฉํ•œ ๊ฐ€๋ฒผ์šด ๋™์‹œ์„ฑ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ด ์žฅ์ ์ด๋‹ค. Go๋ฅผ ์„ค๊ณ„ํ•œ ๋กญ ํŒŒ์ดํฌ(Rob Pike)๊ฐ€ "๊ฐ“ ์กธ์—…ํ•ด์„œ ํ›Œ๋ฅญํ•œ ์–ธ์–ด๋ฅผ ์ดํ•ดํ•  ๋Šฅ๋ ฅ์ด ์—†๋Š” ์–ด๋ฆฐ ๊ตฌ๊ธ€ ์ง์›๋“ค์„ ์œ„ํ•ด ๋‹จ์ˆœํ•˜๊ฒŒ ๋งŒ๋“ค์—ˆ๋‹ค"[6]๋ผ๋Š” ๋ฐœ์–ธ์„ ํ•ด์„œ ๋…ผ๋ž€์ด ๋˜๊ธฐ๋„ ํ–ˆ๋Š”๋ฐ, ํ‘œํ˜„์˜ ์ ์ ˆ์„ฑ๊ณผ ๋ณ„๊ฐœ๋กœ ํ•™์Šต๊ณผ ๊ตฌํ˜„์ด ์‰ฝ๊ณ  ์ƒ์‚ฐ์„ฑ์ด ๋†’์€ ๊ฒƒ์€ ํฐ ์žฅ์ ์ด๋‹ค. ํŠนํžˆ ๋Ÿฌ์ŠคํŠธ์˜ ๋‹จ์ ์ด ๋Ÿฌ๋‹ ์ปค๋ธŒ์ด๊ธฐ ๋•Œ๋ฌธ์— Go์˜ ์‰ฌ์šด ๋ฌธ๋ฒ•์ด ๋”์šฑ ๋ถ€๊ฐ๋œ๋‹ค. ์–ธ์–ด ์ŠคํŽ™๋งŒ ๋ณด๋ฉด ๋Ÿฌ์ŠคํŠธ๊ฐ€ ํ›จ์”ฌ ์•ˆ์ „ํ•˜๊ณ  ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ์„ ์ง€์›ํ•˜๋Š” ๊ฒƒ ๊ฐ™์ง€๋งŒ, ํ˜„์‹ค์˜ ๋ชจ๋“  ์ƒํ™ฉ์—์„œ ๊ผญ ํ•˜๋‚˜๊ฐ€ ์šฐ์œ„๋ฅผ ์ฐจ์ง€ํ•  ์ˆ˜๋Š” ์—†์„ํ…Œ๋‹ˆ ์ƒํ™ฉ์— ๋งž์ถฐ์„œ ํŒ๋‹จํ•˜๋ฉด ๋˜๊ฒ ๋‹ค.

๋‚ด๊ฐ€ ๋Ÿฌ์ŠคํŠธ๋ฅผ ์„ ํƒํ•œ ๊ฐ€์žฅ ํฐ ์ด์œ ๋Š” ์–ธ์–ด ์ฐจ์›์˜ ์•ˆ์ „์„ฑ๊ณผ ๋”๋ถˆ์–ด ์ƒํƒœ๊ณ„ ๋•Œ๋ฌธ์ด๊ธฐ๋„ ํ•˜๋‹ค. ๋Ÿฌ์ŠคํŠธ๋Š” ์ดˆ๊ธฐ๋ถ€ํ„ฐ ์นด๊ณ ๋ฅผ ํ†ตํ•œ ํŒจํ‚ค์ง€ ๊ด€๋ฆฌ๋ฅผ ์ง€์›ํ•œ ๋•๋ถ„์— ํŠผํŠผํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ƒํƒœ๊ณ„๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. ๋Ÿฌ์ŠคํŠธ ์ƒํƒœ๊ณ„์™€ ๋ฐฉ๋Œ€ํ•œ ์›น ์ƒํƒœ๊ณ„ ์‚ฌ์ด ๊ต์ง‘ํ•ฉ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ฏธ๋ž˜๋„ ๋ฐ๋‹ค. ๋Ÿฌ์ŠคํŠธ ํ”„๋กœ๊ทธ๋žจ์„ ์›น์–ด์…ˆ๋ธ”๋ฆฌ๋กœ ์ปดํŒŒ์ผํ•˜๋ฉด npm์— ํŒจํ‚ค์ง€๋ฅผ ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ๊ณ , ์ด๋ ‡๊ฒŒ ๋ฐฐํฌํ•œ ํŒจํ‚ค์ง€๋ฅผ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๊ทธ๋Œ€๋กœ ์„ค์น˜ํ•ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.[7] ์›น์–ด์…ˆ๋ธ”๋ฆฌ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ FFI(Foreign Function Interface)๋ฅผ ํ†ตํ•ด C/C++, ํŒŒ์ด์ฌ ๋“ฑ ๋‹ค๋ฅธ ์–ธ์–ด๋กœ ์ž‘์„ฑ๋œ ์™ธ๋ถ€ ํ•จ์ˆ˜๋ฅผ ๋Ÿฌ์ŠคํŠธ๋กœ ๊ฐ€์ ธ์™€ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ๋Ÿฌ์ŠคํŠธ๋กœ ์ž‘์„ฑํ•œ ํ•จ์ˆ˜๋ฅผ ๋‹ค๋ฅธ ์–ธ์–ด์—์„œ ์‚ฌ์šฉํ•˜๋„๋ก ํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ธฐ์ˆ ์ ์ธ ์ƒํƒœ๊ณ„ ๋ฟ ์•„๋‹ˆ๋ผ ์ปค๋ฎค๋‹ˆํ‹ฐ๋„ ๊ต‰์žฅํžˆ ํ™œ๋ฐœํ•˜๊ณ  ์นœ์ ˆํ•˜๋‹ค.

์ด๋Ÿฐ ํ๋ฆ„์ด๋ผ๋ฉด 'C/C++ ๋Œ€์ฒดโ€™๋ผ๋Š” ๋Ÿฌ์ŠคํŠธ์˜ ํฐ ๊ทธ๋ฆผ์ด ์ •๋ง ์ด๋ค„์งˆ ์ˆ˜๋„ ์žˆ์„ ๊ฒƒ ๊ฐ™๋‹ค.

References


  1. Karen Rustad Tรถlva, โ€œHello, crustaceansโ€, rustacean.net. โ†ฉ๏ธŽ

  2. American Psychological Association, โ€œSingular โ€˜Theyโ€™โ€, apastyle.apa.org. โ†ฉ๏ธŽ

  3. GitHub, โ€œThe State of the Octoverseโ€, 2019. โ†ฉ๏ธŽ

  4. The Rust Programming Language, โ€œProduction usersโ€, rust-lang.org. โ†ฉ๏ธŽ

  5. Rustdoc, โ€œStruct Vec - Capacity and reallocationโ€, doc.rust-lang.org. โ†ฉ๏ธŽ

  6. Rob Pike, โ€œFrom Parallel to Concurrentโ€, 2014. โ†ฉ๏ธŽ

  7. MDN web docs โ€œCompiling from Rust to WebAssemblyโ€, 2019. โ†ฉ๏ธŽ

โ†

์ธํ„ฐ๋„ท์ด ๋™์ž‘ํ•˜๋Š” ์•„์ฃผ ๊ตฌ์ฒด์ ์ธ ์›๋ฆฌ

ํ•™๊ต์—์„œ ๊ตฌ๊ธ€์— ์ ‘์†ํ•˜๋Š” ๊ณผ์ •

โ†’

๐Ÿ—ž๏ธ ํ›ˆ๋ จ์†Œ์—์„œ ๋งค์ผ ๋‰ด์Šค ๋ฐ›์•„๋ณด๊ธฐ

๊ณ ๋ฆฝ๋œ ํ›ˆ๋ จ๋ณ‘์„ ์œ„ํ•œ ์ข…ํ•ฉ ๋‰ด์Šค

โ† Articles