"borrow checker랑 싸워서 이길 필요는 없어. command 하나만 내보내면 돼. 그 둘은 아주 다른 목표야."
이 다섯 개면 일이 돼
Rust의 아주 작은 조각만 알아도 쓸 만한 Tauri command를 짤 수 있어. 그 조각이 이거야:
- 소유권이랑 빌림. 값마다 주인은 딱 하나야. 값을 넘기면 이동(move)해서 예전 이름으론 더 못 쓰고, 아니면 참조로 빌려줘. 읽기만 할 땐
&T, 고칠 땐&mut T. 컴파일러가 이걸 강제하니까 use-after-free나 데이터 레이스가 아예 안 생겨. command는 대부분 소유한 인자를 받아서 소유한 값을 돌려주니 제일 단순한 경우에 해당해. - null이 없어 —
Option<T>. 없을 수도 있는 값은Some(x)아니면None이야. 컴파일러가None인 경우를 반드시 처리하게 만들어서, Rust 프로그램엔 null 포인터 때문에 놀랄 일이 없어. - 예외가 없어 —
Result<T, E>. 실패할 수 있는 연산은Ok(value)아니면Err(error)를 돌려줘. 네 command가 돌려줄 타입이 이거고, resolve된 Promise랑 reject된 Promise에 그대로 대응돼. - struct랑 derive.
struct가 네 데이터의 모양이고,#[derive(Serialize, Deserialize)]가 그걸 다리 너머로 보낼 코드를 알아서 만들어줘. - String이랑 &str.
String은 소유하고 늘어나는 문자열,&str은 빌려서 들여다보는 창이야. command 인자로String을 받으면 lifetime을 아예 안 따져도 돼.
컴파일러는 깐깐한 과외선생이지 적이 아냐
Rust 에러 메시지는 유난히 좋아 — 어떻게 고치라고 정확히 짚어줄 때가 많거든. borrow checker가 투덜대면 진짜 버그 부류(허공을 가리키는 참조, 레이스)를 태어나기 전에 잡아주는 거야. 빨간 줄을 공짜 시니어 리뷰어라고 생각해. ? 연산자도 여기서 네 편이야. Ok면 알맹이를 꺼내고 Err면 바로 반환해서, 길게 늘어질 에러 처리를 글자 하나로 줄여줘.
더 깊이 가고 싶어지면
이건 숙달이 아니라 생존이야, 일부러. trait, lifetime, 제네릭, iterator, async의 속사정 — 그건 언어 하나를 제대로 배우는 만큼의 분량이고 /cwk-quests/rust-quest에 자기 퀘스트가 따로 있어. 첫 command 열 개를 엮는 덴 그중 하나도 필요 없어. 먼저 만들고, 깊이는 나중에.