[React] 기존 React 프로젝트 TypeScript 적용
📌 TypeScript
- TypeScript는 마이크로소프트에서 개발한 JavaScript의 상위 집합(Superset) 언어로, 정적 타입을 지원하고 확장자로 .ts를 사용하며 작성한 코드는 컴파일을 거쳐 JavaScript로 변환됩니다.
- 가장 큰 특징은 정적 타입을 명시할 수 있다는 점. 이를 통해 개발 도구(IDE)와 컴파일러가 코드 자동 완성 타입 오류 감지 등의 피드백을 제공하여 생산성을 높이고 버그를 줄이며 유지보수를 쉽게 만듭니다. 👍
즉, TypeScript는 실행 전에 타입 오류를 미리 잡아주는 역할을 하는 언어 !
📍 기존 React 프로젝트에 TypeScript 설치
npm i typescript @types/node @types/react @types/react-dom @types/jest
✅ typescript
- TypeScript의 컴파일러(tsc)를 포함한 핵심 패키지
- .ts나 .tsx 파일을 JavaScript로 변환하는 역할
✅ @types/node
- Node.js에서 TypeScript를 사용할 때 필요한 타입 정의
- TypeScript 프로젝트에서 Node.js의 내장 모듈(예: fs, path, http 등)을 사용할 때 해당 모듈의 타입 정보를 자동으로 가져올 수 있게 해줍니다.
✅ @types/react
- React 관련 타입 정의
- React의 컴포넌트, 훅, 이벤트 등에서 TypeScript를 사용할 수 있도록 해줌
✅ @types/react-dom
- react-dom의 타입 정의 파일
- ReactDOM.render() 같은 함수에서 TypeScript를 사용할 수 있도록 도와줍니
✅ @types/jest
- Jest(테스트 프레임워크) 관련 타입 정의
- Jest를 사용할 때 TypeScript의 지원을 받으려면 필요
※ 만약 Jest를 사용하지 않는다면 설치하지 않아도 돼요
📍 tsconfig.json 파일 생성
- TypeScript를 설정하려면 프로젝트 루트에 tsconfig.json 파일을 추가 해야 하는데
tsc --init 명령어를 실행하여 기본 설정 파일을 생성
- tsconfig.json 파일을 통해 TypeScript 컴파일러의 기본 설정을 포함하고 있고 컴퍼일러 옵션을 설정 !
npx tsc --init
☝️ 파일 생성 확인
// tsconfig.json
{
"compilerOptions": {
"target": "ES6",
"module": "esnext",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"moduleResolution": "node",
"resolveJsonModule": true,
"jsx": "react-jsx",
"strict": true,
"esModuleInterop": true,
"allowJs": true,
"allowSyntheticDefaultImports": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"isolatedModules": true,
"noEmit": true
},
"include": [
"src"
]
}
✅ target: "ES6"
- 컴파일된 코드가 사용할 JavaScript 버전을 ES6으로 설정
✅ module: "esnext"
- 모듈 시스템을 최신 ES 모듈로 설정
- 최신 JavaScript(ES6+)에서 사용하는 import/export 구문을 그대로 사용할 수 있습니다.
✅ lib : ["dom", "dom.iterable", "esnext"]
- 사용할 라이브러리의 종류를 설정합니다.
- DOM API, DOM 이터러블 API, ESNext(최신 ECMAScript 표준)포함.
- React 프로젝트에서는 dom이 필수적이며, 최신 기능을 사용하려면 esnext를 포함하는 것이 좋습니다.
✅ moduleResolution: "node"
- 모듈을 Node.js 방식으로 해석하도록 설정합니다. node_modules에서 모듈을 찾을 때 Node.js의 모듈 해석 규칙을 따릅니다.
✅ resolveJsonModule
- .json 파일을 모듈처럼 import할 수 있게 허용
- JSON 파일을 TypeScript에서 직접 import하려는 경우 유용
✅ jsx: "react-jsx"
- react-jsx는 JSX를 컴파일할 때 React.createElement 호출을 자동으로 처리합니다.
✅ strict
- TypeScript의 엄격한 타입 검사를 활성화합니다.
- 코드 품질을 높이고, 오류를 미리 잡아낼 수 있도록 도와줍니다.
✅ esModuleInterop
- CommonJS와 ES 모듈 간의 호환성을 개선하는 옵션
- require와 import를 함께 사용할 때 발생하는 문제를 해결합니다
✅ allowJs
- 기존 JavaScript 파일도 TypeScript 프로젝트 내에서 사용할 수 있게 허용합니다.
- JavaScript에서 TypeScript로 전환하는 중에 유용합니다.
- avaScript와 TypeScript를 함께 사용하려는 경우 설정
✅ allowSyntheticDefaultImports
- ES 모듈에서 default export를 사용할 때, CommonJS 모듈의 module.exports를 default로 처리할 수 있게 해줍니다.
✅ skipLibCheck
- 라이브러리의 타입 정의 파일에 대한 검사를 건너뛰도록 설정합니다.
- 외부 라이브러리의 타입 정의 오류를 무시, 타입 정의에 문제가 있어도 컴파일 오류를 피할 수 있게 해 줍니다.
✅ forceConsistentCasingInFileNames
- 파일 이름의 대소문자 일관성을 강제합니다. 예를 들어, MyComponent.tsx와 myComponent.tsx가 다른 파일로 처리
- 운영 체제에 따라 대소문자 구분이 다를 수 있기 때문에 대소문자 일관성을 유지하기 위해 사용됩니다.
✅ noFallthroughCasesInSwitch
- switch 문에서 fall-through(케이스 간에 break 없이 실행되는 현상)을 방지하도록 설정
- switch 문을 사용할 때 의도하지 않은 동작을 방지하여 코드 안정성을 높입니다.
✅isolatedModules
- 각 파일을 독립적으로 처리할 수 있도록 설정
- 주로 Babel과 함께 사용할 때 필요하며, jsx가 있는 파일에서도 사용됩니다.
- 파일 별로 독립적인 컴파일을 위해 설정됩니다.
✅ noEmit
- TypeScript 컴파일러가 JavaScript 파일을 생성하지 않도록 설정
- 타입 검사만 수행하고 JavaScript 파일을 출력하지 않게 합니다.
- 타입 체크만 하고, 컴파일된 JavaScript 파일을 생성하고 싶지 않을 때 사용됩니다.
✅ "include": ["src"]
- src 폴더 안에 있는 모든 TypeScript 파일을 검사하고 컴파일 진행
- src 폴더가 프로젝트의 주요 코드가 있는 디렉토리일 때 적합합니다
- 외부 타입 선언 파일이나 특정 파일을 포함시키려면 별도로 include 항목을 추가 필요합니다
📍 파일 확장자 변경
- TypeScript 로 진행하기 위해서는 .js 파일은 .ts로 .jsx 파일은 .tsx로 확장자로 변경
- 컴포넌트가 포함된 파일은 .tsx 확장자로 변경
- 일반적인 JavaScript 파일은 .ts로 변경
EX)
src/App.js ➡️ src/App.tsx
src/pages/MainPage.jsx ➡️ src/pages/MainPage.tsx
src/utils/test.js ➡️ src/utils/test.ts
😅 파일 수가 엄청 많은 상태에서 진행하는 경우 힘들 수 있어요!
📍경로 별칭
✅ 타입스크립트를 적용하기 전 경로 별칭을 사용해서 import를 하고 있었는데
타입스크립트를 적용하면서 다시 해야하는 문제 발생!!
jsconfig.json 파일은 삭제 하고 tsconfig.json 옵션 추가 진행
// tsconfig.json
{
"compilerOptions": {
...,
"baseUrl": "./src",
"paths": {
"*": ["*"]
}
},
}
- baseUrl / paths 추가
📍index.tsx 에러
index.js ➡️ index.tsx 변경 후 발생하는 에러
Argument of type 'HTMLElement | null' is not assignable to parameter of type 'Container'.
Type 'null' is not assignable to type 'Container'.ts(2345)
✅ document.getElementById('root')가 null을 반환할 수 있기 때문에 발생.
📗 해결방법
✅ ! (Non-null assertion operator) 사용
const root = ReactDOM.createRoot(document.getElementById('root')!);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
- null, undefined가 아니라고 단언
✅ if문으로 null 체크
const rootElement = document.getElementById('root');
if (rootElement) {
const root = ReactDOM.createRoot(rootElement);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
}
- rootElement가 null인지 if문으로 확인 후 root.render() 호출.
- null 일경우 else console.error를 사용하여 오류를 확인 하여 디버깅, 처리 가능
✅ as HTMLElement
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
- document.getElementById('root')의 반환 타입은 HTMLElement | null인데, as HTMLElement를 사용하면 무조건 HTMLElement로 간주
- 문제 강제로 HTMLElement로 간주하기 때문에 런타임 오류가 발생할 수 있습니다.
- 짧고 간결하면서 사용하기 위해서는 ! (Non-null assertion) 사용, 가장 안전한 방법으로 if문 사용
📍Router createBrowserRouter element 에러
- 'App' refers to a value, but is being used as a type here. Did you mean 'typeof App'?ts(2749)
- TypeScript 별칭 설정을 잘못했을까 하고 수정도 하고 App.tsx 수정도 했지만 에러나와 찾아보니 파일 확장자 문제..😅
🔽 .ts → .tsx
✅ element에서 컴포넌트를 전달하면서 JSX 포함하고 있지만 .ts는 JSX를 인식하지 못하기 때문에 오류 발생..!
확장자를 .tsx를 변경하여 오류 해결
확장자 변경과 발생하는 오류를 해결을 하고 나면 끝!
✅ 완료!
✍️ 기록
감사합니다. 😁