새로운 기술을 학습할 때, 가장 좋은 방법은 기존에 진행했던 프로젝트에 기술을 적용해보거나 기술로 새롭게 프로젝트에 적용해보는 것이라고 생각한다
최근에 타입스크립트에 관심이 생겨 학습을 진행했고, 이에 대한 결과물로 기존에 내가 바닐라 자바스크립트로 진행한 프로젝트에 타입스크립트를 적용해서 변환하는 과정을 글에 녹여내고자 한다 🙂
개인적으로 프로젝트를 진행하면서 어려운 일 중 하나는 환경설정을 세팅하는 것이라고 생각한다
처음에 설정 코드나 라이브러리가 어떤 역할을 하는지 제대로 파악하지 못하고 마구잡이식으로 사용하다 보면 설정이 얽혀서 문제가 발생했을 때 해결하기에 더욱 어려워질 수 있고, 수정이 두려워지기 때문이다
내가 한 환경 구성이 누군가에게 도움이 될 수 있다면 좋을 것 같다 😀
JS 파일은 엔트리 파일이자 컨트롤러 역할을 하는 app.js, 상태를 관리하고 변경 메서드를 제공하는 store.js, 화면에 그리는 역할을 담당하는 view.js, 상수와 그 외 헬퍼 함수를 작성한 utils 폴더로 구분하였다
웹팩은 bundle, devserver 버전으로 나누어 설정 파일을 관리했다
package.json
{
"name": "kanban-board",
"version": "1.0.0",
"scripts": {
"start": "npm run serve -- --open",
"serve": "webpack serve --node-env development --config webpack/config.server.js",
"bundle": "webpack --node-env development --config webpack/config.dev.js"
},
"devDependencies": {
"@babel/core": "^7.17.0",
"@babel/preset-env": "^7.16.11",
"@babel/preset-typescript": "^7.16.7",
"@typescript-eslint/eslint-plugin": "^5.10.2",
"@typescript-eslint/parser": "^5.10.2",
"css-loader": "^6.5.1",
"eslint": "^8.8.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.0.0",
"prettier": "^2.5.1",
"style-loader": "^3.3.1",
"ts-loader": "^9.2.6",
"typescript": "^4.5.5",
"webpack": "^5.65.0",
"webpack-cli": "^4.9.1",
"webpack-dev-server": "^4.7.1"
}
}
package.json
파일에 devDependencies의 내용을 추가하고 npm i
명령어로 설치하는 것이 가장 간단하다.eslintrc.js
module.exports = {
root: true,
env: {
browser: true,
node: true,
},
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
],
plugins: ['prettier', '@typescript-eslint'],
rules: {
'prettier/prettier': [
'error',
{
singleQuote: true,
semi: true,
useTabs: false,
tabWidth: 2,
printWidth: 100,
bracketSpacing: true,
arrowParens: 'avoid',
},
],
},
parserOptions: {
parser: '@typescript-eslint/parser',
},
};
webpack/dev.js
/* eslint-disable @typescript-eslint/no-var-requires */
const path = require('path');
const __root = process.cwd();
const devConfig = {
target: ['web'],
mode: 'development',
devtool: 'source-map',
entry: './src/js/app.ts',
output: {
path: path.resolve(__root, 'dist'),
filename: 'js/[name].js',
},
module: {
rules: [
{
test: /\.ts$/,
use: 'ts-loader',
},
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
],
},
resolve: {
extensions: ['.ts', '.js'],
},
};
module.exports = devConfig;
tsconfig.json
{
"compilerOptions": {
"allowJs": true,
"sourceMap": true,
"target": "ES5",
"module": "ES2015",
"outDir": "./dist",
"lib": ["ES2015", "DOM", "DOM.Iterable"],
"noImplicitAny": true,
"downlevelIteration": true,
},
}
타입스크립트를 적용하면서 세운 규칙은 2가지이다
tsconfig.json
파일에 "noImplicitAny": true
옵션을 추가하고, js 확장자명을 가진 파일을 ts 파일로 바꾸니 수많은 에러가 검출되었다
우선 이를 타입스크립트 환경에서도 문제가 발생하지 않도록 하기 위해 any 타입을 활용하여 에러를 해결하였다
ts 파일로 바꾸고 난 후 발생한 수많은 에러들을 any 타입을 이용해서 해결하고, 정상적으로 코드가 동작하는 것을 확인하였다
다음 단계는 any 타입으로 정의한 타입들을 좀 더 구체적으로 변경하는 작업이었다
// types/Issue/index.ts
export interface DragIssue {
$el: HTMLLIElement;
index: number;
boardType: string;
}
export interface Issue {
id: string;
regDate: string;
title: string;
writer: string;
}
export interface UpdateIssue {
id: string;
type: string;
title: string;
writer: string;
}
export interface Issues {
[key: string]: Issue[];
}
export interface IssuesInfo {
idNumber: number;
issues: Issues;
}
export interface DragDropInfo {
dragIndex: number;
dragBoardType: string;
dropIndex: number;
dropBoardType: string;
}
export interface DropInfo {
$drop: HTMLLIElement;
$ul: HTMLUListElement;
$el: HTMLLIElement;
dragIndexOfTargetList: number;
dropIndex: number;
}
위의 코드와 같이 객체의 경우 interface로 정의하여 매개변수로 받을 타입을 지정하고, 원시값을 넘겨받는 경우에는 string, number, 유니온 타입을 적절히 사용하여 전체 파일을 타입스크립트 파일로 변경하였다
그 다음 단계로는 tsconfig.json 파일에서 strict 옵션을 true로 변경하였다
{
"compilerOptions": {
...
"strict": true
},
}
이렇게 옵션을 설정하면 기존보다 더 엄격하게 타입을 검사하고 예기치 못한 에러를 발생시키지 않도록 검사한다
대부분의 발생한 오류의 경우 DOM이나 타입이 null일 수도 있는 경우 발생하는 타입 에러였다
이를 해결하기 위해서 옵셔널 체이닝 연산자, if 문을 사용한 타입 가드, 타입 단언 등을 사용하여 문제를 해결했다
점진적으로 타입스크립트의 타입을 구체화하며 기존에 바닐라 자바스크립트로 동작되던 프로젝트를 타입스크립트 환경에서도 동작하도록 변환하는 데 성공하였다
REST API 요청을 하지 않고, 작은 규모의 프로젝트임에도 불구하고 예상한 것보다 변환하는 데 시간이 소요되었다. 직접 타입스크립트를 공부하고 프로젝트를 진행하기 전까지는 단순히 타이핑을 도와주는 도구라고 생각하여 쉬울 것이라고 생각했었는데, 직접 사용해보니 잘 사용하기 위해서는 추가적인 학습과 시간이 필요할 것 같다는 생각이 들었다
앞으로는 두 가지 방향으로 타입스크립트 학습을 이어나가고자 한다
좋은글 보고갑니다~