안녕하세요 dev_writer입니다.
오늘은 다소 심플한 주제로, JS/TS 프로젝트를 Webstorm에서 시작할 때 어떻게 하면 좀 더 편하게 시작할 수 있는지 정리해 보는 글을 작성해 보겠습니다.
그동안 IntelliJ에서 스프링 프로젝트만 진행했다 보니 JS/TS 신규 프로젝트를 Webstorm에서 시작하는 방법을 자주 찾게 되었는데, 이 참에 블로그에 정리해 두면 개인적으로도 요긴하게 쓰일 것 같아 정리해보고자 합니다.
실행 환경: Mac
실행 언어: TypeScript
실행 프레임워크: Express
Webstorm, nvm, node는 컴퓨터에 설치되어 있다고 가정합니다. React 라이브러리를 쓰던, Nest.js 프레임워크를 쓰던 Eslint나 Prettier 설정은 본 글과 동일하게 적용될 수 있기에 그런 차원에서도 작성하겠습니다.
1단계: 빈 프로젝트 생성
Webstorm에서 빈 프로젝트를 생성합니다.
2단계: npm init
npm init을 이용하여 프로젝트 초기 설정을 진행합니다.
정의해 둔 값이 없다면 각 단계에서 엔터만 입력해도 무방합니다.
devholic@devholicui-MacBookAir express % npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.
See `npm help init` for definitive documentation on these fields
and exactly what they do.
Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.
Press ^C at any time to quit.
package name: (express)
version: (1.0.0)
description:
entry point: (index.js)
test command:
git repository:
keywords:
author:
license: (ISC)
About to write to /Users/devholic/Desktop/express/package.json:
{
"name": "express",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"description": ""
}
Is this OK? (yes)
3단계: npm 패키지 설치
다음으로는 필요한 패키지들을 설치합니다.
// Express
npm i express
npm i --save-dev @types/express
// TypeScript
npm i --save-dev typescript ts-node
// Nodemon
npm i --save-dev nodemon
// ESLint & Prettier
npm i --save-dev eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-config-prettier prettier
- Express: 본 글에서 진행할 프레임워크입니다.
- @types/express: express 모듈에 대한 타입을 지원합니다. tsconfig.json에서의 Any 타입을 규제한다면 (noImplicitAny) express를 임포트 할 때 에러가 발생하기 때문에 설치해 둡니다.
- TypeScript: 본 글에서 진행할 언어입니다.
- ts-node: TypeScript 코드를 실행할 수 있도록 해주는 Node.js 실행기입니다. TypeScript 파일을 바로 실행할 수 있게 해 줍니다. (선택 사항)
- Nodemon: 자동으로 변경 사항을 감지하고 재시작해 주는 도구입니다.
- ESLint: 코드 퀄리티를 보장하도록 도와주는 도구입니다.
- @typescript-eslint/parser: ESLint는 순수한 자바스크립트만 이해할 수 있기 때문에, 타입스크립트에서도 적용되기 위해 설치합니다.
- @typescript-eslint/eslint-plugin: 타입스크립트 전용 추가 규칙을 제공합니다.
- eslint-config-prettier: ESLint와 Prettier 간의 충돌을 방지합니다.
- Prettier: 일관된 텍스트 작성을 도와주는 도구입니다.
4단계: 각 설정 파일 작성
각 설정 파일들을 프로젝트 루트에 작성해 둡니다.
타입스크립트 설정 작성 (tsconfig.json)
package.json에서의 module은 별도로 지정하지 않았습니다. (즉, node 환경은 CommonJS)
{
"compilerOptions": {
"target": "ES6",
"module": "CommonJS",
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"esModuleInterop": true,
"sourceMap": true, // 선택
"outDir": "./dist" // 선택
},
"include": [
"src/**/*.ts",
"tests/**/*.spec.ts",
]
}
- compilerOptions: 타입스크립트 컴파일러에 대한 옵션을 지정합니다.
- target: 어느 버전의 자바스크립트 코드로 변환할지를 선택할 수 있습니다. 대부분 ES6 이후를 지원하기에 ES6으로 두었습니다.
- module: 변환된 자바스크립트 코드가 어떤 모듈을 따를지 선택할 수 있습니다. 예를 들어 CommonJS로 설정한다면 내부적으로 require를 사용하며, ES6으로 설정하면 자바스크립트 코드에서도 import를 사용하게 합니다. 개인적으로는 개발 환경에서는 ECMAScript를 선호하지만 컴파일된 자바스크립트까지 ECMAScript로 하면 예상치 못한 예외 (undici-types 모듈 조회 불가능 등)가 발생할 수 있는 걸로 보아 CommonJS로 두도록 하였습니다.
- strict: 타입스크립트의 타입 체킹 동작 등을 활성화합니다. 기본값도 true입니다.
- noImplicitAny: 변수 등에 명시적으로 any를 적거나 다른 타입을 적어야만 정상 작동되도록 합니다.
- strictNullChecks: number 등의 타입에 null, undefined를 넣으려고 할 때 에러를 던지도록 할 수 있습니다.
- esModuleInterop: CommonJS로 작성된 모듈들을 ES6 모듈 사양에 맞게 가져올 수 있도록 합니다.
- sourceMap, outDir: outDir은 변환된 자바스크립트 파일의 생성 경로를 지정하고, sourceMap은 타입스크립트 코드에서 생성된 자바스크립트 파일에 소스 맵을 포함 하도록 하여 디버깅 시 원본 타입스크립트 코드를 추적할 수 있도록 합니다.
- 다만, ts-node를 설치하고 start 스크립트에서 이를 이용한다면 sourceMap, outDir을 지정할 필요가 없습니다. (그 대신 컴파일 된 자바스크립트가 보이지 않기에, 둘 중에 선택하면 됩니다.)
- include: 컴파일할 파일들을 지정합니다. 개발 파일과 테스트 파일에 대해 적용되도록 지정했습니다.
Nodemon 설정 (nodemon.json)
nodemon.json을 정의합니다.
{
"watch": ["src"],
"ext": "ts",
}
- watch: 감시할 구간을 의미합니다.
- ext: 감시할 확장자를 의미합니다.
이후 package.json의 스크립트에 아래와 같이 nodemon을 붙이면 됩니다.
"scripts": {
"start": "nodemon --exec 'tsc && node' dist/index.js",
},
...
ESLint
ESLint 설정은 ESLint 9가 나오면서 까다로워졌는데, 해당 부분은 아직 해결하지 못해 아래 명령어를 이용하겠습니다.
devholic@devholicui-MacBookAir express % npm init @eslint/config
> express@1.0.0 npx
> create-config
@eslint/create-config: v1.4.0
✔ How would you like to use ESLint? · problems
✔ What type of modules does your project use? · esm
✔ Which framework does your project use? · none
✔ Does your project use TypeScript? · typescript
✔ Where does your code run? · node
The config that you've selected requires the following dependencies:
eslint, globals, @eslint/js, typescript-eslint
✔ Would you like to install them now? · No / Yes
✔ Which package manager do you want to use? · npm
☕️Installing...
added 2 packages, changed 1 package, and audited 301 packages in 1s
77 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
Successfully created /Users/devholic/Desktop/express/eslint.config.mjs file.
이후 eslint.config.mjs 파일이 생성되는데, 빌드 폴더인 dist에서는 eslint를 적용하지 않도록 ignore를 추가합니다.
import globals from 'globals';
import pluginJs from '@eslint/js';
import tseslint from 'typescript-eslint';
/** @type {import('eslint').Linter.Config[]} */
export default [
{ files: ['**/*.{js,mjs,cjs,ts}'] },
{ languageOptions: { globals: globals.browser } },
pluginJs.configs.recommended,
...tseslint.configs.recommended,
{
ignores: ['dist/*'],
},
// 만약 rules를 적용하고 싶다면 아래처럼 작성하면 됩니다.
{
rules: {
// args all: 모두, none: 검사 X, after-used: 선언된 인자 중 사용되지 않는 것만 경고
'@typescript-eslint/no-unused-vars': ['error', { args: 'all' }],
// 스타일 경고 예시
indent: ['error', 2],
}
}
];
또한, Webstorm에서 작성한 ESLint를 따르도록 합니다. 이렇게 하면 저장할 때마다 ESLint에 맞게 고치는 것이 적용됩니다.
ESLint는 자동 구성을 따랐습니다.
Prettier
Prettier 설정도 Webstorm과 함께할 수 있습니다.
먼저. prettierrc에 해당 코드처럼 설정을 작성합니다.
{
"semi": true,
"singleQuote": true,
"tabWidth": 2
}
그다음, Webstorm 설정 > 언어 및 프레임워크 > JavaScript > Prettier에서 수동 패키지 구성 > Prettier 패키지를 설치한 prettier로 둡니다.
이후 <저장 시 모든 액션>에서 Prettier 실행도 설정해 둡니다.
간혹 Prettier에서 탭 크기를 2로 했음에도 불구하고 4로 된 경우가 있을 텐데요, 그럴 경우에는 Webstorm 설정 > 에디터 > 코드 스타일 > JavaScript, TypeScript 부분에서의 설정을 2로 해 두면 해결됩니다.
코드를 아무렇게나 어지럽게 작성해 둔 뒤
Cmd + S를 누르면, Prettier에 의해 자동 수정됩니다.
최종 정리
최종 작성한 package.json과 예시 src/index.ts는 다음과 같습니다.
// package.json
{
"name": "express",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"lint": "eslint .",
"build": "tsc",
// 원활한 nodemon을 위해 ts-node를 이용하도록 함
"start": "nodemon --exec ts-node src/index.ts",
"prestart": "npm run lint && npm run clean && npm run build",
"clean": "rimraf dist"
},
"author": "",
"license": "ISC",
"description": "",
"dependencies": {
"express": "^4.21.2"
},
"devDependencies": {
"@eslint/js": "^9.19.0",
"@types/express": "^5.0.0",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/parser": "^5.0.0",
"eslint": "^8.57.1",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.0.0",
"globals": "^15.14.0",
"nodemon": "^3.1.9",
"prettier": "^3.4.2",
"rimraf": "^6.0.1", // dist 폴더 제거 용도
"ts-node": "^10.9.2",
"typescript": "^5.7.3",
"typescript-eslint": "^8.22.0"
}
}
// 예시 index.js
import express from 'express';
const app = express();
app.get('/', (req, res) => {
console.log('Hello World!!');
res.send('Welcome to the API!');
});
app.listen(3000, async () => {
// 비동기 테스트
await new Promise((resolve) => setTimeout(resolve, 1000));
console.log('Server started on port 3000');
});
참고 자료
'언어 > JS&TS' 카테고리의 다른 글
[axios] axios 및 axios의 인터셉터 알아보기 (4) | 2024.12.28 |
---|