React 프로젝트 JS -> TS로 변환하기
React JS에서 Ts로 변환하기
배포까지 마무리한 React 애플리케이션을 Javascirpt ==> Typescript로 변환해보자.
먼저, Private 레포를 우리 팀만의 ORG를 하나 만들어서 Public으로 전환해서 우리 팀만을 위한 연습용 레포를 하나 만들고 시작한다.
아래 문서에서 권장하는 방법을 살펴보자.
https://create-react-app.dev/docs/adding-typescript/
기존 프로젝트에서 TypeScript를 추가하는 경우니 아래 cli를 참고하면 된다.
하나하나 무엇을 의미하는지 알아보자.
1. typescript
기본적으로 Ts로 작성하기 위해 typescript 패키지를 설치해야 한다. 해당 패키지를 설치함으로써 확장자 ts를 사용하고 실제 코드에서 Ts로 에러 없이 로직을 작성할 수 있게 된다.
타입 스크립트의 경우 컴파일 과정을 거쳐 자바스크립트 파일로 변환되는데, 실제 컴파일 언어들과는 차이점이 있어 타입 스크립트를 컴파일 언어가 아닌 트랜스 파일러 언어라고도 부르기도 한다. (바벨도 트랜스 파일)
여하튼, 해당 패키지는 TS 파일을 JS로 컴파일(트랜스 파일)하도록 할 수 있는 컴파일러라고도 볼 수 있다.
2. @types/node
이 패키지에는 Node.js( https://nodejs.org/ )에 대한 유형 정의가 포함되어 있습니다.
이 패키지는 Node에서 typescript를 사용할 때 모든 유형 정의를 로드하는 데 사용한다.
다른 패키지를 추가할 때 기본적으로 포함하지 않는 경우 해당 유형도 추가한다.
예를 들어, lodashtypescript 응용 프로그램에서 사용하려는 경우 유형 정의( @types/lodash)도 설치해야 한다!
추가로, TypeScript 2.x 이상 버전에서는 @types/node가 필수라고 한다.
3.@types/react
위 @types/node와 동일하게 해당 패키지는 React에서 typescript를 사용할 때 모든 유형 정의를 로드하는 데 사용한다.
... @types/react-dom , @types/jest 등 패키지들도 위와 동일한 이유로 사용된다.
jest는 사용하지 않기 때문에 이를 제외한 모든 패키지를 설치해주자.
npm install --save typescript @types/node @types/react @types/react-dom @types/jest
위처럼 패키지를 설치하고 나서 원래는 아래 명령어를 실행하여 tsconnfig.json를 만들어줘야 한다고 한다
npx typescript --init
하지만 CRA에서는 첫 번째 cli 명령을 통해 자동으로 tsconfig.json 파일이 루트 디렉토리 내에 생성이 된다.
결국 바로 위 명령어를 실행할 필요가 없게 된다.
tsconfig.json이 무엇인지 짚어보고 넘어가자.
tsconfig.json 파일이 위치한 디렉토리는 TypeScript 프로젝트의 루트 디렉토리가 된다.
tsconfig.json 파일은 해당 프로젝트를 컴파일하기 위해 필요한 루트 파일들과 각종 컴파일러 옵션들을 설정하는 파일이다.
TypeScript는 JavaScript로 컴파일하는 과정이 필요하다.
즉, tsconfig.json 파일이 위치한 디렉토리가 Ts 프로젝트의 루트 디렉토리로 인식이 되고 해당 Ts파일을 Js로 어떻게 컴파일할 것인가를 설정해주는 파일이라고 요약할 수 있을 것 같다.
아직까지는 해당 파일을 수정해야 할 필요성을 느끼지 못했다. 컴포넌트를 하나하나 변경해가면서 체감해보려 한다.
더욱 자세한 건 아래 문서를 보는 게 더 좋다.
https://www.typescriptlang.org/docs/handbook/tsconfig-json.html
https://typescript-kr.github.io/pages/tsconfig.json.html
tsconfig.json 설정 값 확인해보기!!
https://www.typescriptlang.org/tsconfig
여기까지 했을 때 연습 목표였던 Base 컴포넌트를 Ts로 변환해보자
사실상 이번 포스팅의 핵심은 다 소개했다고 생각한다.
아래부터는 위 과정을 모두 마무리한 후, 연습해보는 코드이다.(뒤로 가기 가능!!)
아래 부분부터는 매우 주관적인 코드이며, 처음 사용하고 배우는 단계의 코드이므로 참고만 하면 좋을 것 같다.
Image/index.js ==> index.tsx 확장자를 변경하고 인터페이스로 Prop 타입을 지정해준다.
interface IImage {
src: string
width?: number
height?: number
mode: string
block: Boolean
lazy: Boolean
threshold: number
placeholder: string
iscircle: Boolean
}
const Image = ({
src,
width = 150,
height = 150,
mode,
block,
lazy,
threshold = 0.1,
placeholder,
iscircle,
...props
}: IImage) => {
const [loaded, setLoaded] = useState(false)
const imgRef = useRef(null)
다른 코드에서는 문제가 없지만 한 군데 에러가 발생한다.
('{}' 형식에 'style' 속성이 없습니다.)
Image 컴포넌트의... props 정의되어 있지 않는 prop을 받았을 때 스타일에 조금 더 확장적 이도록 구성했던 코드가 원인이었다.
사실상... props로 받는 args를 일일이 하나하나 지정할 수 없기에 any를 지정하면 될 줄 알았는데 해결이 안 된다.
결국 style이라는 속성이 없기 때문에 에러가 발생하는 것으로 이를 인터페이스에서 style이라는 프로퍼티를 옵셔널 값으로 지정해주었다.
style?: object와 같이 설정할 수 있었지만, style이라는 값은 마진, 패딩과 같은 CSS프로퍼티들로서 위와 같이 React.CSSProperties라 지정해보았다. (정답이라고 생각되지 않는 부분이므로 참고만 하자!!)
가능한 이미지 컴포넌트를 사용하는 부모에서 어떠한 로직도 변경하지 않고 이전 기능을 그대로 완벽히 수행할 수 있길 원했다.
Prop에 style을 추가하고, 스프레드 연산자를 사용해서 style을 모두 받을 수 있도록 작성해보았다.
다행히 스토리북, 리액트 프로젝트 내에서 봐도 잘 동작한다.
출처 및 참고
https://create-react-app.dev/docs/adding-typescript/
https://www.typescriptlang.org/docs/handbook/tsconfig-json.html
https://it-eldorado.tistory.com/126
https://typescript-kr.github.io/pages/tsconfig.json.html
https://www.typescriptlang.org/tsconfig