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
- Andrew Gallant, โError Handling in Rustโ, Andrew Gallantโs Blog, 2015.
- Steve Klabnik, Carol Nichols, โThe Rust Programming Languageโ, 2019.
- Szmozsรกnszky Istvรกn, โDiving into Rust for the first timeโ, Mozilla Hacks, 2015.
- The Rust Programming Language, โ์์ฃผ ๋ฌป๋ ์ง๋ฌธ๋คโ, 2018.
- Thomas Countz, โOwnership in Rust, Part 2โ, 2018.
- [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. โฉ๏ธ