TechFeedTechFeed
Programming Languages

Rust 2024 에디션 주요 변경점 정리 — gen 키워드, unsafe 강화, RPIT

Rust 에디션 시스템, 2024 에디션 핵심 변경점(gen 예약어, unsafe_op_in_unsafe_fn, RPIT lifetime capture), cargo fix 마이그레이션.

한 줄 요약: Rust 2024 에디션은 unsafe 코드 규칙 강화, 새로운 키워드 예약, lifetime capture 규칙 변경 등을 포함하며 cargo fix --edition 한 명령으로 대부분 자동 마이그레이션된다.

이 글이 필요한 사람:

  • Rust 2021 이하 에디션을 사용 중이고 2024로 업그레이드를 검토하는 개발자
  • unsafe 블록을 자주 쓰는 시스템 프로그래밍 팀
  • Rust 에디션 시스템이 어떻게 동작하는지 이해하고 싶은 사람
  • 마이그레이션 전에 breaking change 범위를 미리 파악하려는 팀 리드

Rust 에디션 시스템이란 무엇인가

Rust는 하위 호환성을 언어 보증으로 제공한다. 하지만 언어가 발전하면서 이전 결정을 수정해야 할 때가 있다. 이 긴장을 해소하는 메커니즘이 에디션(Edition)이다.

에디션은 opt-in 방식의 breaking change 묶음이다. Cargo.tomledition 필드로 선택하며, 다른 에디션의 크레이트와 동일 바이너리로 링크할 수 있다. 즉, 내 크레이트를 2024로 올려도 의존하는 라이브러리가 2021을 유지해도 무관하다.

  • 2015: Rust 첫 안정 릴리즈 에디션 (기본값)
  • 2018: 모듈 시스템 개편, async/await 준비, extern crate 불필요
  • 2021: 클로저 캡처 규칙 개선, IntoIterator for arrays, prelude 업데이트
  • 2024: unsafe 규칙 강화, gen 키워드 예약, lifetime capture 변경 등

에디션은 3년 주기를 목표로 릴리즈된다. 2024 에디션은 Rust 1.85(2025년 2월)에서 안정화됐다.

2024 에디션 주요 변경점

공식 에디션 가이드(doc.rust-lang.org/edition-guide/rust-2024/)에 정리된 변경점 중 실무 영향이 큰 항목을 분석한다.

1. unsafe_op_in_unsafe_fn — 경고에서 에러로

2021까지는 unsafe fn 내부에서 unsafe 연산을 할 때 별도 unsafe { } 블록 없이 허용됐다. 2024부터는 unsafe fn이라도 내부에서 unsafe 연산을 쓸 때 반드시 unsafe { } 블록으로 감싸야 한다.

unsafe_op_in_unsafe_fn 변경 예시
// 2021 에디션: 컴파일 통과 unsafe fn old_style(ptr: *const u8) -> u8 { *ptr // unsafe 블록 없이 허용됨 } // 2024 에디션: 컴파일 에러 → unsafe 블록 필수 unsafe fn new_style(ptr: *const u8) -> u8 { unsafe { *ptr } // 명시적 unsafe 블록 필요 }

이 변경의 의도는 unsafe의 범위를 최소화하는 것이다. unsafe fn을 호출하는 것과 unsafe 연산을 수행하는 것을 구분해, 어떤 코드가 실제로 위험한지 명확하게 표시할 수 있다.

2. gen 키워드 예약

gen이 예약 키워드가 됐다. 현재는 experimental한 제너레이터 문법을 위한 자리 예약이며, 아직 안정화된 기능이 아니다. 변수명이나 함수명으로 gen을 사용하던 코드는 r#gen raw identifier로 바꾸거나 이름을 변경해야 한다.

gen 키워드 충돌 처리
// 2024 에디션에서 gen은 예약어 // 기존 코드가 gen을 식별자로 쓴 경우 // 방법 1: raw identifier 사용 (임시 호환) let r#gen = 42; println!("{}", r#gen); // 방법 2: 이름 변경 (권장) let generator_id = 42; println!("{}", generator_id);

실무 영향: gen을 식별자로 쓰는 코드가 있다면 cargo fix가 자동으로 r#gen으로 변환해준다. 이후 팀이 적절한 시점에 이름을 변경하면 된다.

3. RPIT(Return Position Impl Trait) Lifetime Capture 규칙 변경

2024 이전에는 impl Trait을 반환 위치에 쓸 때 lifetime 캡처 규칙이 직관적이지 않았다. 2024부터 impl Trait은 스코프 내 모든 제네릭 파라미터(lifetime 포함)를 기본으로 캡처한다.

RPIT lifetime capture 변경 예시
// 2021: lifetime 'a가 캡처되지 않을 수 있어 컴파일러가 오해할 수 있음 fn process<'a>(data: &'a str) -> impl Iterator<Item = &'a str> { data.split_whitespace() } // 2024: 명시적 캡처 (+ use<'a> 구문으로 정밀 제어 가능) fn process<'a>(data: &'a str) -> impl Iterator<Item = &'a str> + use<'a> { data.split_whitespace() } // 2024 기본: 모든 lifetime을 암묵적으로 캡처 // 캡처를 제한하려면 + use<> 명시 fn no_capture<'a>(data: &'a str) -> impl Iterator<Item = char> + use<> { data.chars() }
+ use<> 구문: 2024 에디션에서 새로 도입된 캡처 경계 지정 구문이다. use<'a, T>처럼 캡처할 파라미터를 명시하거나 use<>로 아무것도 캡처하지 않게 선언할 수 있다. lifetime 관련 컴파일 에러 디버깅 시 이 구문을 먼저 확인하라.

4. Tail Expression Temporary Scope 변경

함수나 블록의 마지막 표현식(tail expression)에서 생성되는 임시 값의 생존 범위가 변경됐다. 2021까지는 임시 값이 함수 전체 스코프까지 살아있었지만, 2024부터는 해당 표현식 스코프로 줄어든다. 이는 불필요하게 긴 borrow를 방지하고 더 직관적인 동작을 제공한다.

Tail Expression Temporary Scope 예시
// 2021: 아래 코드에서 tmp_ref가 함수 끝까지 살아있어 // 동일 스코프에서 가변 참조 획득 불가 let mut v = vec![1, 2, 3]; let len = v.iter().count(); // iterator temporary가 오래 살아있을 수 있음 v.push(4); // 2021에서 간혹 borrow checker 에러 발생 println!("{}", len); // 2024: 임시 값 범위가 좁아져 더 자연스럽게 동작 // 위 코드가 에러 없이 컴파일됨

cargo fix로 마이그레이션하는 방법

공식 마이그레이션 경로는 cargo fix --edition이다. 대부분의 변경점은 자동 변환이 가능하며, 수동 처리가 필요한 부분은 컴파일러가 명확한 메시지로 안내한다.

2024 에디션 마이그레이션 단계
# 1단계: 현재 에디션에서 모든 경고 수정 (clean 상태로 시작) cargo fix # 2단계: 2024 에디션 전환 (자동 코드 수정 포함) cargo fix --edition # 3단계: Cargo.toml 에디션 필드 수동 업데이트 # [package] # edition = "2024" # 4단계: 전체 빌드 및 테스트 cargo build cargo test # 5단계: Clippy로 추가 개선점 확인 cargo clippy -- -W clippy::all

워크스페이스(여러 크레이트)가 있는 경우 각 크레이트별로 독립적으로 마이그레이션할 수 있다. 의존성 트리 아래부터 순서대로 올리는 것을 권장한다.

워크스페이스 마이그레이션
# 특정 패키지만 마이그레이션 cargo fix --edition --package my-lib # 워크스페이스 전체 한 번에 cargo fix --edition --workspace # 마이그레이션 전 dry-run으로 변경 미리 확인 cargo fix --edition --dry-run 2>&1 | head -50
Rust 버전 요구사항: 2024 에디션은 Rust 1.85 이상이 필요하다. rustup update stable로 최신 안정 버전으로 업데이트하고 rustc --version으로 확인한 뒤 마이그레이션을 시작하라.

실무 영향 분석 — 어떤 코드가 영향을 받나

변경점이 실제로 영향을 주는 코드 패턴과 그렇지 않은 경우를 구분해 정리한다.

FFI 코드가 많은 크레이트: unsafe fn을 많이 쓰는 C 바인딩, 시스템 콜 래퍼 코드에서 unsafe_op_in_unsafe_fn 변경이 가장 많은 수동 검토를 요구한다. cargo fix가 자동으로 unsafe 블록을 추가하지만, 추가된 블록의 범위가 의도와 맞는지 확인하는 것이 권장된다.

async Rust 코드: RPIT lifetime capture 변경이 async 함수의 반환 타입에 영향을 줄 수 있다. 특히 async fn-> impl Future로 desugaring해서 쓰는 패턴에서 lifetime 에러가 발생할 수 있다.

대부분의 애플리케이션 코드: unsafe를 직접 쓰지 않고 gen을 식별자로 사용하지 않는다면 마이그레이션 비용이 매우 낮다. cargo fix --edition 한 번으로 완료되는 경우가 많다.

언제 마이그레이션해야 하나

2024 에디션으로 즉시 마이그레이션하지 않아도 기존 코드는 계속 동작한다. 에디션은 강제 업그레이드가 아니다. 다음 기준으로 마이그레이션 시점을 결정하라.

에디션 마이그레이션은 crates.io 생태계 전체가 점진적으로 전환하는 과정이다. 주요 의존성이 2024 에디션을 지원하는지 확인하려면 각 크레이트의 Cargo.toml에서 rust-version 필드를 참고하라.

Rust2024 에디션cargo fixunsafeRPIT프로그래밍 언어

관련 포스트

Rust vs Go — 2026년 백엔드 언어 선택 가이드2026-03-17웹 개발자를 위한 Rust 입문2026-02-28Go로 마이크로서비스 구축하기2026-03-01Python 3.13 새 기능 총정리2026-03-08