Java의 지원 중단(Deprecation) 발전 과정
Java 생태계에서 기능의 지원 중단을 표시하는 방식은 시간이 흐름에 따라 점진적으로 발전해 왔습니다.
- Java 1.4 이하: JavaDoc의
@deprecated지시어를 사용했으나, 이는 문서화 용도일 뿐 런타임이나 컴파일러가 직접적으로 인식하기 어려웠습니다. - Java 1.5:
java.lang.Deprecated어노테이션이 도입되어 런타임에서도 지원 중단 여부를 확인할 수 있게 되었으나, 구체적인 시점이나 삭제 예정 여부 등의 메타데이터는 부족했습니다. - Java 9:
@Deprecated어노테이션에since와forRemoval속성이 추가되었습니다.since는 해당 기능이 언제부터 지원 중단되었는지 정보를 제공하며,forRemoval=true는 향후 버전에서 실제로 제거될 것임을 경고하여 더 강력한 주의를 환기합니다.
JRuby의 어노테이션 업데이트 동기
JRuby는 오랜 역사를 가진 프로젝트인 만큼 코드베이스 곳곳에 속성이 없는 단순한 @Deprecated 어노테이션이 많이 존재했습니다. JRuby 10이 최소 Java 21 버전을 요구하게 되면서, Java 9 이상의 기능을 자유롭게 사용할 수 있는 환경이 조성되었습니다. 이에 따라 기존의 모든 “bare” 어노테이션을 최신 규격에 맞게 업데이트하여 API 사용자에게 더 나은 정보를 제공하고 내부적으로는 오래된 코드를 정리할 기준을 마련하고자 했습니다. 이는 특히 JRuby를 API로 사용하거나 대규모 Java 애플리케이션에 내장하여 사용하는 개발자들에게 유용한 정보를 제공합니다.
Ruby와 Git을 활용한 자동화 스크립트
수천 개의 파일을 수동으로 수정하는 대신, 저자는 Ruby의 유연성과 Git의 이력 추적 기능을 결합한 자동화 스크립트를 작성했습니다. 이 프로세스는 다음과 같은 단계로 진행됩니다.
- 대상 식별: 모든
.java파일을 순회하며 속성이 정의되지 않은@Deprecated문자열을 찾습니다. - 이력 추적:
git blame명령어를 사용하여 해당 어노테이션이 처음 추가된 커밋의 SHA 값을 추출합니다. 특정 라인의 변경 이력을 추적하여 정확한 도입 시점을 찾아냅니다. - 버전 매핑: 추출된 SHA 값을 바탕으로
git describe --tags --contains명령어를 실행하여, 해당 커밋이 포함된 최초의 JRuby 정식 릴리스 태그를 확인합니다. - 코드 수정: 확인된 태그 정보를
since속성에 삽입하여@Deprecated(since = "vX.Y.Z")형태로 치환하고 파일을 업데이트합니다.
도입의 장단점 및 고려사항
이러한 자동화 방식은 다음과 같은 명확한 이득과 잠재적 위험을 동시에 동반합니다.
- 장점: 각 기능의 지원 중단 시점을 명확히 알 수 있어 ‘가장 오래된’ 지원 중단 API부터 순차적으로 제거하는 일정을 수립하기 용이합니다. 또한 사용자에게는 더 상세한 컴파일 경고를 제공하여 마이그레이션을 독려할 수 있습니다.
- 단점 및 한계: 파일 이동이나 대규모 리팩토링으로 인해 Git 이력이 단절된 경우 부정확한 버전이 기입될 수 있습니다. 또한
git blame실행 시 최신 커밋이 어노테이션 수정 건으로 기록되어, 과거의 실제 로직 변경 이력을 보려면 부모 커밋을 찾아야 하는 번거로움이 발생할 수 있습니다. 저자는 이를 단일 커밋으로 묶어 관리함으로써 부작용을 최소화했습니다.