개발하다보면 시간이 지나면서 라이브러리가 deprecated되고,
라이브러리 버전업 및 마이그레이션을 해야하는 경우가 생기는데요.
또한, 디자인 시스템을 만들면서 기능 및 인터페이스가 deprecated 되거나 변경되는 케이스가 존재했는데
그때를 위한 좋은 라이브러릴 하나 찾아서 공유해봅니다.
1. jscodeshift란 무엇인가?
jscodeshift는 Facebook(현 Meta)에서 개발한 JavaScript 코드베이스 변환 도구입니다.
이 도구는 Abstract Syntax Tree(AST)를 사용하여 코드의 구조를 이해하고, 필요한 변환을 자동으로 수행할 수 있게 해줍니다.
(위 그림을 보시면 좀 무서울수도 있는데 codemod Studio나 chatgpt를 사용하시면 손쉽게 사용 가능합니다...)
이 도구는 특히 대규모 코드베이스에서 일관된 코드 스타일 적용, API 변경에 따른 대규모 리팩토링, 혹은 레거시 코드에서 최신 문법으로의 변환 작업 등에 매우 유용합니다.
jscodeshift를 찾기 전엔 아래 방법을 사용했었는데요,
1. vscode의 전체 검색 및 변경으로 대응
2. file I/O 스크립트+정규식을 통하여 변경
다음 케이스는 대응이 어려웠습니다. (실제로 업무중 발생한 케이스)
1. 함수/클래스 인터페이스가 변경되는 경우
// 변경전
<Dialog Trigger={TriggerComponent}>
<Dialog.Header />
<Dialog.Content />
</Dialog>
// 변경 후
<Dialog>
<Dialog.Trigger asChild>
<TriggerComponent />
</Dialog.Trigger>
<Dialog.Content>
<Dialog.Header/>
<Dialog.Body/>
</Dialog.Content>
</Dialog>
예를 들어서 react에서 props로 넘기던 컴포넌트를
children으로 주입해주게 리펙토링 하는 경우 대응이 어려웠습니다.
2. import 경로가 바뀌는 경우, 혹은 일부만 아예 다른 경로로 바뀌는 경우
// 이전
import { useLoginSession, anotherHook } from '@/hooks/login'
// 이후
import { useLoginSession } from '@/entities/auth'
import { anotherHook } from '@/hooks/login'
그외에도 정규식만으로 대응하기는 어려운 케이스가 수십, 수백 케이스 있겠죠. 특히 라이브러리 migration이 골치아팠었습니다.
그럼 쓰는 예시를 코드로 한번 봅시다.
jscodeShift 코드 예시
2번 케이스가 간단하니 코드로 한번 봅시다.
export default function transformer(file, api) {
const j = api.jscodeshift
const root = j(file.source)
root
.find(j.ImportDeclaration, {
source: { value: '@/hooks/login' },
})
.forEach((path) => {
const useLoginSessionSpecifier = path.node.specifiers.find(
(specifier) => specifier.imported && specifier.imported.name === 'useLoginSession',
)
if (useLoginSessionSpecifier) {
// 경로를 '@/entities/auth'로 변경
path.node.source.value = '@/entities/auth'
// 다른 import가 있다면 분리
const otherSpecifiers = path.node.specifiers.filter((specifier) => specifier !== useLoginSessionSpecifier)
if (otherSpecifiers.length > 0) {
// 원래 import 구문에서 useLoginSession을 제거
path.node.specifiers = [useLoginSessionSpecifier]
// 새로운 import 구문 추가
const newImport = j.importDeclaration(otherSpecifiers, j.literal('@/hooks/login'))
j(path).insertAfter(newImport)
}
}
})
return root.toSource()
}
과정을 글로 설명하면 다음과 같습니다.
1. code를 AST 트리로 파싱합니다.
2. AST 트리에서 변경하고 싶은 부분을 찾아냅니다.
3. 변경을 적용합니다.
4. 적용한 코드를 내보냅니다. (마지막 코드 부분)
1,2,3번이 좀 어려울 수 있는데 codemod(https://codemod.com/studio) 를 사용하거나,
ChatGPT 같은 AI의 도움을 받으면 빠르고 손쉽게 변경 가능합니다.
ai를 사용한다면 내가 하고 싶은 과정을 step by step으로 잘 풀어내는 게 중요하겠네요.
결론
codemod 와 jscodeshift를 사용하면 자동화된 스크립트를 통하여 손쉽게 바꿀 수 있습니다.
저는 요즘 디자인 시스템 개발 & 기존 코드 migration을 하고 있었는데, 여러 팀이 동시에 작업을 하다보니
기존 개발 되었던 컴포넌트의 기본 인터페이스가 잘못되었다고 판단되어도
다른 팀의 프로젝트에 이미 쓰고 있으니 변경이 매우 골치아팠었는데 리펙토링 후 migration 스크립트를 같이 제공하는것으로 변경과 확장에 매우 유연해질 수 있었습니다.
좋은 라이브러리 찾아서 공유해봅니다 ㅎㅎ
'Front-end > JavaScript' 카테고리의 다른 글
commonjs와 ESM의 차이 (0) | 2023.07.25 |
---|---|
pnpm 도입기 (feat: 모노 레포) (0) | 2023.07.15 |
자바스크립트의 async/await에 대해서 (0) | 2022.03.31 |
JS로 Single Page Application 구현 (0) | 2022.03.12 |
Generator (0) | 2022.02.02 |