모든 소프트웨어 프로젝트는 결국 더 이상 사용되지 않는 코드, 구식으로 표시된 구성 요소, 사용을 권장하지 않는 구성 요소 또는 제거 예정인 구성 요소를 만나게 됩니다. @deprecated 자바에서 어노테이션은 DeprecationWarning 파이썬에서 IDE 자동 완성 기능의 취소선 표시와 같은 것들은 모두 여러분이 사용하거나 유지 관리하는 특정 기능이 더 이상 사용되지 않는다는 것을 알려주는 신호입니다. 이러한 신호를 무시하면 의존성이 제거되거나, 보안 패치가 오래된 API를 건너뛰거나, 프레임워크 업그레이드로 인해 세 버전 전에 사용이 중단된 기능에 여전히 의존하는 모든 것이 제대로 작동하지 않게 될 때까지 위험이 조용히 누적됩니다.
'사용 중단됨'의 의미, 중요성, 그리고 체계적인 처리 방법을 이해하는 것은 개발팀이 갖춰야 할 가장 실용적인 유지보수 기술 중 하나입니다. 이 가이드는 명확한 정의, 유사 용어와의 비교, 다양한 언어에서의 사용 중단 경고, 그리고 사용 중단된 종속성이 실제 운영 환경에서 문제가 되기 전에 관리하는 체계적인 접근 방식 등 전반적인 내용을 다룹니다.
더 이상 사용되지 않는 코드란 무엇인가요?
사용이 권장되지 않는 코드(deprecated code)란 여전히 작동하지만 공식적으로 사용을 권장하지 않는 함수, 메서드, API, 라이브러리 또는 전체 구성 요소를 말합니다. 이러한 코드는 계속해서 작동하고 컴파일, 실행되어 결과를 생성하지만, 해당 코드의 관리자는 향후 버전에서 제거되거나, 더 나은 대안으로 대체되거나, 더 이상 유지 관리 또는 업데이트되지 않을 것이라고 밝혔습니다. 사용이 권장되지 않는 코드를 사용하는 것은 해당 코드의 관리자가 더 이상 관심을 두지 않는 부분에 의존하는 것을 의미합니다.
사용 중단(Deprecation)은 기술적인 상태가 아니라 소통 방식입니다. 라이브러리 관리자가 함수를 사용 중단으로 표시하는 것은 "이 함수는 현재도 작동하지만, 향후 제거할 예정이므로 그 전에 다른 함수로 마이그레이션해야 합니다."라는 의미입니다. 사용 중단 공지 후 실제 제거까지의 기간은 다양하며, 한 번의 메이저 버전 업데이트 후가 될 수도 있고 5년이 걸릴 수도 있지만, 궁극적인 목표는 항상 같습니다. 사용 중단은 결국 제거된다는 것을 의미합니다.
Deprecated와 Depreciated의 철자 혼동:
이 두 단어는 자주 혼동되는데, 둘 다 의미가 다른 실제 영어 단어이기 때문에 맞춤법 검사기도 도움이 되지 않습니다.
(소프트웨어에서) 사용 중단됨 : 더 이상 사용되지 않거나, 권장되지 않거나, 제거 예정인 기능을 의미합니다. 소프트웨어 맥락에서 사용되는 정확한 용어입니다.
감가상각 (회계 용어): 시간이 지남에 따라 가치가 감소하는 것. 예: "서버 하드웨어는 3년에 걸쳐 감가상각되었습니다."
기술 문서에서 "사용 중단된 코드(depreciated code)"라는 표현을 보게 된다면, 거의 항상 "사용 중단된 코드(deprecated code)"를 의미합니다. 작성자가 회계 용어를 사용했지만 소프트웨어 용어를 의도하지 않은 것입니다. 이 오류는 매우 흔해서 이 글의 검색 콘솔 데이터에도 나타납니다. 소프트웨어에서는 항상 "사용 중단된 코드(deprecated)"를 사용하세요.
더 이상 사용되지 않는 코드 vs. 구식 코드 vs. 레거시 코드 vs. 사멸된 코드
이 용어들은 서로 관련이 있지만 코드의 서로 다른 상태를 나타냅니다. 이들을 혼동하면 부정확한 대화와 잘못된 우선순위 결정으로 이어질 수 있습니다.
| 기간 | 의미 | 제거되었나요? | 유지 관리가 되고 있나요? | 위험 수준 |
|---|---|---|---|---|
| 추천하지 않습니다 | 공식적으로 권장하지 않으며, 향후 제거될 예정입니다. | 아니요, 아직 있습니다. | 아니요, 점검이 중단되었습니다. | 중간 규모이며 시간이 지남에 따라 성장합니다. |
| 시대에 뒤 떨어진 | 더 이상 관련성이 없거나 적용되지 않습니다. 대체되었습니다. | 때때로 | 아니 | 중간 고 |
| 유산 | 오래된 코드이지만 여전히 작동하며, 프로덕션 환경에서 사용될 수도 있습니다. | 아니요, 아직 활동 중입니다. | 드물게 | 변수, 변화율에 따라 달라짐 |
| 데드 코드 | 실행 중에는 어떠한 연락도 받지 않았습니다. | 아니요, 아직 소스에 있습니다. | 해당 없음, 실행되지 않음 | 마이그레이션/감사 위험도: 낮음-중간 |
| 오래된 코드 | 오랫동안 수정되지 않았지만 공식적으로 사용 중단되지 않은 코드 | 아니 | 불분명 함 | 중간 크기이며, 가정을 숨길 수 있습니다. |
더 이상 사용되지 않는 것과 사용되지 않는 것의 차이'사용 중단됨'은 공식적인 명칭으로, 누군가가 명시적으로 표시한 것입니다. @deprecated 또는 사용 중단 공지를 발표했습니다. '사용 중단'은 좀 더 포괄적인 표현으로, 코드가 여전히 작동할 수는 있지만 최신 대안이 있는 상황에서 더 이상 합리적인 사용 사례가 없다는 의미입니다. 모든 사용 중단된 코드는 결국 사용 중단되지만, 모든 사용 중단된 코드가 공식적으로 사용 중단된 것은 아닙니다.
사용 중단 예정(Deprecation)과 제거됨(Removed) : 사용 중단된 코드는 코드베이스에 여전히 존재합니다. 제거된 코드는 완전히 삭제됩니다. 사용 중단 예정 기간은 이 두 상태 사이의 기간, 즉 코드가 더 이상 작동하지 않게 되기 전에 마이그레이션해야 하는 시간입니다.
사용 중단 예정 코드와 레거시 코드의 차이 : 레거시 코드는 이전 기술 시대에 작성된 오래된 운영 코드로, 종종 여전히 활발하게 사용 및 유지 관리되고 있습니다. 사용 중단 예정 코드는 삭제 대상으로 명시적으로 표시된 코드입니다. 일일 거래를 처리하는 레거시 COBOL 프로그램은 사용 중단 예정 코드가 아니라, 레거시 코드이지만 활발하게 유지 관리되고 있습니다. 라이브러리 공급업체에서 더 이상 사용하지 않는다고 표시한 COBOL API 함수가 사용 중단 예정 코드입니다.
사용 중단(Deprecate)과 서비스 종료(Decommission)의 차이 : 사용 중단은 코드베이스나 라이브러리 내에서 기술적인 신호를 보내는 것입니다. 서비스 종료는 운영상의 결정으로, 서비스를 중단하거나, 인프라를 제거하거나, 제품에 대한 지원을 종료하는 것을 의미합니다. 사용 중단된 API는 수년 동안 계속 실행될 수 있지만, 서비스 종료된 API는 특정 날짜에 서비스가 중단됩니다.
사용 중단됨 표시의 예: 언어별 경고
사용 중단 경고는 언어와 도구에 따라 다양한 형태로 나타납니다. 경고를 즉시 인식하는 것이 해결의 첫걸음입니다.
Python: 사용 중단 경고
파이썬
import warnings
# Marking a function as deprecated
def old_function():
warnings.warn(
"old_function is deprecated, use new_function instead",
DeprecationWarning,
stacklevel=2
)
# original implementation
def new_function():
# improved implementation
pass
Python은 런타임에 사용 중단 경고를 표시합니다. 일반적인 컴파일러 메시지는 다음과 같습니다.
DeprecationWarning: old_function is deprecated, use new_function instead
또는 타사 패키지의 경우:
DeprecationWarning: pkg_resources is deprecated as an API.
Use importlib.resources or importlib.metadata instead.
자바: @Deprecated 어노테이션
자바
public class LegacyProcessor {
@Deprecated
public void processData(String input) {
// old implementation
}
// Replacement method
public void processDataV2(String input, ProcessOptions options) {
// new implementation
}
}
자바 컴파일러는 다음과 같은 결과를 생성합니다.
Note: SomeFile.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
JavaScript/TypeScript: JSDoc @사용 중단됨
자바 스크립트
/**
* @deprecated Use fetchUserById() instead.
* This function will be removed in version 4.0.
*/
function getUser(id) {
// old implementation
}
// Modern replacement
async function fetchUserById(id) {
// new implementation
}
타이프 스크립트
class ApiClient {
/** @deprecated Use post() with typed options instead */
sendRequest(url: string): Promise<any> {
// deprecated implementation
}
}
IDE 디스플레이 getUser 호출되는 모든 곳에 취소선이 그어져 있으며, TypeScript의 @typescript-eslint/no-deprecated CI에서 해당 규칙이 플래그를 지정합니다.
C++: [[사용 중단됨]] 속성
CPP
// C++14 and later
[[deprecated("Use processV2() instead")]]
void process(int value) {
// old implementation
}
void processV2(int value, ProcessFlags flags = ProcessFlags::Default) {
// new implementation
}
컴파일러는 다음을 생성합니다.
warning: 'process' is deprecated: Use processV2() instead [-Wdeprecated-declarations]
Swift: 사용 중단된 @available
빠른
@available(*, deprecated, renamed: "fetchUser(withID:)")
func getUser(id: String) -> User {
// old implementation
}
func fetchUser(withID id: String) -> User {
// replacement
}
Kotlin/Java: @Deprecated와 ReplaceWith 사용
코 틀린
@Deprecated(
message = "Use processItems() instead",
replaceWith = ReplaceWith("processItems(items)"),
level = DeprecationLevel.WARNING
)
fun handleItems(items: List<Item>) {
// deprecated
}
fun processItems(items: List<Item>) {
// replacement
}
더 이상 사용되지 않는 코드가 실제 문제를 일으키는 이유
더 이상 사용되지 않는 코드는 단순한 관리 문제가 아닙니다. 이는 네 가지 측면에서 구체적이고 누적적인 위험을 초래합니다.
보안 취약점. 더 이상 사용되지 않는 API와 라이브러리는 보안 패치를 받지 않습니다. 패치가 적용되지 않은 CVE가 있는 사용 중단된 라이브러리는 영구적인 취약점을 나타내며, 관리자는 모든 사용자가 다른 라이브러리로 마이그레이션하도록 유도하기 위해 더 이상 수정을 진행하지 않습니다. 사용 중단된 구성 요소를 사용하는 조직은 의도적으로 알려진 취약한 코드를 사용하고 있는 것입니다.
업그레이드 시 종속성 문제가 발생합니다. 사용 중단 알림은 해당 기능이 곧 제거될 예정임을 알리는 것입니다. 주요 버전 업그레이드가 진행되어 사용 중단된 API가 제거되면, 해당 API에 여전히 의존하는 모든 시스템이 최악의 순간, 즉 정상적인 업그레이드 과정 중에 동시에 작동을 멈추게 됩니다.
유지보수 복잡성 증가. 더 이상 사용되지 않는 코드는 개발자가 기존 코드의 기능과 새로운 대체 코드의 기능을 동시에 이해해야 하는 두 가지 사고방식을 요구합니다. 새로 합류하는 모든 팀원은 코드베이스의 어떤 부분을 피해야 하는지, 그리고 그 이유는 무엇인지 배워야 합니다. 이러한 이중적인 복잡성은 더 이상 사용되지 않는 구성 요소가 추가될 때마다 누적됩니다.
기술 부채는 누적됩니다. 더 이상 사용되지 않는 각 종속성은 기술 부채의 단위입니다. 다른 부채와 달리, 더 이상 사용되지 않는 코드 부채에는 기한이 있으며, 해당 구성 요소가 실제로 제거되는 순간 "경고"에서 "오류 발생"으로 전환됩니다.
소프트웨어 프로젝트에서 더 이상 사용되지 않는 종속성을 처리하는 방법
1단계: 모든 감가상각 항목 목록 작성
사용되지 않는 구성 요소를 하나씩 찾아내는 대신 체계적인 검사를 실행하세요. 대부분의 도구는 전체 목록을 보여주는 기능을 제공합니다.
세게 때리다
# Python: find all DeprecationWarning instances
python -W error::DeprecationWarning -m pytest
# JavaScript/Node.js: run with deprecation tracing
node --trace-deprecation app.js
# Java: compile with full deprecation details
javac -Xlint:deprecation *.java
# npm: find deprecated packages
npm outdated
npm audit
2단계: 위험도에 따라 분류
모든 감가상각 항목이 즉각적인 조치를 필요로 하는 것은 아닙니다. 각 항목을 분류하십시오.
| 우선 | 기준 | 동작 |
|---|---|---|
| 결정적인 | 보안상 중요한 라이브러리이며 더 이상 사용되지 않습니다. 알려진 CVE가 있으며, 다음 주요 버전에서 제거될 예정입니다. | 즉시 이주하세요 |
| 높음 | 현재 주요 버전에서 사용이 중단되었으며, CI에서 경고 메시지가 표시됩니다. | 현재 스프린트 또는 다음 스프린트 일정 |
| 중급 | 더 이상 사용되지 않지만 2개 이상의 주요 버전에서는 여전히 지원됩니다. 보안 위험은 없습니다. | 일정과 함께 백로그에 추가 |
| 높음 | 내부 코드에서 사용 빈도가 낮은, 더 이상 사용되지 않는 어노테이션 | 관련 리팩토링 중에 추적 및 처리 |
3단계: 마이그레이션 전에 모든 사용처를 찾으세요
더 이상 사용되지 않는 구성 요소를 변경하기 전에 해당 구성 요소가 사용되는 모든 위치를 파악하십시오. 완전한 사용 위치 파악 없이 변경하면 오류 없이 작동을 멈추게 하는 사용 위치를 놓칠 위험이 있습니다.
파이썬
# Using grep for basic search
grep -r "old_function" src/
# Using ast-grep for code-aware search (TypeScript/JS)
ast-grep --pattern 'getUser($ID)' --lang ts
# Using ripgrep with file type filtering
rg "deprecated_method" --type java
대규모 코드베이스의 경우, 자동화된 정적 분석 도구는 특히 동적 디스패치나 상속을 통한 간접 사용에 대해 수동 grep보다 더 정확하게 완전한 상호 참조 맵을 생성합니다.
4단계: 체계적으로 마이그레이션
더 이상 사용되지 않는 사용법을 하나씩 교체하고, 다음 단계로 넘어가기 전에 각 사용법의 유효성을 검사하십시오.
파이썬
# Before: deprecated
import imp
module = imp.load_source('mymodule', '/path/to/mymodule.py')
# After: replacement
import importlib.util
spec = importlib.util.spec_from_file_location('mymodule', '/path/to/mymodule.py')
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
자바 스크립트
// Before: deprecated event property
document.addEventListener('keydown', (event) => {
const key = event.keyCode; // deprecated
});
// After: modern replacement
document.addEventListener('keydown', (event) => {
const key = event.key; // current standard
});
5단계: CI/CD에 사용 중단 게이트 추가
정리 작업 후 더 이상 사용되지 않는 코드가 코드베이스에 추가되는 것을 방지합니다.
얌
# .github/workflows/deprecation-check.yml
- name: Check for deprecated API usage (Java)
run: javac -Xlint:deprecation -Werror src/**/*.java
- name: Check for deprecated packages (Node)
run: npm audit --audit-level=moderate
- name: ESLint no-deprecated rule (TypeScript)
run: npx eslint --rule '{"@typescript-eslint/no-deprecated": "error"}' src/
감가상각 정책 수립
조직이 제품 사용 중단을 효과적으로 관리하려면 이를 단순히 기술적인 문제가 아니라 정책적인 문제로 접근해야 합니다. 제품 사용 중단 정책은 다음과 같은 사항을 정의합니다.
누가 사용 중단을 결정할 수 있나요? 단일 개발자가 팀 검토 없이 널리 사용되는 내부 API를 일방적으로 사용 중단해서는 안 됩니다. 사용 중단 결정에는 해당 API를 사용하는 구성 요소의 소유자가 참여해야 합니다.
사용 중단 기간은 얼마나 지속될까요? 적절한 기본값은 제거 전 주요 버전 주기 한 번입니다. 공개 API의 경우 주요 버전 두 번, 내부 API의 경우 릴리스 주기 한 번입니다.
사용 중단 알림은 코드 주석, 변경 로그 항목, 그리고 알려진 사용자에게 직접 알림을 통해 전달됩니다 . 코드 주석에만 있는 사용 중단 알림은 전달되지 않을 수 있습니다.
"제거됨"의 의미는 무엇인가요? 코드가 삭제되는 건가요? 별도의 선택적 패키지로 이동되는 건가요? 기능 플래그 뒤에 숨겨지는 건가요? 최종 상태를 명확하게 정의하세요.
마이그레이션 경로가 문서화되는 방식. 모든 사용 중단 경고에는 대체 기능에 대한 참조가 포함되어야 합니다. @deprecated Use fetchUserById() instead 보다 더 유용하다 @deprecated.
더 이상 사용되지 않는 코드가 여전히 작동할까요?
네, 그렇습니다. 하지만 그렇지 않은 경우도 있습니다. 사용이 중단된 코드는 실제로 제거되는 버전이 나올 때까지 정상적으로 실행됩니다. 이것이 사용이 중단된 코드의 가장 위험한 특징입니다. 바로 잘못된 안정감을 조성한다는 것입니다. 수년간 사용이 중단된 API를 사용해 온 시스템은 안정적으로 보일 수 있지만, 매 릴리스 주기마다 갑작스러운 오류 발생 위험이 커집니다.
"더 이상 사용되지 않는 코드를 실행해도 안전한가요?"라는 질문에 대한 답은 제거 예정일이 얼마나 가까운지, 그리고 해당 구성 요소의 보안 상태가 어떤지에 따라 다르다는 것입니다. 알려진 CVE가 없는 활발하게 유지 관리되는 라이브러리의 마이너 릴리스에서 사용이 중단된 함수는 즉각적인 위험이 낮습니다. 하지만 패치가 되지 않은 취약점이 있고 지원 종료일이 발표된 인증 라이브러리는 즉각적인 위험이 매우 높습니다.
방법 SMART TS XL 기업 시스템 전반에서 더 이상 사용되지 않는 코드를 식별합니다.
단일 언어 프로젝트에서는 사용되지 않는 코드를 찾는 것이 올바른 컴파일러 플래그나 린트 규칙을 실행하는 것만으로 간단하게 해결됩니다. 하지만 COBOL, JCL, Java, Python 및 최신 서비스가 혼합된 엔터프라이즈 환경에서는 각 언어의 사용되지 않는 구성 요소를 동시에 찾아야 하며, 이러한 구성 요소들 간의 관계 또한 사용 중단 자체만큼이나 중요합니다.
SMART TS XL의 정적 코드 분석 환경 내 모든 언어를 스캔하여 전체 코드베이스에서 더 이상 사용되지 않는 어노테이션, 구식 API 사용, 사용되지 않는 코드 패턴을 동시에 찾아냅니다. COBOL 카피북이 더 이상 사용되지 않는 것으로 표시되면, SMART TS XL 해당 메서드를 포함하는 모든 프로그램을 식별합니다. Java API 메서드가 더 이상 사용되지 않게 되면 포트폴리오 내 모든 서비스의 모든 호출 지점을 추적합니다.
영향 분석 기능은 여기서 한 단계 더 나아갑니다. 더 이상 사용되지 않는 구성 요소를 제거하기 전에, 해당 제거가 어떤 영향을 미칠지, 어떤 프로그램, 어떤 작업 흐름, 어떤 하위 서비스에 영향을 미칠지 모든 언어에 걸쳐 전체 범위를 생성합니다. 이를 통해 "무엇이 손상될까?"라는 위험한 질문을 제거를 진행하기 전에 검증해야 할 모든 항목의 구조화되고 열거된 목록으로 변환합니다.
엔터프라이즈 검색 기능을 통해 인벤토리를 쿼리할 수 있습니다. 수백만 줄의 코드와 여러 언어에서 특정 사용 중단 함수의 모든 사용 사례, 사용 중단된 카피북에 대한 모든 참조, 더 이상 사용되지 않는 API 호출을 단 몇 초 만에 찾아낼 수 있습니다. 사용 중단된 구성 요소 인벤토리가 마이그레이션 범위를 결정하는 출발점 인 레거시 현대화 프로그램의 경우, 이 검색 기능은 수주에 걸친 수동 감사 작업을 특정 쿼리로 대체합니다.