본문으로 건너뛰기

안동민 개발노트

본문 시작

E - 에디션

Rust 에디션이 언어 변화를 선택적으로 적용하면서 크레이트 간 호환성을 유지하는 방식과 마이그레이션 절차를 이해합니다.

러스트를 오래 사용할수록 버전이 올라가면 내 코드는 어떻게 되지?라는 질문을 자주 하게 됩니다.

에디션 개념은 이 질문에 답하기 위해 만들어진 러스트의 핵심 호환성 전략입니다.

초보 단계에서는 버전 번호처럼 보일 수 있지만, 실제로는 팀 전체의 마이그레이션 비용과 도구 호환성을 결정하는 기준입니다.

이 절을 통해 에디션을 릴리즈 주기와 함께 이해하면 업그레이드 의사결정을 더 안정적으로 내릴 수 있습니다.

특히 프로젝트마다 에디션을 명시적으로 고정해 두면 새 팀원이 합류했을 때 환경 차이로 인한 혼선을 줄일 수 있습니다.

또한 cargo fix 같은 보조 도구를 병행하면 에디션 전환 과정의 수작업 부담을 크게 줄일 수 있습니다.

결국 에디션 전략은 기술 선택이 아니라 유지보수 전략의 일부라는 관점으로 보는 것이 중요합니다.

rustc와 toolchain 릴리스 축, 각 크레이트의 언어·표준 라이브러리 해석을 고르는 edition 축, edition에 연동되는 Cargo resolver와 rustfmt style 축, 서로 다른 지원 에디션의 크레이트가 같은 의존성 그래프에서 링크되는 결과를 비교한 표와 모바일 카드

Rust · edition · two-axis matrix

도구의 버전과 소스를 읽는 규칙은 따로 선택된다

toolchain을 올리는 일은 compiler 릴리스를 바꾸고, edition은 크레이트별 언어 호환성 모드를 고릅니다. edition은 parser 설정에 그치지 않고 이름·메서드 해석, closure capture, prelude 같은 동작과 Cargo resolver·rustfmt style 기본값에도 연결됩니다. 지원 범위 안에서는 서로 다른 edition 크레이트를 함께 링크할 수 있습니다.

toolchain 버전 축 × 크레이트별 edition 축
개념 축선택 위치와 현재 값바꾸는 것독립적으로 남는 것
toolchain · rustc 1.xrustup, CI image 또는 rust-toolchain.toml로 compiler 릴리스를 선택그 릴리스에 안정화된 기능과 진단, 수정, code generation과 target 지원을 사용Cargo.toml의 edition 값을 자동으로 바꾸지 않음. 해당 rustc 릴리스 전에 존재한 에디션을 지원
crate · edition각 package의 Cargo.toml2015 | 2018 | 2021 | 2024를 선언키워드와 경로, prelude와 메서드 해석, closure capture와 drop 같은 언어와 표준 라이브러리 호환 동작을 선택사용할 rustc 릴리스나 의존 크레이트의 edition을 고정하지 않음. 예: 배열 .into_iter() 해석은 2021부터 달라짐
edition 연동 도구최상위 2021/2024 package의 기본 Cargo resolver는 각각 2/3. cargo fmt는 package edition을 style 기본값으로 사용workspace 의존성 선택과 formatting 출력이 달라질 수 있음resolver는 workspace 전역이며 명시값이 기본값을 덮어씀. style_edition으로 formatting 전환을 따로 고정 가능
빌드 그래프의 결합Cargo가 각 크레이트에 알맞은 edition을 전달하고 최상위 workspace resolver로 같은 의존성 그래프를 조율각 소스는 자신의 edition 규칙으로 compiler 내부 표현까지 번역됨지원 에디션이 다른 크레이트도 링크·호출 가능. 전체 그래프의 edition을 한 번에 맞출 필요 없음
toolchain axis

rustc 1.x · compiler 릴리스

rustup, CI image나 rust-toolchain.toml로 고릅니다. 안정 기능과 진단, codegen, target 지원이 달라지지만 manifest의 edition은 자동 변경되지 않습니다. Rust 2024 크레이트에는 rustc와 Cargo 1.85+가 필요합니다.

source axis

Cargo.toml edition · 크레이트 해석 규칙

package마다 2015, 2018, 2021, 2024 중 하나를 선언합니다. 구문뿐 아니라 이름과 메서드 해석, prelude, closure capture와 drop 같은 언어와 표준 라이브러리 동작을 고릅니다.

linked tools

resolver와 formatting 기본값도 확인한다

최상위 2021/2024 package의 기본 resolver는 각각 2/3입니다. resolver는 workspace 전역이고 명시값이 우선합니다. cargo fmt는 package edition을 따르지만 style_edition으로 출력 전환을 분리할 수 있습니다.

mixed graph

지원되는 서로 다른 에디션은 함께 링크된다

Cargo가 각 크레이트의 edition을 compiler에 전달하고 최상위 workspace resolver로 그래프를 고릅니다. 각 소스는 자신의 규칙으로 번역되므로 전체 의존성 그래프를 같은 edition으로 동시에 옮길 필요가 없습니다.

현재 에디션 기준

Rust 에디션은 현재 2015·2018·2021·2024 네 가지입니다. Rust 2024는 Rust 1.85에서 안정화되었고, 공식 Rust Book의 현재 본문도 2024 edition을 사용합니다.

명시하지 않았을 때

기존 manifest에 edition 키가 없으면 역호환을 위해 2015가 적용됩니다. 현재 Cargo가 새로 만드는 프로젝트는 기본적으로 최신 안정 에디션인 2024를 선언합니다.

새 edition을 이해하지 못하는 오래된 compiler로 그 크레이트를 빌드할 수는 없습니다. 반대로 최신 toolchain만 쓴다고 기존 크레이트가 자동 전환되지는 않습니다. edition 전환 때는 resolver·Cargo.lock과 rustfmt style diff도 별도로 검증합니다.


부록 E - 에디션

1장에서 cargo new 명령이 Cargo.toml 파일에 에디션에 대한 메타데이터를 추가하는 것을 보았습니다.

이 부록에서는 그것이 무엇을 의미하는지에 대해 설명합니다!

러스트 언어와 컴파일러의 릴리즈 주기는 6주이며, 이는 사용자들에게 지속적으로 새로운 기능을 제공함을 의미합니다.

다른 프로그래밍 언어는 더 낮은 빈도로 큰 변경을 배포합니다; 러스트는 더 자주 작은 업데이트를 배포합니다.

어느 순간부터는 이러한 작은 변경들이 합쳐집니다.

하지만 릴리즈마다 돌아보면서 ‘와, 러스트 1.10과 러스트 1.31 사이에 러스트가 많이 바뀌었구나!’라고 말하기는 어려울 수 있습니다.

매 2년 혹은 3년마다, 러스트 팀은 새로운 러스트 에디션을 출시합니다.

각 에디션은 완전히 업데이트된 문서 및 도구가 포함된 깨끗한 패키지로 출시되는 기능을 제공합니다.

새로운 에디션은 일반적인 6주간의 릴리즈 프로세스의 일부로 출시됩니다.

에디션은 여러 사람에게 여러 목적을 제공합니다.

  • 기존 러스트 사용자의 경우, 새 에디션은 점진적인 변경 사항을 이해하기 쉬운 패키지로 통합하여 제공합니다.
  • 비사용자의 경우, 새 에디션은 몇 가지 주요 개선 사항이 적용되었음을 알리는 신호이며, 이는 러스트를 다시 한번 살펴볼 가치가 있게 합니다.
  • 러스트를 개발하는 사람들에게는 새 에디션이 프로젝트 전체를 위한 결집점을 제공합니다.

현재 사용할 수 있는 러스트 에디션은 Rust 2015, Rust 2018, Rust 2021, Rust 2024의 네 가지입니다.

현재 공식 Rust Book은 Rust 2024 에디션 관용구를 기준으로 설명합니다.

Cargo.tomledition 키는 컴파일러가 코드를 컴파일할 때 사용할 에디션을 나타냅니다.

이 키가 존재하지 않으면, 러스트는 역호환성을 위해 2015를 에디션 값으로 사용합니다.

기존 manifest는 기본 2015 에디션이 아닌 다른 에디션을 명시적으로 채택할 수 있으며, 현재 Cargo가 새로 만드는 프로젝트는 기본적으로 최신 안정 에디션인 2024를 선언합니다.

에디션은 코드에서 식별자와 충돌하는 새 키워드를 포함하는 등 호환되지 않는 변경 사항을 포함할 수 있습니다.

하지만, 그러한 변경 사항을 채택하지 않는다면, 코드는 러스트 컴파일러 버전을 업그레이드하더라도 계속해서 컴파일될 것입니다.

에디션은 초기 구문 분석만 바꾸는 스위치가 아닙니다. 크레이트별 언어·표준 라이브러리 해석 경계를 선택하므로 keyword와 path뿐 아니라 prelude와 method resolution, closure capture와 drop·auto-trait 동작처럼 실행 의미에 닿는 차이도 포함할 수 있습니다.

예를 들어 Rust 2021에서는 closure가 필요한 field만 정밀하게 capture하여 drop 시점이나 Send·Clone 구현 여부가 달라질 수 있고, array의 .into_iter()가 참조가 아니라 owned element를 내놓도록 method call 해석이 바뀝니다. 같은 에디션은 TryInto 같은 standard prelude 추가도 선택합니다.

Cargo와 rustfmt도 에디션에 연동된 기본값을 가질 수 있지만 적용 단위는 다릅니다. top-level package의 Rust 2021은 Cargo resolver 2를, Rust 2024는 resolver 3을 기본으로 선택하며 resolver는 workspace 전체에 적용되고 dependency manifest의 값은 무시됩니다. virtual workspace에서는 [workspace]resolver를 명시해야 합니다.

cargo fmt는 package edition에 대응하는 style edition을 기본으로 사용하지만, rustfmt.tomlstyle_edition으로 formatting 전환을 언어 에디션과 분리할 수 있습니다.

각 러스트 compiler 릴리즈는 그 릴리즈 이전에 존재했던 모든 에디션을 지원하며, 그 compiler가 지원하는 에디션의 크레이트를 서로 링크할 수 있습니다. Rust 2024를 사용하려면 이 에디션이 안정화된 Rust 1.85 이상의 compiler와 Cargo가 필요합니다.

따라서 러스트 2015를 사용 중이고 종속성 중 하나가 러스트 2018을 사용하는 경우도, 프로젝트가 러스트 2024이고 종속성이 Rust 2021인 경우도 지원 toolchain 안에서는 함께 컴파일하고 링크할 수 있습니다.

에디션은 전체 workspace에 하나만 강제되는 값이 아닙니다. Cargo는 빌드 그래프의 각 크레이트에 해당 manifest의 에디션을 적용하므로, 크레이트는 서로의 전환 시점을 막지 않고 독립적으로 이동할 수 있습니다.

명확히 말씀드리자면, 대부분의 기능은 모든 버전에서 사용할 수 있습니다.

모든 러스트 에디션을 사용하는 개발자는 새로운 안정 버전이 출시되면 계속해서 개선 사항을 확인할 수 있습니다.

그러나 몇몇 경우, 주로 새로운 키워드가 추가될 경우에 일부 새로운 기능은 이후 버전에서만 사용 가능할 수도 있습니다.

이러한 기능을 활용하려면 에디션을 전환해야 합니다.

더 자세한 내용은 에디션 간의 차이점을 열거하고 cargo fix를 통해 코드를 새 에디션으로 자동 업그레이드하는 방법을 설명하는 에디션에 대한 전체 책자인 에디션 가이드를 참조하세요.


에디션은 언어 전체를 갈아엎는 버전이 아니라, 기존 코드를 지키면서 크레이트의 언어·표준 라이브러리 해석과 연동 도구의 기본값을 선택하는 경계입니다.

에디션 전환을 결정할 때는 compiler 업데이트와 에디션 변경을 별도 작업으로 분리해야 합니다.

Rust 2024로 전환하기 전에는 개발 환경과 CI가 Rust 1.85 이상인지 확인하고, 지원 정책에 맞춰 rust-version도 검토합니다. 현재 compiler·crate별 edition·workspace resolver·lockfile·rustfmt style edition·target/feature별 테스트를 기준선으로 남기면 toolchain 변경과 edition 변경의 diff를 분리할 수 있습니다.

공식 Edition Guide의 기본 순서처럼 의존성 갱신을 별도 diff로 확인하고 cargo fix --edition을 실행한 뒤, 자동 수정이 다루지 못한 경고·macro·doctest·generated code·조건부 코드를 수동으로 검토합니다.

이 명령은 기본적으로 선택된 package의 모든 Cargo target을 검사하지만, 활성화된 feature와 현재 target platform의 cfg에서 보이는 코드만 수정합니다. 필요하면 --all-features와 다른 --target을 사용해 구성을 나누어 반복해야 합니다.

그 다음 Cargo.tomledition 값을 바꿉니다. top-level non-virtual package에서 Rust 2024가 암시하는 resolver 3과 virtual workspace의 명시적 [workspace] resolver = "3" 여부를 확인하고, dependency resolution을 다시 수행했다면 Cargo.lock 차이를 검토합니다.

마지막으로 cargo fmt가 선택하는 Rust 2024 style edition의 formatting diff를 동작 변경과 분리해 검토하고, editor와 CI가 같은 정책을 쓰도록 필요하면 style_edition = "2024"를 명시합니다. build, test, CI의 target·feature 조합과 mixed-edition dependency graph를 모두 검증한 뒤 팀 기준선을 갱신합니다.

compiler·crate edition·workspace resolver·lockfile·rustfmt style 기준을 기록하고 toolchain-only 업데이트와 edition 마이그레이션을 분기한 뒤, Rust 1.85 이상에서 자동 수정과 manifest·resolver·format diff를 검토하고 테스트·CI·의존성을 검증해 팀 기준선에 반영하는 흐름

Rust · edition migration · flowchart

compiler 업데이트와 edition 전환을 한 diff로 섞지 않는다

현재 기준선을 기록한 뒤 toolchain-only와 edition migration 경로를 분기합니다. Rust 2024 경로는 rustc·Cargo 1.85+를 전제로 source fix, manifest·resolver·lockfile·style diff를 나누어 검토합니다. 두 경로 모두 검증을 통과한 뒤에만 팀 기준으로 승격합니다.

compiler 업데이트와 edition 마이그레이션 분리 흐름 현재 toolchain, crate edition, workspace resolver, lockfile, rustfmt style 기준을 기록합니다. toolchain-only 경로는 edition을 유지하고 compiler 변화만 격리합니다. Rust 2024 migration 경로는 rustc와 Cargo 1.85 이상을 준비하고 cargo fix edition 뒤 manifest, resolver, lockfile, format 차이를 검토합니다. 두 경로는 target, feature, mixed-edition 의존성을 포함한 테스트와 CI 검증에서 합쳐집니다. TOOLCHAIN EDITION 현재 기준선 기록 rustc · edition · resolver · lockfile · style 어느 축을 바꾸는가? toolchain only | edition migration toolchain만 업데이트 edition unchanged compiler 변화만 격리 Rust 1.85+ 준비 · 자동 수정 dependency update: separate diff cargo fix --edition manifest · resolver · style 검토 edition = "2024" · resolver = "3" Cargo.lock · macro · doctest · fmt diff 빌드 · 테스트 · CI 검증 targets · features · mixed editions resolver · lockfile · style 차이 확인 팀 기준선에 반영 edition · resolver · style · MSRV · CI
baseline

현재 기준선 기록

rustc --version, crate별 edition·rust-version, workspace resolver, lockfile, rustfmt style, CI target·feature와 테스트 결과를 남깁니다.

decision

어느 축을 바꾸는가?

아래 두 경로를 같은 diff에 섞지 않습니다. 왼쪽은 compiler release만, 오른쪽은 crate의 edition과 연동 도구 기본값까지 바꿉니다.

A · toolchain only

edition을 유지한다

toolchain과 CI image만 올려 compiler 진단, codegen, target 지원 변화를 격리합니다. crate edition, resolver와 style 기준은 그대로 둡니다.

B · edition migration

Rust 1.85+에서 단계별 전환

① 의존성 갱신을 별도 diff로 검토합니다. ② package·feature·target별 cargo fix --edition과 수동 검토를 거칩니다. ③ edition = "2024", workspace resolver, Cargo.lock과 format diff를 각각 확인합니다.

merge · verify

빌드·테스트·CI 검증

두 경로 모두 target과 feature 조합, mixed-edition 의존성을 실행 검증합니다. edition 경로는 resolver 재해결과 Cargo.lock, cargo tree, rustfmt style 차이도 따로 확인합니다.

adopt

팀 기준선에 반영

검증된 edition·resolver·style, MSRV 또는 toolchain pin, CI image와 전환 이유를 문서화합니다.

자동 수정 범위

cargo fix --edition은 기본적으로 선택된 package의 모든 Cargo target을 검사합니다. 다만 활성 feature와 현재 target platform의 cfg에서 보이는 코드만 수정하므로, 필요하면 --all-features와 다른 --target으로 반복합니다.

작업 단위

toolchain 업데이트, 의존성 갱신, 자동 수정, manifest·resolver·lockfile 변경과 포맷 diff를 분리하면 회귀 원인을 추적하기 쉽습니다.

의존성 에디션

의존 크레이트를 같은 edition으로 강제 이동할 필요는 없습니다. 선택한 rustc가 각 크레이트의 edition을 지원하고 전체 API와 동작 검증을 통과하면 함께 링크할 수 있습니다.

공식 Edition Guide의 기본 순서는 의존성 갱신, cargo fix --edition, manifest edition 변경, build·test, format입니다. Rust 2024에는 rustc·Cargo 1.85 이상이 필요하며 resolver 3 전환은 자동 migration 대상이 아닙니다. 자동 도구가 의미 보존을 보장하지 않으므로 source·lockfile·format diff와 실제 지원 구성을 팀 검증 절차에 포함합니다.

이 페이지의 목차