본문 바로가기
일지/FlowFroge(GTDList)

FlowForge(GTDList) 04-03 일지 Typescript Test / Build(Babel) 환경 기록

by 리나그(ReenAG) 2024. 4. 4.
728x90
반응형

 여기서는 간단하게 typescript로 작성된 코드의 경우 어떻게 테스팅 환경을 짜면 좋은지를 기록해두려고 한다. 지금은 backend를 먼저 바꾸고 있는데, 거기서 어떻게 했는지 알아내면 frontend에서도 바로 적용이 가능하기 때문이다. 

 

테스트환경은 jest를 쓰기로 했다. 공식적으로 typescript를 지원하고, 문서 지원도 되어있기에 선택했다.

 

https://jestjs.io/docs/getting-started

 

Getting Started · Jest

Install Jest using your favorite package manager:

jestjs.io

 

다만 이게 엄청난 스노볼이 되어서 또 다른 삽질을 불러일으키기는 했다.

babel이라는 트랜스파일러를 이용해서 체크를 하는 방법이 소개되어 있는데, 그냥 그걸 하는 김에 바벨을 이용해 보기로 한 것이 음... 하여간에 관련한 이야기는 또 뒤에 할 것이다.

 

1. 우선 jest를 설치한다.

yarn add --dev jest ts-jest @jest/globals

 

2. eslint.json을 고쳐준다.

 

명확하게 이게 뭐 하는지는 모르겠다. 일단 getting started에 적혀있는 말로는 jest를 이용할 때 생기는 일종의 전역변수들을 eslint 측에서 인식하게 하게 해 준다는 것 같아서 필요한 듯해서 넣어두었다.

    ...
    "overrides": [
        {
            "files": ["test/**/*"],
            "env": {
            "jest": true
            }
        }
    ]
    ...


내가 봤을 땐 jest만 썼으면 딱히 큰 문제가 생기지 않았을 것 같은데... 말한 대로 babel을 한번 이용해 보고자 했던 게 지금 해결이 되지 않은 상태이다.

 

babel에 대해 내가 이해한 바로는, "ECMA2015+ 이상의 javascript를 이전에서도 동작하도록 하게끔 고쳐 써주는 트랜스파일러"로 알고 있다.

tsc와 비슷하게 구문분석이 가능한 스택이어서 그런가 모르겠는데... typescript 컴파일을 이 녀석도 할 수 있는 것 같다...?

왜지? 정확히는 모르겠지만...

하여간에 tsc를 대체하는 무언가가 생겼기 때문에, 기존의 런타임으로 이용하고 있었던 npx tsx만 확보하기보다는, (즉, ts로만 돌리기보다는) build 스크립트를 짜서 조금이라도 최적화를 해보는 것이 어떤가 하는 생각이 들어서 일단 babel을 한번 껴보기로 했다.(지금 생각해 보니 이것도 좀 바보 같은 생각인 게, 옛날 코드로 변환시켜 주는데 빨리 돌아가지는 않을 것 같다.)

 

근데 decorator가 여기서 또 복병이 될 거라고는 생각조차 못했는데...

 

일단 설치 과정은 대충 이랬던 것 같다 :

 

1. babel 설치

yarn add --dev @babel/cli @babel/core @babel/plugin-proposal-decorators @babel/preset-env @babel/preset-typescript

 

2. babel.config.cjs 설정 (babel.config.js와 같다 그냥 module.export 문법상 편의를 위해서 그렇게 해두었다.)

// eslint-disable-next-line no-undef
module.exports = {
    presets: [
        '@babel/preset-typescript',
        ['@babel/preset-env', {targets: {node: 'current'}}],
        ["@babel/plugin-proposal-decorators", { "version": "2023-11" }],
    ],
};

 

3. tsconfig 설정

...
// Ensure that .d.ts files are created by tsc, but not .js files
"declaration": true,
"emitDeclarationOnly": true,
// Ensure that Babel can safely transpile files in the TypeScript project
"isolatedModules": true,
"outdir": "./lib",
...

여기서 outdir를 babel이 build 할 때의 output dir과 같은 곳으로 설정되어야지 제대로 컴파일이 되는 것으로 보인다.  d.ts만 내보낸다. (타입체킹만 시킬 예정.)

 

4. package.json buld 설정

"scripts": {
	...
    "build": "tsc && babel src --out-dir lib --extensions \".ts,.tsx\" --source-maps inline",
	...
 },

 

이 자료도 참고하면 좋다.

https://github.com/microsoft/TypeScript-Babel-Starter/blob/master/package.json#L5

 

TypeScript-Babel-Starter/package.json at master · microsoft/TypeScript-Babel-Starter

A sample setup using Babel CLI to build TypeScript code, and using TypeScript for type-checking. - microsoft/TypeScript-Babel-Starter

github.com

 

여기까지는 잘되는가 싶었는데... 이딴 에러가 튀어나왔다. decorator 때문에 새로 추가한 라이브러리에서 문제가 생겼는데,

$ yarn run build
yarn run v1.22.17
$ tsc && babel src --out-dir lib --extensions ".ts,.tsx" --source-maps inline
Error: Cannot find package '@babel/preset-plugin-proposal-decorators' imported from C:\everything\Studies\Coding\GTDList\gtdlist-server\babel-virtual-resolve-base.js
    at new NodeError (C:\everything\Studies\Coding\GTDList\gtdlist-server\node_modules\@babel\core\lib\vendor\import-meta-resolve.js:194:5)
    at packageResolve (C:\everything\Studies\Coding\GTDList\gtdlist-server\node_modules\@babel\core\lib\vendor\import-meta-resolve.js:908:9)
    at moduleResolve (C:\everything\Studies\Coding\GTDList\gtdlist-server\node_modules\@babel\core\lib\vendor\import-meta-resolve.js:937:20)
    at defaultResolve (C:\everything\Studies\Coding\GTDList\gtdlist-server\node_modules\@babel\core\lib\vendor\import-meta-resolve.js:1007:15)
    at resolve (C:\everything\Studies\Coding\GTDList\gtdlist-server\node_modules\@babel\core\lib\vendor\import-meta-resolve.js:1020:12)
    at tryImportMetaResolve (C:\everything\Studies\Coding\GTDList\gtdlist-server\node_modules\@babel\core\lib\config\files\plugins.js:142:45)
    at resolveStandardizedNameForImport (C:\everything\Studies\Coding\GTDList\gtdlist-server\node_modules\@babel\core\lib\config\files\plugins.js:164:19)
    at resolveStandardizedName (C:\everything\Studies\Coding\GTDList\gtdlist-server\node_modules\@babel\core\lib\config\files\plugins.js:173:22)
    at loadPreset (C:\everything\Studies\Coding\GTDList\gtdlist-server\node_modules\@babel\core\lib\config\files\plugins.js:61:20)
    at loadPreset.next (<anonymous>)
    at createDescriptor (C:\everything\Studies\Coding\GTDList\gtdlist-server\node_modules\@babel\core\lib\config\config-descriptors.js:140:16)
    at createDescriptor.next (<anonymous>)
    at step (C:\everything\Studies\Coding\GTDList\gtdlist-server\node_modules\gensync\index.js:261:32)
    at evaluateAsync (C:\everything\Studies\Coding\GTDList\gtdlist-server\node_modules\gensync\index.js:291:5)
    at C:\everything\Studies\Coding\GTDList\gtdlist-server\node_modules\gensync\index.js:44:11
    at Array.forEach (<anonymous>)
    at Function.async (C:\everything\Studies\Coding\GTDList\gtdlist-server\node_modules\gensync\index.js:43:15)
    at Function.all (C:\everything\Studies\Coding\GTDList\gtdlist-server\node_modules\gensync\index.js:216:13)
    at Generator.next (<anonymous>)
    at createDescriptors (C:\everything\Studies\Coding\GTDList\gtdlist-server\node_modules\@babel\core\lib\config\config-descriptors.js:102:41)
    at createDescriptors.next (<anonymous>)
    at createPresetDescriptors (C:\everything\Studies\Coding\GTDList\gtdlist-server\node_modules\@babel\core\lib\config\config-descriptors.js:96:17)
    at createPresetDescriptors.next (<anonymous>)
    at C:\everything\Studies\Coding\GTDList\gtdlist-server\node_modules\@babel\core\lib\gensync-utils\functional.js:39:27
    at Generator.next (<anonymous>)
    at mergeChainOpts (C:\everything\Studies\Coding\GTDList\gtdlist-server\node_modules\@babel\core\lib\config\config-chain.js:350:34)
    at mergeChainOpts.next (<anonymous>)
    at chainWalker (C:\everything\Studies\Coding\GTDList\gtdlist-server\node_modules\@babel\core\lib\config\config-chain.js:316:14)
    at chainWalker.next (<anonymous>)
    at loadFileChain (C:\everything\Studies\Coding\GTDList\gtdlist-server\node_modules\@babel\core\lib\config\config-chain.js:191:24)
    at loadFileChain.next (<anonymous>)
    at buildRootChain (C:\everything\Studies\Coding\GTDList\gtdlist-server\node_modules\@babel\core\lib\config\config-chain.js:77:27)
    at buildRootChain.next (<anonymous>)
    at loadPrivatePartialConfig (C:\everything\Studies\Coding\GTDList\gtdlist-server\node_modules\@babel\core\lib\config\partial.js:72:62)
    at loadPrivatePartialConfig.next (<anonymous>)
    at loadFullConfig (C:\everything\Studies\Coding\GTDList\gtdlist-server\node_modules\@babel\core\lib\config\full.js:36:46)
    at loadFullConfig.next (<anonymous>)
    at Function.<anonymous> (C:\everything\Studies\Coding\GTDList\gtdlist-server\node_modules\@babel\core\lib\transform-file.js:24:44)
    at Generator.next (<anonymous>)
    at step (C:\everything\Studies\Coding\GTDList\gtdlist-server\node_modules\gensync\index.js:269:25)
    at C:\everything\Studies\Coding\GTDList\gtdlist-server\node_modules\gensync\index.js:273:13
    at async.call.result.err.err (C:\everything\Studies\Coding\GTDList\gtdlist-server\node_modules\gensync\index.js:223:11)
    at C:\everything\Studies\Coding\GTDList\gtdlist-server\node_modules\gensync\index.js:37:40 {
  code: 'ERR_MODULE_NOT_FOUND'
}
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

 

보니까 일단 

1. @babel/preset-plugin-proposal-decorators라는, 기존의 @babel/plugin-proposal-decorators와 비슷하지만 존재하지 않는 라이브러리를 참고한다.

2. 해당 라이브러리를 찾는. js파일은 잠시 컴파일할 때만 존재하는 듯하기에, 내가 파일 내용을 알 수도 없고 알아도 딱히 의미는 없을 것 같다.

3. 아직 컴파일이 제대로 시작되기도 전, config에서 참조할 때부터 문제가 생기는 듯하다.

 

우선 3번째 추측을 한번 증명해 보기 위해서 build input을 src에서 100% 컴파일이 될 녀석으로, tempsrc라는 디렉터리로 바꾸어 주었는데, 같은 에러가 나왔다. 여기서 babel.config.js에 있던 config를 날렸는데, 역시 제대로 되지 않는다. 제대로 라이브러리가 설치가 되지 않거나 충돌이 일어난 듯한데, 다시 깔아 봐야겠다.

 

그렇게 다시 깔아보다가 결국 이유를 발견했는데... babel.config.js의 구조에 대해서 찾아보다가 preset과 plugin이 다른 옵션이라는 것을 인지하지 못하고 있었다는 사실을 알아냈다...

// eslint-disable-next-line no-undef
module.exports = {
    presets: [
        '@babel/preset-typescript',
        ['@babel/preset-env', {targets: {node: 'current'}}],
    ],
    plugins: [
        ["@babel/plugin-proposal-decorators", { "version": "2023-11" }]
    ]
};

 

이렇게 하니까 잘만 된다. 나는 여태까지 plugins에 넣어야 할 걸 presets에다가 만 넣어두고 있었던 것이다. 그러면 위의 이상한 behavior도 설명된다. plugins에 넣을 걸 preset에 넣으니까, 그에 대해당하는 preset 라이브러리를 찾고 있었던 게 아닐까? build, lint, test 같은 기초 유틸리티를 갖추고 나니까 js 생태계를 조금이라도 더 둘러본 기분이다.

 

 

하지만 아직 끝나지 않았다. 빌드에 성공했다면 적어도 돌아가는지 확인은 해야지. 하지만 commonjs 환경이 아니라고 node는 실행을 시켜주지 않는다.

찾아보니까 @babel/node를 써도 되.지.만!

느리다네요?

https://github.com/babel/example-node-server

 

GitHub - babel/example-node-server: Example Node Server w/ Babel

Example Node Server w/ Babel. Contribute to babel/example-node-server development by creating an account on GitHub.

github.com

그래서 이 녀석을 참조하면 되는 듯하다.

오늘 안에 아예 생 node로 돌리는 것까지 기록하고 싶었는데 너무 졸리다. 일단 내일 또 시도해 보도록 하겠다.

728x90
반응형