Rust ๊ฐœ๋ฐœ์ž์šฉ ์ •์  ์ฝ”๋“œ ๋ถ„์„ ๋„๊ตฌ

Rust ๊ฐœ๋ฐœ์ž ๋„๊ตฌ ์ƒ์ž: ์ตœ๊ณ ์˜ ์ •์  ์ฝ”๋“œ ๋ถ„์„ ๋„๊ตฌ

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

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

์ฐจ๋ก€

SMART TS XL

์–ธ์–ด์˜ ๊ฐ•๋ ฅํ•œ ์•ˆ์ „์„ฑ์ด ๋ณด์žฅ๋˜๋”๋ผ๋„, ์ตœ์‹  Rust ๊ฐœ๋ฐœ์—์„œ ํ’ˆ์งˆ์„ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์€ ์–ด๋ ต์Šต๋‹ˆ๋‹ค. SMART TS XL Rust์˜ ๊ณ ์œ ํ•œ ๊ธฐ๋Šฅ์— ๋งž์ถฐ ์‹ฌ์ธต์ ์ธ ์ •์  ๋ถ„์„ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜์—ฌ ํŒ€์ด ์•ˆ์ •์ ์ด๊ณ  ์œ ์ง€ ๊ด€๋ฆฌ๊ฐ€ ์šฉ์ดํ•˜๋ฉฐ ์•ˆ์ „ํ•œ ์†Œํ”„ํŠธ์›จ์–ด๋ฅผ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋ฌธ์ œ๋ฅผ ์กฐ๊ธฐ์— ๋ฐœ๊ฒฌํ•˜๊ณ , ์ผ๊ด€์„ฑ์„ ์œ ์ง€ํ•˜๋ฉฐ, ์ˆ˜๋™ ๊ฒ€ํ†  ์ž‘์—…์„ ์ค„์—ฌ ์ „๋ฌธ์ ์ธ ์—”์ง€๋‹ˆ์–ด๋ง ์›Œํฌํ”Œ๋กœ๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

๋…น์˜ ์„ธ ๊ฐ€์ง€ ์ธต์œ„ ์ •์  ๋ถ„์„

์–ด๋–ค ๋„๊ตฌ๊ฐ€ ์–ด๋””์— ์ ํ•ฉํ•œ์ง€ ์ดํ•ดํ•˜๋ฉด ๋ฆฐํ„ฐ๋กœ ์ถฉ๋ถ„ํ•œ ๊ณณ์— ํ˜•์‹ ๊ฒ€์ฆ ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ๋ณด์•ˆ ์Šค์บ๋„ˆ๊ฐ€ ํ•„์š”ํ•œ ๊ณณ์— ๋ฆฐํ„ฐ๋งŒ ์‚ฌ์šฉํ•˜๋Š” ํ”ํ•œ ์‹ค์ˆ˜๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ์™„์„ฑ๋„ ๋†’์€ Rust ํ”„๋กœ์ ํŠธ๋Š” ์ด ์„ธ ๊ฐ€์ง€ ๊ณ„์ธต์„ ๋ชจ๋‘ ๋‹ค๋ค„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

1๋‹จ๊ณ„: ๋ณดํ’€ ์ œ๊ฑฐ ๋ฐ ์Šคํƒ€์ผ๋ง ๊ด€์šฉ์ ์ธ ํ‘œํ˜„ ์œ„๋ฐ˜, ํ”ํ•œ ์‹ค์ˆ˜ ๋ฐ ์œ ์ง€๋ณด์ˆ˜ ๋ฌธ์ œ๋ฅผ ์žก์•„๋ƒ…๋‹ˆ๋‹ค. ์‚ฌ์šฉ ๋„๊ตฌ: Clippy, rustfmt, rust-analyzer.

2๋‹จ๊ณ„: ์˜์กด์„ฑ ๋ฐ ๊ณต๊ธ‰๋ง ๋ณด์•ˆ ํƒ€์‚ฌ ํฌ๋ ˆ์ดํŠธ์—์„œ ์•Œ๋ ค์ง„ ์ทจ์•ฝ์  ๋ฐ ์ •์ฑ… ์œ„๋ฐ˜ ์‚ฌํ•ญ์„ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ ๋„๊ตฌ: cargo-audit, cargo-deny, cargo-auditable.

3๋‹จ๊ณ„: ์‹ฌ์ธต ๊ฒ€์ฆ ์•ˆ์ „ํ•˜์ง€ ์•Š์€ ์ฝ”๋“œ์—์„œ ๋ฉ”๋ชจ๋ฆฌ ์•ˆ์ „์„ฑ ๋ฌธ์ œ๋ฅผ ๋ฐœ๊ฒฌํ•˜๊ณ , ์ •์˜๋˜์ง€ ์•Š์€ ๋™์ž‘์„ ๋ถ„์„ํ•˜๋ฉฐ, ํ•ต์‹ฌ ํ•จ์ˆ˜์˜ ์†์„ฑ์„ ํ˜•์‹์ ์œผ๋กœ ์ฆ๋ช…ํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ ๋„๊ตฌ: Miri, Kani, MIRAI, Rudra, Creusot, Prusti.

์•„๋ž˜ ํ‘œ๋Š” ๊ฐ ์ฃผ์š” ๋„๊ตฌ๋ฅผ ํ•ด๋‹น ๊ณ„์ธต, ๋น„์šฉ, CI ์ ํ•ฉ์„ฑ ๋ฐ ์ฃผ์š” ์‚ฌ์šฉ ์‚ฌ๋ก€์™€ ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค.

์ˆ˜๋‹จ์ธต๋น„์šฉCI ์ ํ•ฉ์ฃผ์š” ์‚ฌ์šฉ ์‚ฌ๋ก€
ํด๋ฆฌ ํ”ผ๋ณดํ’€๋ฌด๋ฃŒ / ์˜คํ”ˆ์†Œ์Šค๊ฐ€๋Šฅ๊ด€์šฉ์ ์ธ ๋ฆฐํŒ…, ์Šคํƒ€์ผ, ์ผ๋ฐ˜์ ์ธ ๋ฒ„๊ทธ
๋Ÿฌ์ŠคํŠธfmt๋ณดํ’€๋ฌด๋ฃŒ / ์˜คํ”ˆ์†Œ์Šค๊ฐ€๋Šฅ์ฝ”๋“œ ์„œ์‹ ๊ฐ•์ œ ์ ์šฉ
๋…น ๋ถ„์„๊ธฐ๋ฆฐํŒ… / DX๋ฌด๋ฃŒ / ์˜คํ”ˆ์†Œ์Šค์ผ๋ถ€์˜IDE ์ง„๋‹จ, ์ธ๋ผ์ธ ๋ถ„์„
ํ™”๋ฌผ ๊ฐ์‚ฌ์ข…์†์„ฑ ๋ณด์•ˆ๋ฌด๋ฃŒ / ์˜คํ”ˆ์†Œ์Šค๊ฐ€๋Šฅํฌ๋ ˆ์ดํŠธ์—์„œ ๋ฐœ๊ฒฌ๋œ ์•Œ๋ ค์ง„ CVE
ํ™”๋ฌผ ๊ฑฐ๋ถ€์ข…์†์„ฑ ๋ณด์•ˆ๋ฌด๋ฃŒ / ์˜คํ”ˆ์†Œ์Šค๊ฐ€๋Šฅ๋ผ์ด์„ ์Šค, ๋ณต์ œ๋ณธ, ๊ถŒ๊ณ ์‚ฌํ•ญ
ํ™”๋ฌผ ๊ฐ์‚ฌ ๊ฐ€๋Šฅ์ข…์†์„ฑ ๋ณด์•ˆ๋ฌด๋ฃŒ / ์˜คํ”ˆ์†Œ์Šค๊ฐ€๋Šฅ๋ฐ”์ด๋„ˆ๋ฆฌ์— ์ข…์†์„ฑ ๋ฐ์ดํ„ฐ๋ฅผ ํฌํ•จ์‹œํ‚ค์„ธ์š”
๋ฏธ๋ฆฌ์‹ฌ์ธต ๊ฒ€์ฆ๋ฌด๋ฃŒ / ์˜คํ”ˆ์†Œ์Šค์„ ํƒ์ ์ธ์•ˆ์ „ํ•˜์ง€ ์•Š์€ ์ฝ”๋“œ์—์„œ ์ •์˜๋˜์ง€ ์•Š์€ ๋™์ž‘์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
์นด๋‹ˆ์‹ฌ์ธต ๊ฒ€์ฆ๋ฌด๋ฃŒ / ์˜คํ”ˆ์†Œ์Šค์„ ํƒ์ ์ธํ˜•์‹ ๊ฒ€์ฆ, ๋ชจ๋ธ ๊ฒ€์ฆ
๋ฏธ๋ผ์ด์‹ฌ์ธต ๊ฒ€์ฆ๋ฌด๋ฃŒ / ์˜คํ”ˆ์†Œ์Šค์„ ํƒ์ ์ธ์ถ”์ƒ ํ•ด์„, ์˜ค์—ผ ๋ถ„์„
๋ฃจ๋“œ๋ผ์‹ฌ์ธต ๊ฒ€์ฆ๋ฌด๋ฃŒ / ์˜คํ”ˆ์†Œ์Šค๋ฆฌ์จ์น˜์•ˆ์ „ํ•˜์ง€ ์•Š์€ Rust ์ฝ”๋“œ์˜ ๋ฉ”๋ชจ๋ฆฌ ์•ˆ์ „์„ฑ ๋ฒ„๊ทธ
์…ˆ๊ทธ๋ ™๊ต์ฐจ ์ ˆ๋‹จ๋ฌด๋ฃŒ ํ‹ฐ์–ด + ์œ ๋ฃŒ ํ‹ฐ์–ด๊ฐ€๋Šฅ๋งž์ถคํ˜• ๋ณด์•ˆ ํŒจํ„ด, ๋‹ค๊ตญ์–ด ์ง€์›
์†Œ๋‚˜ํด๋ผ์šฐ๋“œ๊ต์ฐจ ์ ˆ๋‹จ๋ฌด๋ฃŒ ํ‹ฐ์–ด + ์œ ๋ฃŒ ํ‹ฐ์–ด๊ฐ€๋Šฅ์ง€์†์ ์ธ ํ’ˆ์งˆ ๊ด€๋ฆฌ, ๋Œ€์‹œ๋ณด๋“œ

๋ ˆ์ด์–ด 1: ๋ฆฐํŒ…, ์Šคํƒ€์ผ ๋ฐ ๊ฐœ๋ฐœ์ž ๊ฒฝํ—˜

ํด๋ฆฌ ํ”ผ

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

์„ธ๊ฒŒ ๋•Œ๋ฆฌ๋‹ค

# Run all lints including pedantic and nursery groups
cargo clippy -- -W clippy::all -W clippy::pedantic

# Fail CI on any warning
cargo clippy -- -D warnings

# Check specific lint group
cargo clippy -- -W clippy::correctness -W clippy::suspicious

Clippy์˜ ๋ฆฐํŠธ ์นดํ…Œ๊ณ ๋ฆฌ๋Š” ๋ช…ํ™•ํ•˜๊ฒŒ ์ดํ•ดํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์นดํ…Œ๊ณ ๋ฆฌ ๊ทธ๊ฒƒ์ด ์žก๋Š” ๊ฒƒ
correctness๊ฑฐ์˜ ํ™•์‹คํžˆ ํ‹€๋ฆฐ ์ฝ”๋“œ (ํ•ญ์ƒ ๊ฑฐ๋ถ€)
suspicious์ž˜๋ชป๋˜์—ˆ๊ฑฐ๋‚˜ ๋งค์šฐ ๋†€๋ผ์šด ์ฝ”๋“œ
style๋ช…ํ™•ํ•œ ๊ฐœ์„ ์ ์„ ๋ณด์—ฌ์ฃผ๋Š” ๋น„๊ด€์šฉ์  ํŒจํ„ด
complexity๋ถˆํ•„์š”ํ•˜๊ฒŒ ๋ณต์žกํ•œ ๊ตฌ์กฐ
performance์ปดํŒŒ์ผ์€ ๋˜์ง€๋งŒ ์‹คํ–‰ ์†๋„๊ฐ€ ์˜ˆ์ƒ๋ณด๋‹ค ๋А๋ฆฐ ์ฝ”๋“œ
pedantic์—„๊ฒฉํ•œ ์ง€์นจ, ์ฃผ๊ด€์  ๊ด€์  (์„ ํƒ์ ์œผ๋กœ ํ™œ์„ฑํ™”)
restrictionํŠน์ • ์ƒํ™ฉ์—์„œ ์ ์šฉํ•˜๊ณ  ์‹ถ์€ ๊ทœ์น™
nursery์ƒˆ๋กœ์šด ๋ณดํ‘ธ๋ผ๊ธฐ๋Š” ์˜คํƒ์ง€๋ฅผ ์œ ๋ฐœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ™”๋ฌผ ๊ฒ€์‚ฌ vs ํด๋ฆฌํ”ผ: cargo check ๋ฐ”์ด๋„ˆ๋ฆฌ ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜์ง€ ์•Š๊ณ  ํƒ€์ž… ์ •ํ™•์„ฑ๊ณผ ์ปดํŒŒ์ผ์„ฑ์„ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค. ๋น ๋ฅด๊ณ  ๋นŒ๋“œ ๊ฒ€์ฆ์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค. cargo clippy ์‹คํ–‰ cargo check ๋ชจ๋“  ๋ฆฐํŠธ ๋ถ„์„๋„ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. CI์˜ ๊ฒฝ์šฐ, ๋‹ค์Œ ๋ช…๋ น์„ ์‹คํ–‰ํ•˜์„ธ์š”. cargo check ๋น ๋ฅธ ์ปดํŒŒ์ผ ํ”ผ๋“œ๋ฐฑ์„ ์œ„ํ•ด cargo clippy -- -D warnings ๋ณ„๋„์˜ ํ’ˆ์งˆ ๊ด€๋ฆฌ ์ ˆ์ฐจ์ž…๋‹ˆ๋‹ค. ์„œ๋กœ ํ˜ธํ™˜๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. cargo check ๊ด€์šฉ์ ์ธ ๋ฌธ์ œ๋ฅผ ํฌ์ฐฉํ•˜์ง€ ๋ชปํ•  ๊ฒƒ์ด๋ฉฐ, cargo clippy ๋” ๋А๋ฆฝ๋‹ˆ๋‹ค.

Clippy ์„ค์ •ํ•˜๊ธฐ ๋ฅผ ํ†ตํ•ด clippy.toml ๋˜๋Š” ์ธ๋ผ์ธ ์†์„ฑ์„ ํ†ตํ•ด ํŒ€์€ ๋…ธ์ด์ฆˆ๋ฅผ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ†ฐ

# clippy.toml
avoid-breaking-exported-api = false
msrv = "1.70"

๋…น

// Suppress a lint for one function with documented reason
#[allow(clippy::too_many_arguments)]
fn complex_setup(...) { ... }

Clippy์—์„œ ์ง€์›ํ•˜์ง€ ์•Š๋Š” ๊ธฐ๋Šฅ์€ ๋ชจ๋“ˆ ๊ฐ„ ์‹ฌ์ธต ๋ฐ์ดํ„ฐ ํ๋ฆ„ ๋ถ„์„, ์ข…์†์„ฑ ๋ณด์•ˆ ์ทจ์•ฝ์  ์Šค์บ”, ํ˜•์‹์  ์ •ํ™•์„ฑ ์ฆ๋ช… ๋˜๋Š” ์กฐ์ง๋ณ„ ๋งž์ถค ๊ทœ์น™ ์„ค์ •์ž…๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๊ธฐ๋Šฅ์€ ๋‹ค๋ฅธ ๊ณ„์ธต์˜ ๋„๊ตฌ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

๋Ÿฌ์ŠคํŠธfmt

rustfmt๋Š” ์ฝ”๋“œ๋ฒ ์ด์Šค ์ „์ฒด์— ๊ฑธ์ณ ์ผ๊ด€๋œ ์„œ์‹์„ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค. cargo fmt. ๊ทธ๋งŒํผ rustfmt.toml ์„ค์ • ํŒŒ์ผ์€ ํ”„๋กœ์ ํŠธ ์ „์ฒด์˜ ์Šคํƒ€์ผ ๊ทœ์น™์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. CI ํ™˜๊ฒฝ์—์„œ๋Š” cargo fmt -- --check ํŒŒ์ผ์ด ์žฌํฌ๋งท๋  ๊ฒฝ์šฐ 0์ด ์•„๋‹Œ ์ข…๋ฃŒ ์ฝ”๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฏ€๋กœ ๊ตฌ์„ฑ ์˜ค๋ฒ„ํ—ค๋“œ ์—†์ด ๊น”๋”ํ•œ ํ’ˆ์งˆ ๊ฒ€์‚ฌ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

์„ธ๊ฒŒ ๋•Œ๋ฆฌ๋‹ค

# Check formatting without modifying files (CI mode)
cargo fmt -- --check

# Apply formatting (developer mode)
cargo fmt

Rust ๋ถ„์„๊ธฐ์™€ IDE ํ†ตํ•ฉ

rust-analyzer๋Š” Rust์šฉ ์–ธ์–ด ์„œ๋ฒ„ ํ”„๋กœํ† ์ฝœ(LSP) ๊ตฌํ˜„์ฒด๋กœ, LSP ํ˜ธํ™˜ ํŽธ์ง‘๊ธฐ์—์„œ ์‹ค์‹œ๊ฐ„ ์ง„๋‹จ, ์ฝ”๋“œ ์ž๋™ ์™„์„ฑ, ์ •์˜ ์œ„์น˜๋กœ ์ด๋™, Clippy ๊ฒฝ๊ณ  ํ‘œ์‹œ ๋“ฑ์˜ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๋” ์ด์ƒ ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š” RLS(Rust Language Server)๋ฅผ ๋Œ€์ฒดํ•˜๋ฉฐ, ์ƒˆ๋กœ์šด ํ”„๋กœ์ ํŠธ์—์„œ๋Š” Rust ์–ธ์–ด ์„œ๋ฒ„๋งŒ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

์ •์  ๋ถ„์„ ๊ด€์ ์—์„œ ๋ณด๋ฉด, rust-analyzer๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ์ž…๋ ฅํ•˜๋Š” ๋™์•ˆ Clippy ๋ฆฐํŠธ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ”๋กœ ํ‘œ์‹œํ•˜์—ฌ ๋ณ„๋„์˜ ํ„ฐ๋ฏธ๋„ ์‹คํ–‰ ์—†์ด๋„ ์Šคํƒ€์ผ ๋ฐ ์ •ํ™•์„ฑ ๋ฌธ์ œ์— ๋Œ€ํ•œ ์ฆ‰๊ฐ์ ์ธ ํ”ผ๋“œ๋ฐฑ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

JSON

// VS Code settings.json: enable Clippy via rust-analyzer
{
  "rust-analyzer.check.command": "clippy",
  "rust-analyzer.check.extraArgs": [
    "--", "-W", "clippy::all", "-W", "clippy::pedantic"
  ]
}

rust-analyzer๋Š” ์ถ”๋ก ๋œ ์œ ํ˜•, ๋นŒ๋ฆผ ์ˆ˜๋ช… ๋ฐ ๋งค๊ฐœ๋ณ€์ˆ˜ ์ด๋ฆ„์— ๋Œ€ํ•œ ์ธ๋ ˆ์ด ํžŒํŠธ๋ฅผ ์ œ๊ณตํ•˜๋ฏ€๋กœ ์ •์˜๋กœ ์ด๋™ํ•˜์ง€ ์•Š๊ณ ๋„ ์ต์ˆ™ํ•˜์ง€ ์•Š์€ ์ฝ”๋“œ๋ฅผ ๊ฒ€ํ† ํ•˜๋Š” ๋ฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

2๋‹จ๊ณ„: ์˜์กด์„ฑ ๋ฐ ๊ณต๊ธ‰๋ง ๋ณด์•ˆ

ํ™”๋ฌผ ๊ฐ์‚ฌ

ํ™”๋ฌผ ๊ฐ์‚ฌ ๊ฒ€์‚ฌ๋Š” ๋‹ค์Œ์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. Cargo.lock RustSec Advisory Database์— ๋Œ€ํ•œ ํŒŒ์ผ์„ ๊ฒ€์‚ฌํ•˜์—ฌ ์ง์ ‘ ๋ฐ ๊ฐ„์ ‘ ์ข…์†์„ฑ์—์„œ ์•Œ๋ ค์ง„ CVE๋ฅผ ์‹๋ณ„ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋ชจ๋“  Rust ํ”„๋กœ์ ํŠธ๊ฐ€ CI์—์„œ ์‹คํ–‰ํ•ด์•ผ ํ•˜๋Š” ์ตœ์†Œํ•œ์˜ ์ข…์†์„ฑ ๋ณด์•ˆ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค.

์„ธ๊ฒŒ ๋•Œ๋ฆฌ๋‹ค

# Install
cargo install cargo-audit

# Run audit
cargo audit

# Ignore a specific advisory (document the reason in comments)
cargo audit --ignore RUSTSEC-2024-0001

# JSON output for pipeline integration
cargo audit --json | jq '.vulnerabilities'

cargo-audit๋Š” ์•Œ๋ ค์ง€๊ณ  ๊ณต๊ฐœ๋œ ๋ณด์•ˆ ๊ถŒ๊ณ  ์‚ฌํ•ญ๋งŒ ํƒ์ง€ํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž ์ฝ”๋“œ์˜ ์ทจ์•ฝ์ , RustSec ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์•„์ง ๋“ฑ๋ก๋˜์ง€ ์•Š์€ ๋ฌธ์ œ ๋˜๋Š” ์›์น˜ ์•Š๋Š” ๋ผ์ด์„ ์Šค์™€ ๊ฐ™์€ ์ •์ฑ… ์œ„๋ฐ˜ ์‚ฌํ•ญ์€ ํƒ์ง€ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

ํ™”๋ฌผ ๊ฑฐ๋ถ€

cargo-deny๋Š” ์•Œ๋ ค์ง„ CVE๋ฅผ ๋„˜์–ด ๋ผ์ด์„ ์Šค ์ค€์ˆ˜, ์ค‘๋ณต ํฌ๋ ˆ์ดํŠธ ๊ฐ์ง€, ์‚ฌ์šฉ์ž ์ง€์ • ๊ธˆ์ง€/ํ—ˆ์šฉ ์ •์ฑ…๊นŒ์ง€ ์ข…์†์„ฑ ๊ด€๋ฆฌ๋ฅผ ํ™•์žฅํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๊ทœ์ • ์ค€์ˆ˜ ์š”๊ฑด์ด ์žˆ๋Š” ์กฐ์ง์— ๋”์šฑ ํฌ๊ด„์ ์ธ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค.

ํ†ฐ

# deny.toml
[advisories]
vulnerability = "deny"
unmaintained = "warn"

[licenses]
allow = ["MIT", "Apache-2.0", "ISC", "BSD-2-Clause", "BSD-3-Clause"]
deny = ["GPL-2.0"]
copyleft = "warn"

[bans]
multiple-versions = "warn"

์„ธ๊ฒŒ ๋•Œ๋ฆฌ๋‹ค

cargo install cargo-deny
cargo deny check

ํ™”๋ฌผ ๊ฐ์‚ฌ ๊ฐ€๋Šฅ

cargo-auditable์€ ์ปดํŒŒ์ผ๋œ Rust ๋ฐ”์ด๋„ˆ๋ฆฌ์— ๊ตฌ์กฐํ™”๋œ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ํ˜•ํƒœ๋กœ ์ „์ฒด ์ข…์†์„ฑ ํŠธ๋ฆฌ๋ฅผ ํฌํ•จ์‹œ์ผœ ์ „์šฉ ๋ง์ปค ์„น์…˜์— ๋ฐฐ์น˜ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์†Œ์Šค ์ฝ”๋“œ์— ์ ‘๊ทผํ•˜์ง€ ์•Š๊ณ ๋„ ๋ฐฐํฌ๋œ ๋ฐ”์ด๋„ˆ๋ฆฌ๋ฅผ ๊ฐ์‚ฌํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ๋ฐฐํฌ ํ›„ ๋ณด์•ˆ ๊ฒ€ํ†  ๋ฐ ๊ณต๊ธ‰๋ง ํˆฌ๋ช…์„ฑ ํ™•๋ณด์— ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

์„ธ๊ฒŒ ๋•Œ๋ฆฌ๋‹ค

cargo install cargo-auditable
cargo auditable build --release
# The binary now contains auditable dependency metadata
# Audit a binary directly:
cargo audit bin ./target/release/my-service

3๋‹จ๊ณ„: ์‹ฌ์ธต ๊ฒ€์ฆ

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

Miri: ์ •์˜๋˜์ง€ ์•Š์€ ๋™์ž‘ ๊ฐ์ง€

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

์„ธ๊ฒŒ ๋•Œ๋ฆฌ๋‹ค

# Install Miri (requires nightly)
rustup +nightly component add miri

# Run tests under Miri
cargo +nightly miri test

# Enable strict aliasing validation
MIRIFLAGS="-Zmiri-strict-provenance" cargo +nightly miri test

๋ฏธ๋ฆฌ๊ฐ€ ๊ฐ์ง€ํ•˜๋Š” ๊ฒƒ: ์ •์˜๋˜์ง€ ์•Š์€ ๋™์ž‘ unsafe ๋ธ”๋ก, ๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ ์œ„๋ฐ˜, ํ•ด์ œ ํ›„ ์‚ฌ์šฉ, ์ •๋ ฌ๋˜์ง€ ์•Š์€ ์ ‘๊ทผ, ๋””๋ฒ„๊ทธ ๋นŒ๋“œ์—์„œ์˜ ์ •์ˆ˜ ์˜ค๋ฒ„ํ”Œ๋กœ, ์•ˆ์ „ํ•˜์ง€ ์•Š์€ ๋™์‹œ ์‹คํ–‰ ์ฝ”๋“œ์—์„œ์˜ ๋ฐ์ดํ„ฐ ๊ฒฝ์Ÿ.

๋ฏธ๋ฆฌ๊ฐ€ ๋‹ค๋ฃจ์ง€ ์•Š๋Š” ๋‚ด์šฉ: ๋ฏธ์ •์˜ ๋™์ž‘, ์˜์กด์„ฑ ์ทจ์•ฝ์ , ์ฝ”๋“œ ์Šคํƒ€์ผ ๋˜๋Š” ์„ฑ๋Šฅ ๋ฌธ์ œ๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š๋Š” ์•ˆ์ „ํ•œ ์ฝ”๋“œ ๋‚ด์˜ ๋…ผ๋ฆฌ์  ๋ฒ„๊ทธ.

CI ํ†ตํ•ฉMiri๋Š” 10~50๋ฐฐ ๋А๋ฆฌ๊ฒŒ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. cargo test. ํŠน์ • ๋ชจ๋“ˆ์— ๋Œ€ํ•ด์„œ๋งŒ ์„ ํƒ์ ์œผ๋กœ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. unsafe ์ฝ”๋“œ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๊ฑฐ๋‚˜, ๋งค๋ฒˆ ์ปค๋ฐ‹ํ•  ๋•Œ๋งˆ๋‹ค ์—…๋ฐ์ดํŠธํ•˜๋Š” ๋Œ€์‹  ์•ผ๊ฐ„์— ์—…๋ฐ์ดํŠธํ•˜๋Š” ๊ฒƒ๋„ ๊ณ ๋ คํ•ด ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์–Œ

- name: Miri on unsafe modules
  run: |
    rustup +nightly component add miri
    cargo +nightly miri test --package my-unsafe-crate

Kani: ๋ชจ๋ธ ๊ฒ€์ฆ ๋ฐ ํ˜•์‹ ๊ฒ€์ฆ

Amazon Web Services์—์„œ ๊ฐœ๋ฐœํ•œ Kani๋Š” ์ •์˜๋œ ๋ฒ”์œ„๊นŒ์ง€ ์‹คํ–‰ ๊ฒฝ๋กœ๋ฅผ ์ฒ ์ €ํ•˜๊ฒŒ ํƒ์ƒ‰ํ•˜์—ฌ Rust ์ฝ”๋“œ์˜ ์†์„ฑ์„ ํ˜•์‹์ ์œผ๋กœ ๊ฒ€์ฆํ•˜๋Š” ๋ชจ๋ธ ๊ฒ€์ฆ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค. Miri๊ฐ€ ์‹ค์ œ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ๊ตฌ์ฒด์ ์ธ ๋ฒ„๊ทธ๋ฅผ ์ฐพ๋Š” ๋ฐ˜๋ฉด, Kani๋Š” ๋ถ„์„ ๋ฒ”์œ„ ๋‚ด์˜ ๋ชจ๋“  ์ž…๋ ฅ์— ๋Œ€ํ•ด ์†์„ฑ์ด ์„ฑ๋ฆฝํ•˜๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ์ฆ๋ช…ํ•˜๊ฑฐ๋‚˜ ๋ฐ˜์ฆํ•ฉ๋‹ˆ๋‹ค.

Kani๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๊ฒ€์ฆ ํ•˜๋„ค์Šค๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ์ž…๋ ฅ ๊ณต๊ฐ„๊ณผ ๊ฒ€์ฆํ•  ์†์„ฑ์„ ์ •์˜ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋…น

#[cfg(kani)]
mod verification {
    use super::*;

    #[kani::proof]
    fn verify_add_no_overflow() {
        let a: u32 = kani::any();
        let b: u32 = kani::any();
        if a.checked_add(b).is_some() {
            let result = safe_add(a, b);
            assert!(result == a + b);
        }
    }
}

์„ธ๊ฒŒ ๋•Œ๋ฆฌ๋‹ค

cargo install --locked kani-verifier
cargo kani setup
cargo kani

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

MIRAI: ์ถ”์ƒ ํ•ด์„ ๋ฐ ์˜ค์—ผ ๋ถ„์„

Facebook Research์—์„œ ๊ฐœ๋ฐœํ•œ MIRAI๋Š” ์ถ”์ƒ์ ์ธ ํ•ด์„์„ ์‚ฌ์šฉํ•˜์—ฌ Rust์˜ MIR์„ ๋ถ„์„ํ•ฉ๋‹ˆ๋‹ค. ํ•จ์ˆ˜ ํ˜ธ์ถœ์„ ํ†ตํ•ด ๊ฐ’์ด ์–ด๋–ป๊ฒŒ ํ๋ฅด๋Š”์ง€ ์ถ”์ ํ•˜๋Š” ํ”„๋กœ์‹œ์ € ๊ฐ„ ๋ถ„์„์„ ์ˆ˜ํ–‰ํ•˜์—ฌ ์ž ์žฌ์ ์ธ ํŒจ๋‹‰, ๊ณ„์•ฝ ์œ„๋ฐ˜ ๋ฐ ์ฝ”๋“œ ์ „์ฒด์— ์˜ค์—ผ์ด ์ „ํŒŒ๋˜๋Š” ๊ฒƒ์„ ๊ฐ์ง€ํ•ฉ๋‹ˆ๋‹ค.

๋…น

use mirai_annotations::*;

fn divide(a: i32, b: i32) -> i32 {
    precondition!(b != 0);  // MIRAI verifies all callers satisfy this
    a / b
}

MIRAI๋Š” ์•ผ๊ฐ„์— ๋ฐฐํฌ๋˜๋Š” Rust ์ปดํŒŒ์ผ๋Ÿฌ๋ฅผ ํ•„์š”๋กœ ํ•˜๋ฉฐ ์„ค์ • ๊ณผ์ •์ด ์ƒ๋‹นํžˆ ๋ณต์žกํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ณด์•ˆ ์—”์ง€๋‹ˆ์–ด๋ง ์ „๋‹ดํŒ€์ด๋‚˜ ์—ฐ๊ตฌ ์ค‘์‹ฌ์˜ ํ’ˆ์งˆ ์š”๊ตฌ ์‚ฌํ•ญ์„ ๊ฐ€์ง„ ํŒ€์— ๊ฐ€์žฅ ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.

Rudra: ์•ˆ์ „ํ•˜์ง€ ์•Š์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ฝ”๋“œ์—์„œ์˜ ๋ฉ”๋ชจ๋ฆฌ ์•ˆ์ „์„ฑ

Rudra๋Š” Rust์˜ ์†Œ์œ ๊ถŒ ๋ชจ๋ธ์— ํŠนํ™”๋œ ๋ฉ”๋ชจ๋ฆฌ ์•ˆ์ „์„ฑ ๋ฒ„๊ทธ๋ฅผ ํƒ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ํฌ๋ ˆ์ดํŠธ ์ „๋ฐ˜์— ๊ฑธ์ณ ํ”„๋กœ๊ทธ๋žจ ์ „์ฒด๋ฅผ ๋ถ„์„ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ฒ„๊ทธ์—๋Š” Send/Sync ํŠธ๋ ˆ์ดํŠธ ์•ˆ์ „์„ฑ ์œ„๋ฐ˜, ๋ถˆ์•ˆ์ •ํ•œ ์ˆ˜๋ช… ์—ฐ์žฅ์„ ํ—ˆ์šฉํ•˜๋Š” ๊ณ ์ฐจ ํƒ€์ž… ์ˆ˜๋ช… ๋ฌธ์ œ, ์•ˆ์ „ํ•˜์ง€ ์•Š์€ ์ฝ”๋“œ์˜ ํŒจ๋‹‰ ์•ˆ์ „์„ฑ ๋ฌธ์ œ ๋“ฑ์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. ์›๋ž˜ ์—ฐ๊ตฌ์›๋“ค์ด ๊ฐœ๋ฐœํ•œ Rudra๋Š” ์ปดํŒŒ์ผ๋Ÿฌ ํ”Œ๋Ÿฌ๊ทธ์ธ์œผ๋กœ ์ž‘๋™ํ•˜๋ฉฐ ํŠน์ • ๋‚˜์ดํ‹€๋ฆฌ ๋ฒ„์ „์„ ํ•„์š”๋กœ ํ•ฉ๋‹ˆ๋‹ค. ์•ˆ์ „ํ•˜์ง€ ์•Š์€ ๋‚ด๋ถ€ ๊ตฌ์กฐ๋ฅผ ๊ฐ€์ง„ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํฌ๋ ˆ์ดํŠธ์˜ ๊ฒฝ์šฐ, ๋งค ์ปค๋ฐ‹๋งˆ๋‹ค ์‹คํ–‰ํ•˜๊ธฐ๋ณด๋‹ค๋Š” ์˜ˆ์•ฝ๋œ ์‹œ๊ฐ„์— ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

ํฌ๋ฃจ์†Œ์™€ ํ”„๋ฃจ์Šคํ‹ฐ: ์—ฐ์—ญ์  ๊ฒ€์ฆ

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

์ถ”๊ฐ€๋กœ ํฌํ•จํ•  ๋งŒํ•œ ๋„๊ตฌ

์‚ฌ์šฉ์ž ์ง€์ • ๋ณด์•ˆ ํŒจํ„ด์„ ์œ„ํ•œ Semgrep

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

์–Œ

# Custom rule: flag .unwrap() in production paths
rules:
  - id: no-unwrap-in-production
    pattern: $X.unwrap()
    message: "Use proper error handling instead of .unwrap()"
    languages: [rust]
    severity: WARNING

Semgrep์€ ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ ๊ด€๋ฆฌํ•˜๋Š” Rust ๋ณด์•ˆ ๊ทœ์น™์ด ํฌํ•จ๋œ ๊ด€๋ฆฌํ˜• ๊ทœ์น™ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ๋„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

SonarCloud/SonarQube๋ฅผ ํ™œ์šฉํ•œ ์ง€์†์ ์ธ ํ’ˆ์งˆ ๊ฒŒ์ดํŠธ ํ…Œ์ŠคํŠธ

SonarCloud๋Š” ๋Œ€์‹œ๋ณด๋“œ, ํŠธ๋ Œ๋“œ ์ถ”์ , ํ’€ ๋ฆฌํ€˜์ŠคํŠธ ๋ฐ์ฝ”๋ ˆ์ด์…˜ ๊ธฐ๋Šฅ์„ ํ†ตํ•ด ์ง€์†์ ์ธ ์ฝ”๋“œ ํ’ˆ์งˆ ๋ถ„์„์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. Rust ์ง€์›์„ ํ†ตํ•ด ์ผ๋ฐ˜์ ์ธ ๋ฒ„๊ทธ ํŒจํ„ด, ๋ณด์•ˆ ์ทจ์•ฝ์ , ์ฝ”๋“œ ์Šค๋ฉœ ๋“ฑ์„ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฏธ ๋‹ค๋ฅธ ์–ธ์–ด์— SonarCloud๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ๊ธฐ์—… ํŒ€์€ Rust๋ฅผ ๋™์ผํ•œ ํŒŒ์ดํ”„๋ผ์ธ์— ์ถ”๊ฐ€ํ•˜์—ฌ ์Šคํƒ ์ „๋ฐ˜์— ๊ฑธ์ณ ํ†ตํ•ฉ๋œ ํ’ˆ์งˆ ๊ฐ€์‹œ์„ฑ์„ ํ™•๋ณดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ณ„์ธตํ˜• CI/CD ํŒŒ์ดํ”„๋ผ์ธ ๊ตฌ์ถ•

๋‹ค์Œ GitHub Actions ์›Œํฌํ”Œ๋กœ๋Š” ๊ณผ๋„ํ•œ ์„ค๊ณ„ ์—†์ด ํฌ๊ด„์ ์ธ Rust ํ’ˆ์งˆ ๊ฒ€์ฆ์„ ์›ํ•˜๋Š” ํŒ€์„ ์œ„ํ•œ ์‹ค์šฉ์ ์ธ ์‹œ์ž‘์ ์„ ์ œ์‹œํ•ฉ๋‹ˆ๋‹ค.

์–Œ

# .github/workflows/quality.yml
name: Code Quality and Security

on: [push, pull_request]

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        with:
          components: clippy, rustfmt

      - name: Check formatting
        run: cargo fmt -- --check

      - name: Clippy (treat warnings as errors)
        run: cargo clippy -- -D warnings

  security:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable

      - name: Install security tools
        run: |
          cargo install cargo-audit
          cargo install cargo-deny

      - name: Dependency audit
        run: cargo audit --deny warnings

      - name: License and policy check
        run: cargo deny check

  verify:
    runs-on: ubuntu-latest
    # Scheduled or manually triggered, not on every push
    if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@nightly
        with:
          components: miri

      - name: Miri on unsafe modules
        run: cargo +nightly miri test --package my-unsafe-crate

์–ด๋–ค ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ• ๊นŒ์š”? ๊ฒฐ์ • ๊ฐ€์ด๋“œ

์ƒˆ๋กœ์šด Rust ํ”„๋กœ์ ํŠธ ์‹œ์ž‘ํ•˜๊ธฐClippy + rustfmt + cargo-audit. 5๋ถ„ ์ด๋‚ด์— ์„ค์ • ๊ฐ€๋Šฅํ•˜๋ฉฐ, ํŒ€์—์„œ ํ”ํžˆ ์ ‘ํ•˜๋Š” ๋Œ€๋ถ€๋ถ„์˜ ํ’ˆ์งˆ ๋ฐ ๋ณด์•ˆ ๋ฌธ์ œ๋ฅผ ์žก์•„๋ƒ…๋‹ˆ๋‹ค.

์™ธ๋ถ€ ์ข…์†์„ฑ์ด ์žˆ๋Š” ํ”„๋กœ๋•์…˜ ์„œ๋น„์Šค๋ผ์ด์„ ์Šค ์ค€์ˆ˜ ๋ฐ ๊ณต๊ธ‰๋ง ์ •์ฑ… ์‹œํ–‰์„ ์œ„ํ•ด CVE ์™ธ์—๋„ ํ™”๋ฌผ ๊ฑฐ๋ถ€ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

๋‚ด๋ถ€ ๊ตฌ์กฐ๊ฐ€ ์•ˆ์ „ํ•˜์ง€ ์•Š์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํฌ๋ ˆ์ดํŠธ์•ˆ์ „ํ•˜์ง€ ์•Š์€ ์ฝ”๋“œ๊ฐ€ ํฌํ•จ๋œ ๋ชจ๋“ˆ์— ๋Œ€ํ•ด Miri๋ฅผ ํ…Œ์ŠคํŠธ ์Šค์œ„ํŠธ์— ์ถ”๊ฐ€ํ•˜์„ธ์š”. Rudra๋ฅผ ์˜ˆ์•ฝ๋œ ์‹œ๊ฐ„์— ์‹คํ–‰ํ•˜์„ธ์š”.

์•ˆ์ „ ํ•„์ˆ˜ ์ฝ”๋“œ ๋˜๋Š” ์•”ํ˜ธํ™” ์ฝ”๋“œ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ธฐ๋Šฅ์— ๋Œ€ํ•ด Kani ๊ฒ€์ฆ ๋„๊ตฌ๋ฅผ ์ž‘์„ฑํ•˜์‹ญ์‹œ์˜ค. ํŒ€์— ์ •ํ˜• ๋ฐฉ๋ฒ•๋ก  ์ „๋ฌธ ์ง€์‹์ด ์žˆ๋‹ค๋ฉด Creusot ๋˜๋Š” Prusti๋ฅผ ๊ณ ๋ คํ•ด ๋ณด์‹ญ์‹œ์˜ค.

๋ณด์•ˆ์— ์ค‘์ ์„ ๋‘” ์กฐ์ง: ์กฐ์ง ๋ณด์•ˆ ์ •์ฑ…์— ๋Œ€ํ•œ ์‚ฌ์šฉ์ž ์ง€์ • ๊ทœ์น™์„ ํฌํ•จํ•˜๋Š” Semgrep์„ ์ถ”๊ฐ€ํ•˜๊ณ , ๋ฆด๋ฆฌ์Šค ๋นŒ๋“œ์—์„œ cargo-auditable์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

๋” ํฐ ํŒ€์„ ์œ„ํ•œ ์ง€์†์ ์ธ ๊ฐ€์‹œ์„ฑ ํ™•๋ณดSonarCloud๋Š” ํŠธ๋ Œ๋“œ ์ถ”์ , ํ’€ ๋ฆฌํ€˜์ŠคํŠธ ๊ด€๋ฆฌ ๋ฐ ํ’ˆ์งˆ ๊ด€๋ฆฌ ๊ธฐ๋Šฅ์„ ๋น„๋กฏํ•˜์—ฌ ์˜คํ”ˆ ์†Œ์Šค ๋„๊ตฌ๋“ค์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

๋‹ค๊ตญ์–ด ๊ธฐ์—… ํ™˜๊ฒฝ Rust๊ฐ€ COBOL, Java ๋˜๋Š” ๊ธฐํƒ€ ๋ ˆ๊ฑฐ์‹œ ์–ธ์–ด์™€ ์ƒํ˜ธ ์ž‘์šฉํ•˜๋Š” ๊ฒฝ์šฐ, ๋‹จ์ผ ์–ธ์–ด Rust ๋„๊ตฌ๋Š” ์–ธ์–ด ๊ฒฝ๊ณ„๋ฅผ ๋„˜์–ด ์ƒํ˜ธ ์ž‘์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. SMART TS XL ์ „์ฒด ์‹œ์Šคํ…œ์„ ํฌ๊ด„ํ•˜๋Š” ์–ธ์–ด ๊ฐ„ ๋ถ„์„์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

Rust ์ •์  ๋ถ„์„์ด ์—”ํ„ฐํ”„๋ผ์ด์ฆˆ ์‹œ์Šคํ…œ๊ณผ ๋งŒ๋‚  ๋•Œ

Rust๋Š” COBOL, Java, PL/I, RPG ๋“ฑ์„ ๋ฉ”์ธํ”„๋ ˆ์ž„์ด๋‚˜ ๋ ˆ๊ฑฐ์‹œ ํ”Œ๋žซํผ์—์„œ ์‹คํ–‰ํ•˜๋Š” ์กฐ์ง์—์„œ ์ƒˆ๋กœ์šด ์„œ๋น„์Šค๋ฅผ ๊ฐœ๋ฐœํ•˜๋Š” ๋ฐ ์ ์  ๋” ๋งŽ์ด ์‚ฌ์šฉ๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ํ™˜๊ฒฝ์—์„œ ์ •์  ๋ถ„์„์€ Rust ์ „์šฉ ๋„๊ตฌ๊ฐ€ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๋Š” ๋ฒ”์œ„๋ฅผ ๋„˜์–ด์„ญ๋‹ˆ๋‹ค. Rust ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค๋Š” COBOL ํ”„๋กœ๊ทธ๋žจ์„ ํ˜ธ์ถœํ•˜๊ฑฐ๋‚˜, ๊ณต์œ  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ฐ์ดํ„ฐ๋ฅผ ์“ฐ๊ฑฐ๋‚˜, ๋ ˆ๊ฑฐ์‹œ ๋ฐฐ์น˜ ์‹œ์Šคํ…œ์—์„œ ์ƒ์„ฑ๋œ ์ด๋ฒคํŠธ๋ฅผ ์†Œ๋น„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ธฐ์—… ์•„ํ‚คํ…ํŠธ์—๊ฒŒ ์ค‘์š”ํ•œ ํ’ˆ์งˆ ๋ฐ ์ข…์†์„ฑ ๋ถ„์„์€ ์ด๋Ÿฌํ•œ ๋ชจ๋“  ์‹œ์Šคํ…œ์„ ๋™์‹œ์— ์•„์šฐ๋ฅด๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

SMART TS XL Clippy์™€ cargo-audit์€ Rust๋งŒ ์ธ์‹ํ•˜๋Š” ๋ฐ˜๋ฉด, Cargo-audit์€ ์ „์ฒด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํฌํŠธํด๋ฆฌ์˜ค์— ๊ฑธ์ณ ์–ธ์–ด ๊ฐ„ ์ข…์†์„ฑ ๋ถ„์„์„ ์ œ๊ณตํ•˜์—ฌ ์ด๋Ÿฌํ•œ ๊ฒฉ์ฐจ๋ฅผ ํ•ด์†Œํ•ฉ๋‹ˆ๋‹ค. SMART TS XL Rust ์„œ๋น„์Šค๊ฐ€ ๊ณต์œ  ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ, ๋ ˆ๊ฑฐ์‹œ ํ”„๋กœ๊ทธ๋žจ ๋ฐ ์—”ํ„ฐํ”„๋ผ์ด์ฆˆ API์— ์–ด๋–ป๊ฒŒ ์˜์กดํ•˜๋Š”์ง€, ๊ทธ๋ฆฌ๊ณ  ์ด๋Ÿฌํ•œ ์˜์กด์„ฑ์„ ๋ณ€๊ฒฝํ•  ๊ฒฝ์šฐ ์–ด๋–ค ์˜ํ–ฅ์„ ๋ฏธ์น ์ง€ ํŒŒ์•…ํ•˜๋Š” ๋ฐ ์œ ์šฉํ•œ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ Rust ์„œ๋น„์Šค๋Š” ์ด๋Ÿฌํ•œ ์ข…์†์„ฑ ๋ถ„์„์— ํŠนํžˆ ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค. ์˜ํ–ฅ ๋ถ„์„ ๊ธฐ์กด ์‹œ์Šคํ…œ ํ˜„๋Œ€ํ™” ๊ณ„ํš Rust๊ฐ€ ์—ฌ๋Ÿฌ ์–ธ์–ด ์ค‘ ํ•˜๋‚˜๋กœ ์‚ฌ์šฉ๋˜๋Š” ํ™˜๊ฒฝ์—์„œ.

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

๊ณ„์ธต์  ์ ‘๊ทผ ๋ฐฉ์‹์ด ํ•ต์‹ฌ์ž…๋‹ˆ๋‹ค.

Rust์—์„œ์˜ ์ •์  ๋ถ„์„์€ ๋‹จ ํ•˜๋‚˜์˜ ๋„๊ตฌ ์„ ํƒ์œผ๋กœ ๊ฒฐ์ •๋˜๋Š” ๊ฒƒ์ด ์•„๋‹™๋‹ˆ๋‹ค. ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ๋ฌด๋ฃŒ๋กœ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜์—ฌ ์ฝ”๋“œ์˜ ์œ„ํ—˜ ํ”„๋กœํ•„์— ๋”ฐ๋ผ ํ™•์žฅํ•ด ๋‚˜๊ฐ€๋Š” ๊ณ„์ธต์ ์ธ ์ ‘๊ทผ ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. Clippy์™€ rustfmt๋Š” ์ตœ์†Œํ•œ์˜ ๋„๊ตฌ์ด๋ฉฐ, ์™ธ๋ถ€ ์˜์กด์„ฑ์ด ์žˆ๋Š” ํ”„๋กœ์ ํŠธ๋ผ๋ฉด cargo-audit์€ ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค. Miri๋Š” ์•ˆ์ „ํ•˜์ง€ ์•Š์€ ์ฝ”๋“œ๊ฐ€ ์žˆ๋Š” ํ”„๋กœ์ ํŠธ์— ๋ฐ˜๋“œ์‹œ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. Kani์™€ ๊ฐ™์€ ํ˜•์‹ ๊ฒ€์ฆ ๋„๊ตฌ๋Š” ์˜ค๋ฅ˜๊ฐ€ ์ ˆ๋Œ€ ์šฉ๋‚ฉ๋  ์ˆ˜ ์—†๋Š” ํ•จ์ˆ˜์— ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ๋ฐฉ์‹์„ ์ œ๋Œ€๋กœ ์ดํ•ดํ•˜๋Š” ํŒ€์€ ์ •์  ๋ถ„์„์„ ๊ฐœ๋ฐœ ๋ฃจํ”„์— ํ†ตํ•ฉํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์—๋””ํ„ฐ์— Clippy๋ฅผ ์ธ๋ผ์ธ์œผ๋กœ ์‚ฌ์šฉํ•˜๊ณ , ๋ชจ๋“  CI ์‹คํ–‰์— cargo-audit์„ ํฌํ•จ์‹œํ‚ค๋ฉฐ, ํ…Œ์ŠคํŠธ๋งŒ์œผ๋กœ๋Š” ์žก์•„๋‚ผ ์ˆ˜ ์—†๋Š” ์˜ค๋ฅ˜๋ฅผ ํฌ์ฐฉํ•˜๋Š” ์•ผ๊ฐ„ ์ž‘์—…์— Miri๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ๊ฒฐ๊ณผ, ๋ฒ„๊ทธ ์ˆ˜๊ฐ€ ์ค„์–ด๋“œ๋Š” ๊ฒƒ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ, ๊ฐœ๋ฐœ ํ™˜๊ฒฝ๊ณผ ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ ์‚ฌ์ด์— ์žˆ๋Š” ๋ถ„์„ ๊ณ„์ธต์ด ์ œ๋Œ€๋กœ ์ž‘๋™ํ•˜๊ณ  ์žˆ๋‹ค๋Š” ํ™•์‹ ์„ ๋ฐ”ํƒ•์œผ๋กœ ํŒ€์ด ์‹ ์†ํ•˜๊ฒŒ ๋ณ€๊ฒฝ ์ž‘์—…์„ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.