상황
기존의 commonjs로 작성된 서버를 esmodule로 바꾸는 상황이에요. 왜 바꾸냐하면 esm 모듈이 표준으로 많이 바뀐다고 해서 바꿨어요.
준비
🟦 package.json의 설정
package.json
파일에 "type": "module"
을 설정하면, Node.js가 해당 프로젝트의 JavaScript 파일을 ES 모듈(ESM) 방식으로 해석해요. 기본적으로 Node.js는 CommonJS 모듈 시스템을 사용하지만, 이 설정을 추가하면 .js 파일에서도 import
와 export
구문을 사용할 수 있게 돼요.
🟦 tsconfig.json 설정
typescript 컴파일러가 ts 파일을 js로 변환할 때 어떤 모듈 방식으로 변환해야할지 설정시켜요.
target
은 output되는 js코드의 ecmascript 버전을 결정해요.
module
은 컴파일된 JavaScript 코드가 어떤 모듈 시스템을 사용할지를 결정해요
🟩 그러면 pacakage.json과 tsconfig의 module은 뭔차이?
package.json
에 설정하는 "type": "module"
은 런타임에서 Node.js가 해당 프로젝트의 JavaScript 파일을 어떻게 해석할지 결정하는 옵션이에요.
tsconfig.json
의 "module"
옵션은 TypeScript 컴파일러가 코드를 어떤 모듈 시스템 형식으로 변환할지를 지정해요
🟩 tsconfig.json 파일
{
"compilerOptions": {
"target": "ESNext", // 생성되는 JavaScript의 버전을 최신 ECMAScript로 설정해요.
"module": "NodeNext", // Node.js의 ESM 방식에 맞춰 모듈 시스템을 설정해요.
"moduleResolution": "nodeNext", // Node.js의 ESM 방식에 맞는 모듈 해석 방법을 사용해요.
"rootDir": "./src", // 소스 코드의 루트 디렉토리를 지정해요.
"baseUrl": "./", // 절대 경로 기준 디렉토리를 설정해요.
"paths": { // 경로 별칭 설정으로 모듈 임포트를 간소화할 수 있어요.
"@lib/*": ["src/lib/*"],
"@config/*": ["src/config/*"],
"@models/*": ["src/models/*"],
"@dao/*": ["src/dao/*"],
"@service/*": ["src/service/*"],
"@routes/*": ["src/routes/*"],
"@migrations/*": ["src/migrations/*"],
"@utils/*": ["src/utils/*"],
"@middlewares/*": ["src/middlewares/*"],
"@dummyData/*": ["src/dummyData/*"]
},
"resolveJsonModule": true, // JSON 파일도 모듈처럼 import 할 수 있도록 해요.
"noImplicitAny": false, // 암시적인 any 타입 사용을 허용해요.
"declaration": true, // 타입 정의 파일(.d.ts)을 생성해요.
"declarationMap": true, // 선언 파일에 대한 소스맵을 생성해요.
"outDir": "./build", // 컴파일된 파일이 저장될 디렉토리를 지정해요.
"esModuleInterop": true, // CommonJS 모듈과의 호환성을 높여줘요.
"preserveSymlinks": false, // 심볼릭 링크를 원본 경로로 해석하도록 설정해요.
"forceConsistentCasingInFileNames": true, // 파일명 대소문자의 일관성을 강제해요.
"strict": true, // 엄격한 타입 검사를 활성화해요.
"skipLibCheck": true // 외부 라이브러리의 타입 검사를 건너뛰어 컴파일 속도를 높여줘요.
},
"include": [
"src/**/*" // src 폴더 내의 모든 파일을 컴파일 대상으로 포함해요.
],
"exclude": [
"node_modules", // 외부 라이브러리는 컴파일 대상에서 제외해요.
"build" // 컴파일된 결과물은 제외해요.
]
}
여러가지 옵션이 있어요.
import에서 alias를 사용하기 위해서 paths 옵션을 사용해요.
🟦 pacakage.json의 script 설정
"scripts": {
"type-check": "tsc --noEmit",
"build:tsc": "tsc && tsc-alias",
"build": "cross-env swc ./src -d build --strip-leading-paths",
"dev": "cross-env nodemon --watch \\"src/**/*.ts\\" --ext ts --exec \\"node --loader @swc-node/register/esm src/index.ts\\"",
"start": "node build/index.js",
"test": "vitest",
},
🟩 types-check
안타깝게도 swc를 사용하면 type check가 안되요. 그래서 tsc로 타입을 체크하는 것을 만들었어요.
🟩 build
cross-env가 있는데요. 이건 왜쓰냐면 운영체제에 상관없이 환경 변수를 설정할 수 있도록 하기 위해서 에요.
윈도우와 리눅스, 맥 등의 환경에서 환경 변수를 설정하는 방식이 다르기 때문에, cross-env를 사용하면 스크립트 내에서 동일한 명령어로 환경 변수를 설정할 수 있어요.
swc로 실행하는데요. —strip-leading-paths
옵션은 컴파일 결과물에서 파일 경로의 앞부분에 붙은 불필요한 경로 정보를 제거하는 역할을 해요. 즉, build 파일에 컴파일된 결과값들이 절대경로 형태로 들어가게 되요. ex) build/src/…
저는 build/… 형태로 빌드 결과를 얻고싶어서 옵션을 사용했어요.
🟩 build:tsc
기존 tsc로 빌드하는 거에요. alias를 적용해야하니 tsc-alias
페키지가 필수에요. npm i -D tsc-alais
🟩 dev
nodemon
패키지를 사용했어요. 기존에는 tsc-watch
패키지를 사용했는데 esm
모듈을 실행하는데 어려움이 있어서 nodemon으로 바꿨어요.
nodemon은 기본적으로 .js
파일만 감시할 수 있어요. ts
파일의 변경을 감지하도록 --ext ts
옵션을 추가해야해요.
src 밑 ts 파일이 변경되면 자동으로 node --loader @swc-node/register/esm src/index.ts
명령어를 실행시켜줘요.
--loader
옵션은 Node.js의 모듈 로딩 과정에 커스텀 로더를 삽입해요.
@swc-node/register/esm
로더는 typescript나 최신 ecmascript 문법을 일반적인 js코드로 변환해요. swc를 활용해서 소스 코드를 nodejs가 이해할 수 있는 js로 실행되도록 만들어주는 거에요.
🟦 .swrrc
{
"$schema": "<https://json.schemastore.org/swcrc>", // SWC 설정에 대한 JSON 스키마 URL. 올바른 구성 옵션 검증에 도움을 줘요.
"jsc": { // SWC의 JavaScript/TypeScript 컴파일러 설정 영역입니다.
"target": "es2020", // 출력될 JavaScript 코드의 ECMAScript 버전을 es2020으로 설정해요.
"parser": { // 소스 코드 파싱 옵션을 지정합니다.
"syntax": "typescript", // 소스 코드가 TypeScript 문법을 사용함을 지정해요.
"tsx": false, // TSX (JSX in TypeScript) 사용 여부. 여기서는 사용하지 않아요.
"decorators": true // 데코레이터 문법을 사용하도록 활성화해요.
},
"baseUrl": "./", // 모듈 해석 시 기준 디렉터리를 현재 프로젝트 루트로 설정해요.
"paths": { // 모듈 경로 별칭을 설정하여 import 구문을 간소화할 수 있어요.
"@lib/*": ["src/lib/*"],
"@config/*": ["src/config/*"],
"@models/*": ["src/models/*"],
"@dao/*": ["src/dao/*"],
"@service/*": ["src/service/*"],
"@routes/*": ["src/routes/*"],
"@migrations/*": ["src/migrations/*"],
"@utils/*": ["src/utils/*"],
"@middlewares/*": ["src/middlewares/*"],
"@dummyData/*": ["src/dummyData/*"]
},
"keepClassNames": true // 출력 코드에서 클래스 이름을 보존하여 디버깅이나 런타임 리플렉션에 유용하게 사용돼요.
},
"module": {
"type": "es6" // 출력 모듈 시스템을 ES6 모듈(ESM)로 설정해요.
},
"sourceMaps": true, // 디버깅을 위해 소스맵 생성을 활성화해요.
"exclude": [
"node_modules", // 컴파일 대상에서 node_modules 폴더를 제외해요.
"build" // 이미 생성된 빌드 결과물 폴더도 제외해요.
]
}
swc
가 컴파일할 때 사용되는 규칙들이에요. root 폴더에 존재해요.
build 될 때 alias도 이 .swcrc
설정 파일에서 설정할 수 있어요.
'웹 > TypeScript' 카테고리의 다른 글
[Typescript] 디자인 패턴을 적용해보다 (0) | 2024.11.26 |
---|---|
[Typescript] typescript이 컴파일 되는 기준과 d.ts파일 (0) | 2024.11.25 |
typescript에서 …(전개 연산자)을 string에 쓴다면 (0) | 2023.04.26 |
[Typescript] react, typescript에서 변수를 다른 파일에서 사용할 때 만난 TS1184: Modifiers cannot appear here 오류 (0) | 2023.03.23 |
Typescript에서 string key로 객체 접근하기 (0) | 2023.02.01 |