"CRA(Create React App)와 TypeScript(타입스트립트) 사이의 동작원리가 많이 궁금했습니다"
tsconfig.json을 설정하는 과정 중에, 많이 막혔던 내용들이 많아서 이를 정리하고자 블로그 글을 작성하기로 결심했습니다.
가장 먼저 막연하게 든 생각이었습니다. tsconfig.json은 단순히 타입스크립트를 설정하기 위한 파일일까요? 컨벤션에 대한 내용을 다룬다면, Prettier, ESLint 같은 좋은 도구들도 많을 텐데, 이들을 같이 쓰면서 굳이 이 파일을 작성해야 하는 이유는 무엇인가요?
제 자신에게 이에 대해서 질문을 한다고 해도 대답을 하기에는 어려웠습니다. 그래서 tsconfig.json에 대해서 일단은 면밀하게 파악해 보기로 했습니다. 공식문서에서는 이에 대해 이런 식으로 대답했습니다.
tsconfig.json 파일이 존재하는 디렉터리는 해당 디렉터리가 타입스크립트 프로젝트의 root임을 의미합니다. 따라서 tsconfig.json 파일은 프로젝트에서 요구되는 root 파일이나 컴파일러의 옵션들을 좀더 구체적으로 설정할 수 있는 요소들을 제공합니다.
즉, 개발자들은 intellisense가 .ts 파일을 인식하는 방법을 제어하기 위해서 tsconfig.json 파일을 작성해야 합니다. 그런데, 'tsc' 라고 하는 것도 보입니다. 얼핏 봐서는 typescript compiler의 줄임말로 보여집니다. 그리고 제가 예상했던 것이 맞았습니다. tsc는 타입스크립트 컴파일러로, 이를 통해 ts 파일을 js 파일로 변경시킬 수 있습니다.
그런데 이렇게만 넘어가서는 안됩니다. 사실 한가지 중요한 사실을 인지해야 합니다. 그것은 바로 'vscode에서 에러가 나지 않는다고 해서 tsc에서도 마찬가지로 에러가 나지 않는다는 보장은 없다.'입니다. 안타깝게도 그 역도 성립합니다. 그러나, tsc를 통해 vscode의 intellisense가 typescript를 처리하는 방법을 제어할 수는 있습니다.
이제부터는 타입스크립트 공식 문서를 통해 막혔던 부분들을 하나하나 뜯어서 살펴보도록 하겠습니다.
제가 가진 첫 번째 의문이었습니다. 사실 제 팀원들과 같이 진행하고 있는 그룹프로젝트는 'es5'로 설정을 했었습니다. 그러나, 최신 브라우저는 모든 ES6 기능을 지원합니다. 이 웹사이트를 참고해보고, es6를 과연 지원할 수 있을 지 곰곰이 생각해보면, es6로 넣지 않을 이유가 없다는 생각이 들었습니다. 그런데, 그렇다고 esnext처럼 최신형 자바스크립트 버전을 넣는 것은 약간 위험할 수도 있기에 개인적으로는 es6가 target 설정에 제일 적합하지 않을까 하는 생각이 들었습니다.
rootDir은 선언되지 않은 input 파일들을 기반으로 가장 긴 path를 가진 디렉터리를 찾게 됩니다. 이렇게만 이야기하면 이해하기가 쉽지 않죠. 그래서 일단은 이렇게 생각해보기로 했습니다. composite이 true라는 전제 하에(그리고 이것이 기본값입니다.) tsconfig.json 파일을 가지고 있는 디렉터리가 default로 세팅된다고 생각하시면 됩니다.
예시를 한번 들어보겠습니다.

다음의 경우를 예시로 보겠습니다. 이 경우 rootDir는 'core' 디렉터리입니다. 그 이유는 무엇일까요? 바로 'MyProj'일까요? 그런데, 이 디렉터리는 types.d.ts 파일이 들어있습니다. 이 파일은 '선언 파일'입니다. 따라서 비선언(non-declaration) 파일이 들어있지 않은 것에 위배됩니다. 결과적으로, rootDir는 core가 됩니다. 자세한 내용은 이 부분을 참고해주세요
.d.ts 파일은 참고로 type을 정의(declare)하고자 하기 위해서 존재하는 파일입니다. 기존의 JavaScript로 만들어진 서드파티 모듈(제3자, 그러니까 외부 라이브러리가 가장 대표적인 예시)들을 TypeScript 환경에서도 사용하기 위해 따로 타입만 정리해서 넣어둔 파일입니다. 따라서 해당 파일을 통해 JS 기반의 라이브러리라고 할지라도 TS환경 타입이 지정되어 있어서 정상적으로 인식을 하게 됩니다. 가장 대표적인 .d.ts 파일이 바로 '@types/' 입니다.
outDir는 이 속성을 만일 지정하면, .js (이 외에도 .d.ts, .js.map, 등.)파일이 지정한 디렉터리로 배출됩니다. 원본 파일의 디렉터리 구조는 보존됩니다. 계산된 루트가 예상과 다를 경우에는 rootDir을 통해 다시 한번 확인해보세요.
만일 지정하지 않으면, .js 파일은 .ts 파일이 생성된 곳과 동일한 디렉터리에 생성됩니다.
사실 제가 가장 궁금했던 부분이 바로 이 부분이었습니다. 사실 이 부분은 웹팩을 통해 Electron 앱을 TypeScript로 설정하는 과정을 담은 그림입니다. 그런데 CRA 또한 Webpack과 Babel이 들어있고, 이를 TypeScript와 같이 넣는 과정이 유사했기 때문에 한번 가져와 보았습니다.

오른쪽 부분은 테스트코드이기 때문에 테스트코드와 관련된 부분이 따로 필요하신 경우에는 참조해서 읽으면 좋을 것 같습니다.
여기에서 저는 한가지 의문이 들었습니다. tsc를 이용해서 ts -> js로 컴파일링 과정을 거치는데, 여기에서 webpack의 babel-loader를 이용해서 다시 한번 트랜스파일링을 해주는 것인가?
그래서 관련 블로그 글을 가지고 와봤습니다. 관심있으시면 깊게 읽어주시면 감사하겠습니다 :)
https://dev.to/mbeaudru/is-babel-still-relevant-for-typescript-projects-36a7