의존성 관리, 코드모드 및 AI
요약
개발 과정에서 발생하는 의존성 관리 및 취약점 패치 작업에 많은 시간이 소요되는 문제를 다룹니다. 기존 도구들이 단순히 업데이트 보고서를 제공하는 데 그치는 한계를 지적하며, 코드 변환 패키지인 Codemod가 이 문제의 근본적인 해결책임을 제시합니다.
핵심 포인트
- 의존성 업그레이드는 단순한 버전 변경 이상의 복잡한 코드 수정 작업을 수반한다.
- 기존 도구들은 코드가 실제 어떻게 영향을 받는지까지는 알려주지 못한다.
- Codemod는 AST를 이용해 코드를 파싱하고 변환하여 의존성 업데이트 과정을 자동화할 수 있다.
최근 저는 서비스가 사용하는 의존성을 업그레이드하고, 그 의존성들이 의존하는 모든 패키지들을 업데이트하는 데 너무 많은 시간을 썼습니다. 단지 전체 기반 프레임워크를 새로운 메이저 버전으로 마이그레이션해야만 새 패키지들이 '치명적인' 취약점을 갖지 않게 할 수 있다는 것을 알아내기 위해서였습니다. 개발자들은 취약점 패치를 위해 의존성을 업데이트하거나, 새로운 API를 채택하거나, 사용 중단된(deprecated) API를 대체해야 합니다. 그리고 조직이 '제로-취약성(zero-vulnerability)' 버전을 요구할 때, 그 작업은 고객을 위한 기능을 구축하는 시간에서 빼앗아 갑니다.
기존 도구들
시장에는 Dependabot이나 Renovate처럼 코드베이스 호스팅 플랫폼에 통합되는 몇 가지 도구가 있어 개발자들에게 새롭고 취약점이 없는 버전을 제공합니다. 이들은 필요한 모든 변경 사항을 담은 일일/주간 보고서를 보내거나, 심지어 자동으로 코드 변경(Code Changes)까지 생성해 줍니다. 하지만 이러한 접근 방식으로는 여전히 남아있는 몇 가지 과제들 때문에 전체 문제를 해결하지 못합니다.
기존의 어려움들
개발자들이 의존성을 최신 상태로 유지하도록 돕는 기존 도구들은 다음과 같은 어려움을 가져옵니다:
-
버전 업그레이드는 코드 변경을 의미하지 않습니다. 단순히 어떤 버전으로 업그레이드해야 하는지 아는 것만으로는 삶이 편해지지 않습니다. 매주 GitHub의 Dependabot으로부터 제가 사용하는 취약한 패키지의 새 버전에 대한 보고서를 받지만, 엔지니어로서 저는 보통 그것이 제 코드베이스에 어떤 영향을 미칠지 전혀 알지 못합니다. 변경 사항을 이해하려면 변경 로그(change logs)와 릴리스 노트(release notes)를 확인해야 하며, 여러 주요 버전(major versions)을 업데이트하는 경우 반드시 최신 버전을 확인할 필요는 없습니다. 따라서 개발자들은 새로운 API와 그것이 코드베이스에 미치는 영향에 익숙해져야 합니다.
-
버전 업그레이드는 소유한 모든 코드베이스에서 수행되어야 합니다. 동일하게 취약하거나 사용 중단된(deprecated) 패키지는 보통 팀이 소유한 모든 코드베이스에서 사용됩니다. 저희 팀은 여러 서비스와 코드베이스를 소유하고 있으며, 각 하나를 검토하며 패키지를 반복적으로 업데이트하는 데 상당한 시간을 소비합니다. 심지어 AI에게 각각의 코드베이스에 대해 수행하도록 요청하더라도 컨텍스트 오버플로우(context overflow)가 발생하고 이를 압축하면 정보 손실이 발생합니다. 개발자들이 업그레이드에 어느 정도 익숙해진다 하더라도, 각 코드베이스는 비즈니스 도메인 구현과 패키지 자체의 사용 측면에서 고유한 특성을 가지고 있습니다.
-
라이브러리는 독립적으로 작동하지 않습니다. 라이브러리는 보통 다른 패키지를 기반으로 구축되며, 해당 종속성(dependencies)이 미리 설치되어야 합니다. 코드베이스에서 하나의 라이브러리 버전을 업그레이드하는 것이 그 피어 종속성(peer dependencies)에 대해 설정된 제약 조건을 깨뜨릴 수 있습니다. 이는 JavaScript/Typescript 세계에서 발생합니다.
-
최신 변경 로그가 모든 이야기를 알려주지는 않습니다. 주요 버전(major versions)을 많이 업그레이드할수록 코드베이스를 조정하기가 더 어려워집니다. 일반적으로 주요 버전 업그레이드는 라이브러리 API에 호환되지 않는 변경 사항(breaking changes)을 도입하며, 하나 이상 건너뛰는 것은 그 사이에 있는 모든 버전을 검토해야 함을 의미합니다.
코드모드(Codemod)가 구세주입니다
Codemod란 무엇인가요?
Codemod는 'code modification'의 약자로 코드 변환 패키지입니다. 이는 코드베이스의 추상 구문 트리(Abstract Syntax Tree, AST)를 사용하여 코드를 파싱하고, 변환하며, 새로운 버전으로 생성하는 방식으로 작동합니다. Codemod에 정의된 규칙을 따르면서도 관련 없는 코드는 깨뜨리지 않고 정확한 코드 수정을 수행할 수 있습니다. Codemod에 대한 더 자세한 내용은 여기를 참고하세요.
Codemod, 의존성 및 AI
새 버전의 패키지가 도입하는 API 변경 사항은 코드베이스 전반에 걸쳐 구문적으로 동일합니다. 이것이 codemod 접근 방식을 매우 유용하게 만듭니다. 새 버전의 API 변경을 적용하려면 현재 버전이 코드베이스에서 어떻게 사용되는지, 즉 어떤 API 표면(api surface)이 사용되는지 알아야 합니다. 또한 해당 라이브러리의 변경 로그와 릴리스 노트에 있는 모든 하위 호환성 깨짐(breaking changes) 사항을 기록해야 합니다. 전자에 관해서는 정적 코드 분석 도구를 사용하여 코드를 '추상 구문 트리' 구조로 파싱하고 업그레이드하려는 의존성의 모든 사용 사례를 찾을 수 있습니다. 후자에는 LLM 모델이 정보를 수집하고 요약하는 데 매우 능숙하기 때문에 AI를 활용하여 이 과정을 더 빠르게 만들 수 있습니다. 이러한 모든 정보를 LLM의 컨텍스트로 갖추고, Codemod 작성에 특화된 AI 에이전트(AI agents)를 사용하여 codemod 패키지를 생성할 수 있습니다. 이 접근 방식의 몇 가지 장점은 다음과 같습니다:
-
결정론적이고 반복 가능함(Deterministic and repeatable). 동일한 입력은 항상 동일한 출력을 생성합니다. 리베이스 후, 새 브랜치에서, 또는 팀원이 이전 API를 사용하는 코드를 추가한 후에 다시 실행해도 일관된 결과를 얻을 수 있습니다. 에이전트에게 두 번 질문하면 서로 다른 답변을 받을 수 있습니다.
-
코드에 적용되기 전에 테스트됨(Tested before it touches your code). 코드모드(codemod)는 before/after 테스트 피처(test fixtures)를 포함하므로, 프로젝트의 테스트 스위트가 변경된 코드를 우연히 커버하는지 여부와 관계없이 변환 자체가 자체적으로 검사됩니다.
-
프로젝트 전반에 걸쳐 재사용 가능함(Reusable across projects). 에이전트가 생성한 코드모드는 하나의 저장소(repo)에만 도움을 줍니다. 'lib X, 5 → 6'에 대한 코드모드는 해당 업그레이드를 진행하는 모든 프로젝트에서 작동합니다. 코드모드는 조직 내부의 비공개 레지스트리나 공개 레지스트리에 공유될 수 있어 에이전트가 접근할 수 있습니다.
-
시간이 지날수록 비용 효율적임(It gets cheaper over time). LLM 비용은 코드모드가 작성될 때 한 번만 지불됩니다. 이후의 모든 실행은 토큰, 속도 제한, 시간 초과 없이 빠르고 로컬한 AST 변환으로 이루어집니다.
-
대규모 코드베이스에서 정확함(Precise on large codebases). 파일별로 작업하는 에이전트는 컨텍스트를 놓치거나, 파일을 누락하거나, 도중에 이탈할 수 있습니다. 코드모드는 저장소에 10개의 파일이 있든 10,000개가 있든 모든 파일에 동일한 규칙을 적용합니다.
-
범위가 좁고 부수적인 손상이 적음(Narrow scope, less collateral damage). 코드모드는 목표로 하는 코드 패턴에만 영향을 미칩니다.
코드베이스가 원래 다루지 않았던 사용 패턴, 예를 들어 새로운 import 스타일이나 특정 프로젝트의 엣지 케이스를 가질 때 새로운 사례가 추가될 수 있습니다. 이는 처음부터 시작하는 대신 기존 코드모드에 새로운 규칙과 테스트로 추가됩니다.
저는 이 아이디어를 검증하고 의존성 업그레이드를 가능한 한 쉽게 만들기 위해 Apiweiser를 구축하고 있습니다. 현재는 Typescript의 node 프로젝트만 지원합니다. 사용자가 자신의 코드베이스에서 로컬로 실행할 수 있으며, 원하는 모델과 코딩 하네스를 사용할 수 있습니다. 이 도구가 더 유용하고 사용하기 쉬워지며 가능한 한 많은 불편함을 줄일 수 있도록 어떤 피드백이라도 감사하게 생각하겠습니다. 여기에서 확인하실 수 있습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기