Rust 1.99 업그레이드: CI 증분 컴파일과 Cargo 호환성 점검

Rust 1.99 업그레이드에서 CI 빌드 시간과 캐시를 비교하고, Cargo 프로파일·의존성 기능·호환성 변경을 점검한다.

2026-10-11

CI 빌드 시간부터 다시 비교한다

Cargo는 CI 환경 변수로 CI 실행을 감지하고, CI에서는 증분 컴파일을 기본적으로 비활성화한다. Rust 1.99로 올린 뒤 빌드 시간이 달라졌다면, 소스 변경뿐 아니라 이 기본값 변경도 비교 조건에 넣어야 한다.

이 글의 기준 버전은 Rust 1.99.0 (2026-10-01), Cargo 1.99 (2026-10-01), LLVM 23이다. 변경 근거는 Rust 1.99.0 릴리스노트이며, CI 감지와 증분 컴파일 변경은 호환성 항목에 명시돼 있다.

먼저 CI 작업의 실행 환경에 CI 변수가 있는지 확인한다. 이어서 증분 컴파일에 관한 명시적 설정이 있는지 살핀다. 릴리스노트가 말하는 것은 기본값의 변경이다. 기존 설정을 확인하지 않은 채 모든 CI 작업에서 증분 컴파일이 반드시 꺼진다고 단정하면 안 된다.

다음 그림은 CI 빌드 시간을 비교하기 전에 기본값 변경과 기존 설정을 어떻게 구분할지 보여 준다.

⤢✕예아니오CI 작업의 실행 환경 확인CI 환경 변수로 감지되는가증분 컴파일 기본 비활성화이 변경의 CI 조건에 해당하지않음증분 컴파일의 명시적 설정 확인실제 적용 조건을 기록하고 빌드시간 비교

업그레이드 전후를 비교할 때는 같은 소스, 같은 작업, 같은 캐시 복원 조건을 맞춘다. 캐시를 복원하지 않은 실행과 복원한 실행을 구분해 기록하면, 서로 다른 조건의 결과를 버전 차이로 오해하는 일을 줄일 수 있다.

캐시 설정도 함께 검토한다. 현재 저장하는 항목이 무엇인지, 그 항목을 저장하는 이유가 증분 컴파일과 연결돼 있는지 확인한다. 기본값이 바뀌었다는 이유만으로 캐시 전체를 없애거나 유지하기보다는, 해당 작업에서 어떤 설정이 적용되고 어떤 항목을 다시 사용하는지 확인한 뒤 조정한다.

릴리스노트에는 이 변경으로 CI가 얼마나 빨라지거나 느려지는지 수치가 없다. 따라서 업그레이드 검증 결과에는 “더 빠르다”는 예상 대신, 비교 조건과 관측한 시간을 남겨야 한다.

debug 프로파일 도입과 성능 변경을 분리한다

Cargo 1.99에는 내장 debug 프로파일이 추가됐다. 현재 dev와 debug 프로파일 사이에는 차이가 없다.

추가 목적은 앞으로 dev 프로파일을 디버깅 중심에서 벗어나게 하고, 더 빠른 개발 반복에 적합한 기본값으로 전환할 준비다. 이 설명을 현재 버전의 성능 개선으로 읽으면 안 된다. debug라는 이름이 생겼다는 사실만으로 기존 개발 빌드가 빨라졌거나 디버깅 동작이 달라졌다고 판단할 근거는 없다.

실무에서는 프로파일 전환을 CI 기본값 변경과 별개로 다룬다. 빌드 시간이 달라졌을 때 “새 프로파일 때문”이라고 결론 내리기 전에, 실제 작업이 선택한 프로파일과 증분 컴파일 조건을 각각 기록한다.

점검 대상 Rust 1.99에서 확인된 변경 적용 판단
CI 증분 컴파일 CI 환경 변수로 감지되는 CI에서 기본 비활성화 실행 환경과 명시적 설정을 확인하고 시간·캐시 조건을 비교한다
내장 debug 프로파일 새로 추가됐으며 현재 dev와 차이가 없음 이름 변경을 성능 개선의 근거로 삼지 않는다
workspace default-features edition 2024 이상 멤버에서 상속 값 재정의 가능 멤버의 edition과 의존성 선언을 함께 점검한다

프로파일 이름을 바꾸는 작업이 필요하다면 그 목적을 명확히 남긴다. 현재 동작 차이를 이용하려는 것인지, 앞으로의 프로파일 방향을 고려한 것인지 구분해야 이후 빌드 결과를 해석할 때 혼선이 없다.

workspace의 default-features는 멤버 edition과 함께 읽는다

workspace 의존성을 상속하는 멤버에서 default-features = false를 사용하고 있다면, 업그레이드 검토 대상에 넣는다. edition 2024 이상의 멤버는 이제 상속한 workspace 의존성의 default-features를 재정의할 수 있다.

릴리스노트에 제시된 선언은 다음과 같다.

serde = { workspace = true, default-features = false }

workspace 정의가 기본 기능을 활성화하더라도, edition 2024 이상의 멤버에서는 이 선언이 기본 기능을 끈다. 이전 edition에서는 default-features = false가 경고와 함께 무시된다.

같은 선언을 복사했다고 같은 결과가 되는 것은 아니다. 점검 단위는 workspace 전체가 아니라 해당 선언을 가진 멤버와 그 멤버의 edition이다. 특히 기존 경고를 알고도 선언을 남겨 둔 프로젝트라면, 해당 멤버에서 재정의가 적용되는지 다시 확인해야 한다.

다음 그림은 동일한 의존성 선언이 멤버 edition에 따라 어떻게 처리되는지 보여 준다.

⤢✕예아니오workspace 의존성 상속default-features = false선언멤버가 edition 2024 이상인가workspace 정의가 활성화해도기본 기능을 끔경고와 함께 선언을 무시해당 멤버의 빌드와 테스트 확인

검토할 때는 workspace의 의존성 정의, 멤버의 상속 선언, 멤버 edition을 한 묶음으로 읽는다. 이어서 해당 멤버의 빌드와 테스트로 의도한 기능 구성이 맞는지 확인한다. 선언이 허용된다는 사실과 프로젝트가 그 기능 구성으로 동작한다는 사실은 각각 확인해야 한다.

빌드를 막는 변경과 경고를 구분한다

no_mangle_generic_items는 Rust 1.99에서 하드 에러로 승격됐다. 업그레이드 로그에서 이 항목이 보이면 단순한 경고 정리 작업으로 미룰 수 없다. 해당 진단을 발생시키는 코드를 확인하고 수정한 뒤 빌드를 다시 검증한다.

레거시 정수 모듈도 완전히 deprecated됐다. 릴리스노트가 제시한 대체 표기는 다음과 같다.

// 레거시 모듈을 통한 접근
std::i32::MAX

// 대체 표기
i32::MAX

진단의 성격에 따라 검증할 대상도 달라진다.

변경 항목 릴리스노트가 명시한 내용 점검할 대상
no_mangle_generic_items 하드 에러로 승격 해당 진단이 발생하는 코드와 빌드 결과
레거시 정수 모듈 완전히 deprecated std::i32::MAX 같은 레거시 접근 표기
문서 주석의 코드 블록 아무 대상에도 적용되지 않는 속성이 에러 문서 코드 예시와 문서 테스트
외부 매크로의 세미콜론 다른 크레이트에서 온 매크로에도 경고 발생 경고를 발생시키는 매크로와 제공 크레이트

외부 매크로 경고는 수정 책임까지 확인해야 한다. 세미콜론으로 확장되는 매크로는 이제 다른 크레이트에서 왔더라도 semicolon_in_expressions_from_non_local_macros 경고를 낸다.

이전에는 같은 크레이트의 매크로에만 관련 경고가 나타났다. 릴리스노트는 매크로 제공 크레이트의 통합 테스트도 별도 크레이트로 컴파일되기 때문에, 그 제한이 문제를 드러내지 못하게 할 수 있었다고 설명한다. 경고가 나타나면 소비하는 프로젝트에서 잠재우는 데 그치지 말고, 제공 크레이트에 알려 수정하도록 해야 한다.

다음 그림은 업그레이드 로그의 진단을 빌드 수정, 문서 검증, 제공 크레이트의 수정 요청으로 연결하는 판단 경로다.

⤢✕no_mangle_generic_items문서 코드 블록의 속성외부 매크로의 세미콜론업그레이드 로그의 진단 확인진단 항목하드 에러를 발생시키는 코드수정코드 예시 수정 후 문서 테스트확인매크로 제공 크레이트에 문제보고빌드 재검증문서 테스트 재검증제공 크레이트의 수정으로 해결

컴파일 성공 뒤에도 확인할 동작이 있다

RangeInclusive는 일부 상황에서 반복이 더 잘 최적화됐다. 그에 따라 이미 소진된 범위의 start()와 end() 반환값, 소진된 범위를 슬라이스 인덱스로 사용하는 동작이 달라질 수 있다.

릴리스노트는 이 동작들이 안정적으로 보장된 적이 없으므로 호환성을 깨는 변경으로 간주하지 않는다고 설명한다. 그래도 기존 테스트나 코드가 이전 결과를 기대했다면 프로젝트에는 영향을 줄 수 있다. 범위를 모두 순회한 뒤에도 그 범위를 조회하거나 인덱스로 쓰는 코드가 있는지 확인하고, 그 기대를 검토한다. 컴파일이 성공하는지만으로 끝낼 수 없는 항목이다.

unsafe 코드를 다루는 프로젝트라면 다음 항목도 검토 범위에 넣는다.

  • Pin::new_unchecked의 안전 불변식이 약간 변경됐다.
  • Rust Reference는 union과 다른 값을 하나의 패턴으로 함께 검사하는 기존 권고를 철회했다. 일부 상황에서 나머지 패턴을 확인하기 전에 컴파일러가 union의 내용을 읽을 수 있으며, 기존 권고와 비슷한 코드에서 정의되지 않은 동작을 일으킬 수 있기 때문이다.

제공된 릴리스노트에는 Pin::new_unchecked 불변식의 구체적인 변경 내용이나 union 패턴의 수정 예제가 없다. 따라서 일괄 수정 규칙을 만들기보다는, 해당 API와 패턴을 사용하는 위치를 찾아 개별 검토 대상으로 남긴다.

LLVM은 23으로 업데이트됐다. 이 사실은 업그레이드 기록에 포함하되, 자료에 없는 성능 개선이나 코드 생성 차이를 전제하지 않는다.

업그레이드 완료 조건을 CI와 문서까지 잡는다

업그레이드 결과를 남길 때는 변경 항목과 검증 증거를 연결한다. “Rust 1.99에서 빌드 성공”만으로는 CI 기본값, 멤버별 기능 선택, 문서 예시의 변경을 확인했는지 알 수 없다.

  • CI의 CI 환경 변수와 증분 컴파일 명시적 설정을 확인하고, 업그레이드 전후 빌드 시간의 비교 조건을 기록한다.
  • 캐시를 복원한 실행과 복원하지 않은 실행을 구분하고, 저장 항목의 목적이 현재 빌드 설정과 맞는지 검토한다.
  • dev와 debug가 현재 같다는 전제 아래, 실제 작업이 사용하는 프로파일을 기록한다.
  • default-features = false를 선언한 workspace 멤버의 edition을 확인하고, 해당 멤버의 빌드와 테스트를 검증한다.
  • no_mangle_generic_items, 레거시 정수 모듈, 문서 코드 블록의 속성 진단을 처리하고 관련 검증을 다시 수행한다.
  • 외부 매크로 경고의 제공 크레이트를 확인하고, 소진된 RangeInclusive와 관련 unsafe 코드의 사용 여부를 검토한다.

CI 시간과 캐시의 효과는 실제 비교 결과로 판단하고, 호환성 변경은 해당 코드와 테스트로 확인한다. 이 증거가 모여야 기본값 변경을 놓친 업그레이드와 검증을 마친 업그레이드를 구분할 수 있다.

RustCargoCI빌드 캐시호환성