러스트(Rust) 프로그래밍 언어에서 `#[derive(...)]` 매크로를 사용해 `Debug`, `Clone` 등 트레이트(trait) 구현을 자동 생성할 때, 컴파일러가 암묵적으로 `#[inline]` 속성을 추가하는 것으로 나타났습니다. `#[inline]`은 함수 호출 시 해당 함수의 코드를 호출 지점에 직접 삽입하여 실행 속도를 높이는 최적화 힌트인데, 이것이 특정 상황에서는 오히려 최종 바이너리(binary) 파일의 크기를 불필요하게 증가시키는 원인이 될 수 있습니다.
이러한 현상은 특히 필드가 많고 깊게 중첩된 오류 계층(error hierarchy)과 같은 복잡한 데이터 구조에서 두드러집니다. 예를 들어, 여러 오류 타입을 감싸는 열거형(enum)에 `#[derive(Debug)]`를 적용하면, 각 오류 타입의 `Debug::fmt` 구현에 `#[inline]`이 붙게 됩니다. 디버그 로깅(debug logging)과 같이 이 `Debug` 구현이 반복적으로 호출되는 경우, 인라인된 코드가 호출 지점마다 삽입되면서 바이너리 크기가 빠르게 누적될 수 있습니다. 실제 사례로, 파이썬(Python) 패키지 관리 도구인 `uv` 프로젝트는 특정 `Debug` 구현의 인라이닝을 막아 바이너리 크기를 약 160KB 줄이는 데 성공했습니다. 이는 `rustc` 컴파일러가 인라이닝 크기나 횟수에 제한을 두지 않는 것처럼 보였기 때문입니다.
이 문제는 성능 최적화와 코드 크기 사이의 절충점(trade-off)을 보여줍니다. 일반적으로 `#[inline]`은 단순한 함수에 적용될 때 성능 이점을 제공하지만, 복잡한 함수에 무분별하게 적용되면 코드 크기 증가로 이어질 수 있습니다. 러스트 커뮤니티에서는 이 동작을 버그로 보고해야 한다는 의견과, 컴파일러가 완벽한 기본값을 선택하기 어렵다는 의견이 공존합니다. 개발자들은 `#[inline(never)]`와 같은 속성을 직접 사용하거나, 특정 상황에서 인라이닝을 제어할 수 있는 절차적 매크로(procedural macro)를 만드는 등의 해결책을 모색하고 있습니다. 이 논의는 러스트 컴파일러의 최적화 전략과 개발자가 코드 크기를 미세하게 제어할 필요성에 대한 중요한 시사점을 제공합니다.