create-react-app
(CRA)은 리액트 애플리케이션 개발을 시작하는 가장 빠르고 편리한 방법 중 하나입니다. 특히 타입스크립트 템플릿(--template typescript
)을 사용하면 복잡한 초기 설정 없이도 바로 타입-세이프한 개발 환경을 구축할 수 있습니다. 하지만 CRA가 제공하는 기본 설정은 '만인을 위한' 범용적인 구성입니다. 이는 곧, 실제 프로덕션 레벨의 프로젝트나 특정 팀의 요구사항에 맞추기 위해서는 몇 가지 추가적인 개선 작업이 필요하다는 의미이기도 합니다.
기본 설정은 깔끔해 보이지만, 실제 개발에 들어가면 불필요한 파일들이 존재하고, 타입스크립트 설정은 더 엄격하게 가져갈 수 있으며, 코드 스타일을 일관성 있게 유지하기 위한 도구들의 연동이 아쉽습니다. 이 글에서는 CRA로 생성한 리액트 타입스크립트 프로젝트의 초기 설정을 어떻게 더 효율적이고 전문적으로 개선할 수 있는지 단계별로 상세히 알아보겠습니다.
1. 프로젝트 초기 구조 정리하기: 불필요한 파일 제거
CRA로 프로젝트를 생성하면 src
폴더 안에 여러 기본 파일들이 포함됩니다. 이는 리액트의 작동 방식을 보여주기 위한 예제 파일들이지만, 실제 프로젝트를 시작할 때는 대부분 필요하지 않습니다.
새 프로젝트의 초기 파일 구조는 다음과 같습니다:
/src
├── App.css
├── App.tsx
├── App.test.tsx
├── index.css
├── index.tsx
├── logo.svg
├── react-app-env.d.ts
├── reportWebVitals.ts
└── setupTests.ts
여기서 과감하게 정리할 수 있는 파일들은 다음과 같습니다.
- logo.svg: 리액트 로고 SVG 파일입니다. 프로젝트의 로고나 이미지를 사용할 것이므로 제거합니다.
- App.test.tsx:
App
컴포넌트에 대한 기본 테스트 파일입니다. Jest와 React Testing Library를 사용한 예제이지만, 실제 테스트 코드는 직접 작성해야 하므로 초기 파일은 삭제해도 무방합니다. - setupTests.ts: 테스트 환경을 설정하는 파일입니다. 나중에 필요에 따라 다시 구성할 수 있습니다.
- reportWebVitals.ts: 웹 바이탈(성능 지표)을 측정하는 유틸리티 함수입니다. 초기 개발 단계에서는 필수가 아니며, 필요시 언제든지 다시 추가할 수 있습니다.
- App.css:
App.tsx
에 대한 기본 스타일 파일입니다. 보통 CSS-in-JS(Styled-components, Emotion)나 Tailwind CSS 같은 다른 스타일링 솔루션을 도입하므로 제거합니다.
위 파일들을 삭제하고 나면 src
폴더는 훨씬 간결해집니다.
/src
├── App.tsx
├── index.css
├── index.tsx
└── react-app-env.d.ts
이제 파일 삭제에 따른 코드 수정이 필요합니다.
먼저 index.tsx
에서 reportWebVitals
관련 코드를 제거합니다.
// src/index.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
// import reportWebVitals from './reportWebVitals'; // 이 줄을 삭제합니다.
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
// reportWebVitals(); // 이 줄도 삭제합니다.
다음으로 App.tsx
에서 로고 import와 기본 마크업을 정리합니다.
// src/App.tsx
import React from 'react';
// import logo from './logo.svg'; // 로고 import 삭제
// import './App.css'; // CSS import 삭제
function App() {
return (
<div>
<h1>My React App</h1>
<p>프로젝트 설정이 완료되었습니다.</p>
</div>
);
}
export default App;
이렇게 초기 구조를 정리하면, 꼭 필요한 파일들만 남게 되어 프로젝트의 본질에 더 집중할 수 있습니다.
2. `tsconfig.json` 강화하기: 더 엄격하고 편리한 타입 환경
tsconfig.json
파일은 타입스크립트 컴파일러의 동작을 제어하는 핵심 설정 파일입니다. CRA의 기본 설정도 훌륭하지만, 몇 가지 옵션을 추가하여 코드의 안정성을 높이고 개발 편의성을 개선할 수 있습니다.
절대 경로(Absolute Imports) 설정
프로젝트 규모가 커지면 컴포넌트 간의 상대 경로 참조(../../components/Button
)가 매우 복잡해집니다. 이를 해결하기 위해 baseUrl
옵션을 설정하여 절대 경로를 사용할 수 있습니다.
tsconfig.json
파일의 compilerOptions
에 다음을 추가합니다.
{
"compilerOptions": {
"baseUrl": "src",
// ... 기존 옵션들
},
"include": ["src"]
}
이제 src
디렉토리를 기준으로 절대 경로를 사용할 수 있습니다.
- 변경 전:
import Button from '../../components/common/Button';
- 변경 후:
import Button from 'components/common/Button';
파일을 다른 위치로 이동시켜도 import 경로를 수정할 필요가 없어 유지보수성이 크게 향상됩니다.
더 엄격한 컴파일러 옵션 추가
코드의 잠재적인 오류를 컴파일 시점에 미리 발견하기 위해 몇 가지 유용한 옵션을 활성화하는 것이 좋습니다.
"noUnusedLocals": true
: 사용되지 않는 지역 변수가 있으면 에러를 발생시킵니다. 코드를 깔끔하게 유지하는 데 도움이 됩니다."noUnusedParameters": true
: 사용되지 않는 함수 파라미터가 있으면 에러를 발생시킵니다. 인터페이스 구현 등 불가피한 경우, 파라미터 이름 앞에 언더스코어(_
)를 붙여(예:_unusedParam
) 의도적으로 무시할 수 있습니다."forceConsistentCasingInFileNames": true
: 파일 이름의 대소문자를 일관되게 사용하도록 강제합니다. macOS와 같이 대소문자를 구분하지 않는 파일 시스템과 Linux 기반의 배포 환경(대소문자 구분) 간의 잠재적인 문제를 방지합니다.
이 옵션들을 추가한 compilerOptions
예시는 다음과 같습니다.
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true, // 추가
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
// 추가된 옵션들
"baseUrl": "src",
"noUnusedLocals": true,
"noUnusedParameters": true
},
"include": ["src"]
}
3. 코드 품질 관리 자동화: ESLint와 Prettier 연동
일관된 코드 스타일과 잠재적인 버그 예방은 협업 프로젝트의 필수 요소입니다. CRA는 기본적으로 ESLint
를 내장하고 있지만, 코드 포맷팅 도구인 Prettier
와 함께 사용하면 시너지를 극대화할 수 있습니다.
- ESLint: 코드의 문법적 오류나 안티 패턴 등 '논리적'인 문제를 찾아내는 린터(Linter)입니다.
- Prettier: 코드의 스타일(들여쓰기, 줄 바꿈, 따옴표 등)을 정해진 규칙에 따라 자동으로 맞춰주는 포맷터(Formatter)입니다.
이 둘을 연동하면 ESLint는 코드 품질에 집중하고, Prettier는 코드 스타일에 집중하여 각자의 역할을 명확히 할 수 있습니다.
설치 및 설정
먼저 Prettier와 ESLint 연동을 위한 패키지를 설치합니다.
# npm 사용 시
npm install --save-dev prettier eslint-config-prettier eslint-plugin-prettier
# yarn 사용 시
yarn add -D prettier eslint-config-prettier eslint-plugin-prettier
prettier
: Prettier 코어 라이브러리eslint-config-prettier
: ESLint의 포맷팅 관련 규칙 중 Prettier와 충돌하는 것들을 비활성화합니다.eslint-plugin-prettier
: Prettier의 규칙을 ESLint 규칙으로 가져와서 실행합니다. 포맷팅이 잘못된 부분을 ESLint 에러로 표시해줍니다.
설정 파일 생성 및 수정
1. Prettier 설정 파일 (`.prettierrc`)
프로젝트 루트에 .prettierrc
파일을 생성하고 원하는 포맷팅 규칙을 정의합니다. JSON이나 JS 형식으로 작성할 수 있습니다.
{
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "all",
"printWidth": 80,
"arrowParens": "always"
}
semi
: 문장 끝에 세미콜론을 붙입니다.singleQuote
: 문자열에 홑따옴표를 사용합니다.tabWidth
: 들여쓰기 칸 수를 2로 설정합니다.trailingComma
: 객체나 배열의 마지막 요소 뒤에 쉼표를 붙입니다.printWidth
: 한 줄의 최대 길이를 80자로 제한합니다.arrowParens
: 화살표 함수의 파라미터가 하나일 때도 괄호를 사용합니다. (예:(x) => x
)
2. ESLint 설정 파일 (`package.json` 또는 `.eslintrc.js`)
CRA는 기본적으로 package.json
파일 안에 eslintConfig
필드를 사용합니다. 이 부분을 수정하여 Prettier와의 연동을 설정합니다. extends
배열의 가장 마지막에 "plugin:prettier/recommended"
를 추가하는 것이 중요합니다. 이 설정이 다른 규칙들을 덮어쓰면서 충돌을 방지하기 때문입니다.
// package.json
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest",
"plugin:prettier/recommended" // 이 부분을 추가합니다.
]
},
이제 VSCode와 같은 에디터에서 "Format On Save" 옵션을 활성화하면 파일을 저장할 때마다 Prettier가 자동으로 코드를 정리해주고, ESLint는 코드 품질 문제를 알려주게 됩니다.
더 나아가, react-redux-typescript-guide와 같은 잘 정리된 가이드를 참고하면, 리덕스(Redux)를 포함한 복잡한 상태 관리 환경에서의 타입스크립트 및 ESLint 설정에 대한 깊이 있는 인사이트를 얻을 수 있습니다.
4. 패키지 매니저 선택: npm vs. Yarn
대부분의 자바스크립트 튜토리얼이나 문서가 npm
을 기준으로 설명하지만, Yarn
은 여전히 많은 개발자들에게 사랑받는 훌륭한 대안입니다. 특히 초기 Yarn은 npm의 단점이었던 속도와 의존성 관리의 일관성 문제를 해결하며 큰 인기를 얻었습니다.
물론 현재의 npm(버전 7 이상)은 많이 개선되어 Yarn과의 격차를 크게 줄였지만, Yarn은 여전히 다음과 같은 장점을 가집니다.
- 속도: 강력한 캐싱 메커니즘 덕분에 한번 설치한 패키지는 다음부터 매우 빠르게 설치됩니다.
- 안정적인 의존성 관리:
yarn.lock
파일은 모든 개발 환경에서 동일한 버전의 패키지를 설치하도록 보장하여 "내 컴퓨터에서는 됐는데..."와 같은 문제를 최소화합니다. - Workspaces: 하나의 저장소에서 여러 패키지를 관리하는 모노레포(Monorepo) 구성을 네이티브로 강력하게 지원합니다.
CRA 프로젝트에서 npm 대신 Yarn을 사용하는 것은 매우 간단합니다. 프로젝트 생성 시 Yarn이 설치되어 있다면 CRA가 자동으로 Yarn을 사용합니다. 만약 npm으로 생성된 프로젝트를 Yarn으로 전환하고 싶다면, 다음 단계를 따르세요.
- 프로젝트 루트에서
package-lock.json
파일을 삭제합니다. - 터미널에서
yarn install
(또는 간단히yarn
) 명령을 실행합니다.
이것만으로 yarn.lock
파일이 생성되고, 이후부터는 yarn
명령어를 통해 패키지를 관리할 수 있습니다. (예: yarn add <package-name>
, yarn remove <package-name>
)
npm에서 Yarn으로의 마이그레이션에 대한 더 자세한 정보는 Yarn 공식 마이그레이션 가이드에서 확인할 수 있습니다.
결론: 견고한 시작이 성공적인 프로젝트를 만든다
지금까지 Create React App으로 생성한 타입스크립트 프로젝트의 초기 설정을 개선하는 네 가지 방법을 살펴보았습니다.
- 불필요한 파일 정리로 프로젝트 구조를 간결하게 만들고,
tsconfig.json
강화를 통해 타입 안정성과 개발 편의성을 높였으며,- ESLint와 Prettier 연동으로 코드 품질과 스타일을 자동으로 관리하고,
- Yarn과 같은 패키지 매니저를 의식적으로 선택하여 개발 환경의 일관성과 속도를 개선했습니다.
이러한 초기 설정 과정은 다소 번거롭게 느껴질 수 있지만, 장기적인 관점에서 보면 매우 가치 있는 투자입니다. 잘 정돈된 프로젝트는 새로운 팀원이 합류했을 때 적응 시간을 단축시키고, 잠재적인 버그를 사전에 방지하며, 무엇보다 개발 과정 자체를 훨씬 즐겁고 생산적으로 만들어줍니다. 여기서 소개한 설정들을 기반으로 자신만의, 혹은 팀만의 프로젝트 템플릿을 만들어보는 것도 좋은 다음 단계가 될 것입니다.