function transformLegacyImportToNewImport(file, { jscodeshift }) { const root = jscodeshift(file.source); /* 오래된 import 문들을 찾음 */ const oldImports = findOldImports(root, { jscodeshift }); /* 오래된 import 문이 없는 파일인 경우, 아무 작업을 하지 않음 */ if (oldImports.length === 0) { return; } for (const oldImport of oldImports) { /* 오래된 import 문에서 Adaptive를 가져오는 부분을 삭제 */ /* (Adaptive만을 가져오는 import 문인 경우, import 문 전체를 삭제) */ removeImportMember(root, oldImport, 'Adaptive', { jscodeshift }); } /* @tossteam/colors에서 adaptive를 import하는 부분을 추가 */ /* (@tossteam/colors를 import하고 있지 않은 경우, import 문을 추가) */ addImportMember(root, '@tossteam/colors', 'adaptive', { jscodeshift }); /* Adaptive 변수를 모두 adaptive로 치환 */ const oldAdaptives = findIdentifiers(root, 'Adaptive', { jscodeshift }); for (const oldAdaptive of oldAdaptives) { jscodeshift(oldAdaptive).replaceWith( jscodeshift.identifier('adaptive') ); } /* 수정된 소스코드를 반환 */ return root.toSource(); }
function removeImportMember(root, importNode, name, { jscodeshift }) { const oldSpecifiers = importNode.value.specifiers; /* name을 import하는 부분을 삭제 */ const newSpecifiers = oldSpecifiers.filter(specifier => { return ( specifier.type !== 'ImportSpecifier' || specifier.imported.name !== name ); } /* 더 이상 import할 것이 남지 않은 경우에는, import 문을 삭제 */ if (newSpecifiers.length === 0) { jscodeshift(importNode).remove(); return; } /* 그렇지 않은 경우, import 문에서 name을 가져오는 부분만 삭제 */ jscodeshift(importNode).replaceWith( jscodeshift.importDeclaration( newSpecifiers, importNode.value.source ) ); }
JSCodeShift로 기술 부채 청산하기
토스 프론트엔드 챕터에서는 100개 이상의 서비스들이 작은 패키지 단위로 쪼개져 활발하게 개발되고 있는데요. 공통으로 사용하는 라이브러리에서 인터페이스가 변경되는 Breaking Change가 발생하면, 의존하고 있는 모든 서비스의 코드를 수정해야 했습니다. 관리하는 코드베이스가 점점 커지면서 해야 하는 작업의 양도 계속 늘어나고는 했습니다. 이에 프론트엔드 챕터는 JSCodeShift를 도입하여 대부분의 코드 수정 작업이 자동화할 수 있었습니다.
https://toss.tech/article/jscodeshift

