주요 요점:
- 기업 시스템에서 지원 종료된 소프트웨어는 피할 수 없는 현실입니다. 핵심 플랫폼은 종종 그 기반이 되는 오픈소스 구성 요소보다 수명이 더 길며, 이러한 구성 요소들은 공식 지원이 종료된 후에도 오랫동안 취약점이 계속 누적됩니다.
- 지원 종료(EOL)된 소프트웨어를 안전하게 운영하려면 지속적이고 복잡한 노력이 필요합니다. 흩어져 있는 데이터베이스와 복잡한 종속성 그래프 전반에 걸쳐 취약점을 추적한 다음, 팀이 물려받은 구성 요소에 패치를 적용하고 재빌드하며 테스트해야 합니다. 이러한 과정을 수년에 걸쳐 반복해야 합니다.
- 오픈소스의 장기적인 신뢰성은 취약점이 없다는 사실로 결정되는 것이 아니라, 취약점을 처리하는 프로세스의 성숙도에 의해 결정됩니다. 표준화된 패치 워크플로우 와 TuxCare의 Endless Lifecycle Support가 제공하는 것과 같은 조직적 전문성은 시간이 지나도 일관되고 신뢰할 수 있는 오픈소스 보안을 가능하게 합니다.
오늘 개발하는 소프트웨어는 앞으로 수년, 혹은 10년 이상 가동될 가능성이 높습니다. 핵심 시스템은 마음 내키는 대로 교체되지 않습니다. 이러한 시스템은 너무 중요하거나, 비용이 너무 많이 들거나, 다른 시스템과 너무 깊이 연동되어 있어 교체할 수 없기 때문에 유지보수되고, 패치가 적용되며, 계속 가동됩니다.
하지만 대부분의 팀이 개발 과정에서 간과하는 점이 하나 있습니다. 바로 소프트웨어가 의존하는 오픈소스 구성 요소들이 반드시 해당 소프트웨어만큼 오래 지속되지는 않는다는 사실입니다. 라이브러리는 수명 주기가 끝납니다. 프레임워크는 더 이상 업데이트되지 않습니다. 언어 런타임은 새로운 버전으로 넘어가는데, 이는 Node.js 수명 종료 전환 과정에서 직면했던 어려움과 매우 유사합니다. 이러한 현실은 인기 있는 프론트엔드 프레임워크에도 영향을 미치며, 팀들은 종종 프로덕션 로드맵을 방해하지 않으면서 next.js의 EOL ( 수명 종료 ) 주기를 관리할 방법을 모색합니다. 그리고 그럴 경우, 더 이상 공식적으로 지원되지 않는 소프트웨어에 의존하는 프로덕션 시스템을 유지 관리해야 하는 상황에 처하게 됩니다.
공식 지원이 종료된다고 해서 취약점이 사라지는 것은 아닙니다. 취약점은 해마다 계속해서 나타나며, 복잡한 의존성 관계도 곳곳에 흩어져 있습니다.
한두 번 정도는 수습할 수 있습니다. 하지만 5년이나 10년 동안 안정적이고 반복적이며 정확하게 문제를 해결하려면 어떨까요? 이를 위해서는 대부분의 조직이 과소평가하는 요소가 필요합니다. 바로 취약점이 어디에서 나타나든, 언제 발견되든 상관없이 매번 동일한 방식으로 작동하는 성숙하고 체계적인 패치 프로세스입니다.
조직이 어떻게 EOL 소프트웨어를 계속 사용하게 되는가
소프트웨어가 5년, 7년, 혹은 10년 동안 운영 환경에 계속 사용된다면, 그 안에 포함된 오픈소스 구성 요소들은 시스템 자체보다 훨씬 먼저 수명 주기가 끝나게 됩니다. 유지보수 담당자들은 자리를 떠나고, 공식 지원은 중단되며, 어느새 보안 업데이트를 더 이상 받지 못하는 시스템을 운영하게 되는 것입니다. 이는 실수나 계획 부족의 징후가 아닙니다. 시스템 안정성과 통제된 변경이 최우선 과제인 기업 환경에서는 흔히 일어나는 일입니다.
그리고 이런 일은 생각보다 자주 발생합니다. 수년 동안 운영 환경에 적용되어 완벽하게 작동해 온 안정 버전을 사용하고 있을 수도 있습니다. 그 위에 구축한 통합 기능을 다시 구현하려면 막대한 비용이 들 수도 있습니다. 반복하고 싶지 않은 긴 규정 준수 인증 절차를 이미 거쳤을 수도 있습니다. 아니면 최신 버전에 도입된 호환성 깨는 변경 사항이 시스템 전체에 파급 효과를 미칠 수도 있습니다.
하지만 시스템이 장기적인 운영을 위해 설계되었다고 해도, 취약점의 양상은 끊임없이 변화하고 있습니다. 한때 안전하고 활발히 유지보수되던 오픈소스 종속성들에도 이제 아무도 수정하지 않을 취약점들이 쌓이기 시작합니다. 게다가 이러한 문제들 중 상당수는 전혀 눈에 띄지 않은 채로 남아 있습니다. 이들은 사용자가 실제로 상호작용하는 구성 요소 아래에 있는 종속성 계층 속에 묻혀 있기 때문입니다.
공급업체 지원 기간이 최종 제품의 서비스 종료 시점과 어떻게 다른지 더 자세히 알아보려면, ‘제품 수명 종료(End of Life)’와 ‘지원 종료(End of Support)’에 대한 당사의 가이드를 확인해 보세요.
의존성 그래프 문제
대부분의 팀은 자신이 의존하는 오픈소스 구성 요소를 매니페스트 파일에 나열된 단순한 목록으로 여깁니다. 하지만 이러한 라이브러리 각각은 자체적인 종속성을 동반하며, 그 종속성들 역시 또 다른 종속성을 가져옵니다.
아무리 가벼운 라이브러리라도 몇 가지 직접적인 종속성과는 물론, 평소에는 전혀 신경 쓰지 않는 수많은 간접적인 종속성에 의존하고 있을 수 있습니다. 그리고 취약점이 발견된다면, 그 위치는 어디든 될 수 있습니다. 실제로 사용하고 있는 최상위 컴포넌트일 수도 있고, 두 단계 아래에 있는 부차적인 라이브러리일 수도 있으며, 심지어 들어본 적도 없는 깊숙이 중첩된 종속성일 수도 있습니다.
고려해 보세요 spring-boot-starter-web를 고려해 보세요. 이는 자바 웹 애플리케이션에서 흔히 선택되는 라이브러리입니다. 프로젝트에 이 단일 종속성을 추가하면 25개 이상의 전이적 종속성: 전체 Spring® 프레임워크 스택, 내장 Tomcat 서버, JSON 처리를 위한 Jackson, 다양한 로깅 라이브러리, 유효성 검사 라이브러리 등이 포함됩니다.
그림. Spring® Boot Starter Web 의존성 트리.
따라서 오픈소스 컴포넌트의 유지보수를 맡기로 결정하면, 해당 컴포넌트의 전체 의존성 그래프에 대한 책임도 함께 짊어지게 됩니다. 그 그래프 내 어디에서든 취약점이 발견되면 이를 해결해야 할 책임은 여러분에게 있습니다. 게다가 이 수많은 의존성에서 발생하는 취약점에 대한 정보를 적시에 얻기 위해 정기적으로 모니터링할 수 있는 단일한 표준 채널은 존재하지 않습니다.
CVE는 수십 개의 다양한 보안 데이터베이스, 메일링 리스트 및 프로젝트 저장소에 게시됩니다. 사용자가 직접 다뤄본 적 없는 잘 알려지지 않은 전이적 종속성에서 심각한 문제가 발견될 수도 있습니다.
전체 그래프에 걸쳐 지속적인 모니터링이 필요하며, 직접 사용하는 구성 요소뿐만 아니라 여러 계층에 걸친 모든 종속성을 추적하고, 새로운 공개 사항을 주시하며, 어떤 사항이 실제로 특정 EOL 버전에 영향을 미치는지 파악해야 합니다.
취약점을 수정하는 데 실제로 무엇이 포함되는가
의존성 그래프의 어느 부분에 취약점이 발생하더라도, 이를 해결하는 것은 단순히 패치를 적용하는 것만으로 끝나는 일이 결코 아닙니다. 취약점이 있는 구성 요소 자체를 업데이트하고 재빌드해야 하며, 해당 구성 요소에 의존하는 모든 라이브러리를 재빌드하고, 전체 테스트 스위트를 실행한 뒤, 통합 또는 패키징 과정에서 아무런 변화가 없는지 확인해야 합니다.
보안 수정 사항이 사소하고 기존 동작을 유지하도록 설계된 경우라 할지라도, 재빌드는 피할 수 없습니다. 이는 배포해도 신뢰할 수 있는 아티팩트를 생성할 수 있는 유일한 방법이기 때문입니다.
경우에 따라서는 패치를 그대로 적용할 수 있습니다. 하지만 때로는 패치가 최신 버전을 위해 작성된 것이어서, 동결된 구성 요소가 의존하는 구버전 코드 및 종속성 버전과 호환되도록 수정해야 할 때도 있습니다. 이러한 수정 작업을 잘못하면 보안 취약점을 해결하지 못하거나, 해당 구성 요소에 의존하는 시스템과의 호환성이 깨질 수 있습니다.
5년에 걸친 EOL(지원 종료) 기간 동안 수십 건의 취약점이 발견될 수 있으며, 각 취약점은 해당 라이브러리의 전체 의존성 체인에 걸쳐 대응 작업을 유발합니다. 게다가 새로운 취약점은 끊임없이 발견되기 때문에, 해당 EOL 버전을 계속 사용해야 하는 한 이 과정을 반복해야 합니다. 매번 이 과정을 거칠 때마다 패치, 재빌드, 테스트, 검증, 배포라는 동일한 워크플로가 필요합니다. 그리고 재빌드할 때마다 그 자체로 복잡성이 따릅니다.
왜 “동결된 코드”가 “동결된 빌드”를 의미하지 않는가
소스 코드가 고정되고 종속성이 잠겨 있다면, 재빌드 시 항상 동일한 아티팩트가 생성될 것이라고 생각할 수도 있습니다. 하지만 실제로는 그렇지 않습니다.
5년이나 10년 동안 어떤 시스템을 유지 관리한다면, 그 시스템을 구축하는 환경은 필연적으로 변화하게 됩니다. 운영 체제에는 패치가 적용되고, 베이스 이미지는 업데이트되며, 컴파일러는 변경되고, 인증서 체인은 교체되며, CI/CD 도구는 업그레이드되고, 컨테이너 런타임도 발전합니다. 이러한 업데이트는 보안, 규정 준수, 운영상의 필요성 등 타당한 이유로 이루어지며, EOL(지원 종료)된 소프트웨어가 변경되든 그렇지 않든 상관없이 진행됩니다.
이러한 업데이트들은 빌드 환경에 미묘한 차이를 가져오며, 이러한 차이는 최종 아티팩트에 반영될 수 있습니다. 빌드 도구 역시 다른 모든 요소와 함께 진화합니다. 의존성 해결 방식과 아티팩트 패키징 알고리즘이 변경되기도 합니다. 그 결과, 패키징 형식이 약간 달라지거나 메타데이터의 구조가 변경될 수 있습니다. 이러한 변화는 컴포넌트의 실제 동작에는 영향을 미치지 않지만, 다른 라이브러리가 해당 컴포넌트와 통합되는 방식이나 런타임이 이를 로드하는 방식에는 영향을 줄 수 있습니다.
EOL(지원 종료)된 구성 요소가 더 이상 업데이트되지 않더라도 세상은 계속 돌아갑니다. 따라서 재빌드할 때마다 마치 완전히 새로운 릴리스를 출시할 때와 동일한 수준의 검증이 필요합니다. 성숙한 패치 프로세스는 이러한 점뿐만 아니라, 시간이 지남에 따라 이 소프트웨어를 유지 관리하는 팀의 변화까지 고려해야 합니다.
지식 소멸 문제
EOL(지원 종료)된 오픈소스 구성 요소를 5년에서 10년 동안 유지 관리할 때는, 팀이 직접 개발하지 않은 소프트웨어를 다루게 됩니다. 원래의 유지 관리자들은 이미 자리를 떠났고, 프로젝트 커뮤니티도 흩어졌습니다. 문서가 존재한다고 해도 불완전하거나 구식일 수 있으며, 여러분이 유지 관리하고 있는 EOL 릴리스보다는 최신 버전에 초점을 맞추고 있을 수도 있습니다.
귀하의 팀은 직접 개발하지 않은 컴포넌트를 물려받게 되며, 이는 팀이 결정하지 않은 아키텍처적 판단과 통제할 수 없었던 종속성 선택을 내포하고 있습니다. 이러한 컴포넌트를 안전하게 수정하는 방법을 이해한다는 것은, 이제는 더 이상 문의할 수 없는 사람들이 수년 전에 설계한 낯선 코드베이스와 빌드 프로세스를 익혀야 함을 의미합니다.
이러한 기초 지식이 없다면, 패치 작업의 각 단계는 점점 더 어려워지고 위험도 커집니다. 팀은 문제를 해결하는 것보다 원인을 파악하는 데 더 많은 시간을 소비하게 되며, 미묘한 호환성 문제를 유발할 가능성도 높아집니다. 따라서 성숙한 패치 프로세스는 포괄적인 문서화와 표준화된 절차를 통해 지식의 소실을 대비해야 하며, 이는 개별 구성원이 시스템의 작동 방식을 기억하는 것에 의존하지 않아야 합니다.
프로세스 성숙도의 실제 모습
성숙한 패치 프로세스는 단순히 취약점을 더 빠르거나 더 신중하게 해결하는 것에 그치지 않습니다. 이는 취약점이 언제, 어디서, 얼마나 자주 발생하든 상관없이 안정적으로 작동하는 시스템과 체계적인 절차를 구축하는 것입니다. 성숙한 운영과 사후 대응형 운영을 구분 짓는 요소는 다음과 같습니다:
- 전체 그래프에 걸친 포괄적인 모니터링. 성숙한 프로세스는 고객이 CVE를 보고하기를 기다리지 않습니다. 이들은 지원하는 모든 종속성 그래프의 모든 계층에 걸쳐 취약점 현황을 적극적으로 모니터링합니다. 이들은 관리하는 구성 요소의 내부 구조를 정확히 파악하고 있으며, 문제를 조기에 포착합니다.
- 표준화된 재빌드 및 검증 절차. 모든 패치는 동일한 워크플로를 실행합니다: 패치 적용, 재빌드, 테스트, 검증, 패키징, 배포. 이 절차는 CVE의 심각도나 영향을 받는 구성 요소에 관계없이 변함없이 유지됩니다. 이러한 일관성이야말로 프로세스의 신뢰성을 보장합니다. 어떤 일을 백 번이나 같은 방식으로 반복하면 능숙해집니다. 매번 즉흥적으로 대처하면 놓치는 부분이 생기기 마련입니다.
- 철저한 호환성 테스트. 성숙한 프로세스는 패치된 구성 요소가 단독으로 작동하는지뿐만 아니라, 이를 의존하는 다른 모든 라이브러리와 올바르게 통합되는지까지 검증합니다. 이러한 프로세스는 환경의 변화를 고려하며, 단순히 이상적인 실험실 환경이 아닌 고객이 실제로 운영하는 조건에서 테스트를 수행합니다.
- 예측 가능한 관리 주기와 소통. EOL 소프트웨어에 의존하는 고객은 보안 문제가 지속적으로 해결될 것임을 확신할 수 있어야 합니다. 성숙한 프로세스는 명확한 SLA를 수립하고, 어떤 패치가 언제 적용되었는지에 대해 투명한 소통을 유지하며, 신뢰할 수 있는 채널을 통해 업데이트를 제공합니다.
- 조직의 노하우와 문서화. 수년에 걸쳐 수십 개의 EOL(지원 종료) 구성 요소를 유지 관리할 때는, 우연히 특정 라이브러리를 재빌드하는 방법을 알고 있는 소수의 '영웅'에게만 의존할 수는 없습니다. 성숙한 프로세스는 빌드 절차, 테스트 요구 사항, 알려진 특이 사항, 통합 시 주의할 점 등 모든 것을 문서화합니다. 이러한 지식은 팀원이 바뀌더라도 지속됩니다.
왜 공정상의 완벽함이 장기적인 신뢰성을 결정하는가
변경 사항을 최소화하고 기존 동작을 유지하며 철저한 테스트를 거친 완벽한 패치를 작성했다 하더라도, 이를 둘러싼 프로세스가 부실하다면 문제가 발생할 수 있습니다. 업데이트가 필요한 전이적 의존성을 놓칠 수도 있습니다. 재빌드 과정에서 발생한 패키징 변경으로 인해 하류 통합에 문제가 생길 수도 있습니다. 또는 한 가지 CVE는 수정했지만, 같은 주에 그래프의 다른 부분에 반영된 나머지 두 가지는 간과할 수도 있습니다.
장기적인 오픈소스 지원에서 어려운 점은 단순히 훌륭한 패치를 작성하는 것만이 아닙니다. 수년에 걸쳐 지속적으로 취약점이 발견되는 상황에서도, 패치를 안정적이고 반복적이며 정확하게 제공할 수 있는 체계와 규율을 유지하는 것이야말로 진정한 과제입니다. EOL(지원 종료) 이후 5년 동안의 지원 기간 동안, 이는 복잡한 의존성 구조 전반에 걸쳐 50개 이상의 패치를 적용해야 할 수도 있음을 의미합니다. 이에 대응적으로 대처하려는 조직은 팀의 소진을 초래하고 신뢰할 수 없는 패치를 배포하게 됩니다. 반면 프로세스 성숙도에 투자하는 조직은 혼란 없이 일관된 보안을 제공할 수 있습니다.
이러한 체계는 성숙한 프로세스에서만 비롯됩니다. 즉, 표준화된 워크플로, 포괄적인 모니터링, 엄격한 검증, 그리고 개별 구성원을 넘어 지속되는 조직의 노하우가 바로 그것입니다. TuxCare의 'Endless Lifecycle Support' 는 바로 이러한 기반 위에 구축되었습니다. 10년에 걸쳐 다듬어진 당사의 패치 프로세스는 복잡한 종속성 그래프 모니터링부터 시스템이 필요로 하는 한 검증되고 호환성을 유지하는 패치를 제공하는 것까지, 장기적인 EOL 유지보수의 모든 복잡성을 처리합니다.
프로세스의 완벽함이란, CVE 취약점이 발견될 때마다(그리고 이는 끊임없이 반복될 것입니다) 매번 동일한 방식으로 대응한다는 것을 의미합니다. 패치가 올바르게 적용되는 것이죠. 이것이야말로 장기적으로 진정한 오픈소스의 신뢰성을 결정짓는 요소입니다. 취약점이 전혀 없다는 것이 아니라, 아무리 많은 취약점이 나타나거나 어디에 숨어 있든 이를 처리할 수 있을 만큼 성숙한 프로세스가 갖춰져 있다는 것이 바로 진정한 신뢰성입니다.
오픈소스 소프트웨어(전달 의존성 포함)에 대한 ‘무기한 라이프사이클 지원’에 대해 자세히 알아보려면 여기를 클릭하세요.





