Vite + ReactJS 프로젝트 시작하기 (ESLint/Prettier)
1. React는 무엇인가
React는 Meta(구 Facebook)에서 사용자 인터페이스(UI)를 만들기위해 개발한 JavaScript 라이브러리이다.
많은 사람들은 React가 "프레임워크"로 알고 있는 경우가 많은데, 라이브러리와 프레임워크는 차이가 있다.
React가 라이브러리로 분류가 되는 상세한 이유는 다음과 같다.
1. "React는 개발자에게 제어권을 주기 때문" 이다. 또한, 필요한 것을 선택해서 사용하는 '도구' 의 역할을 하기 때문이다.
React의 진입점. main.jsx(또는 main.tsx)를 보면 다음과 같이 되어 있다.
여기서 알 수 있는 점은, 진입점인 main.jsx에서 render()를 호출한다는 것이다. 그리고, React는 이 <App />을 render()하라고 호출하지 않는 이상, 렌더링하지 않는다.
어디에, 무엇을, 어떻게 그릴 것인지 모두 개발자가 결정하기 때문에, React는 라이브러리로 분류된다.
2. React는 특정 방식만을 강요하지 않는다.
일반적으로 React를 사용할 때, 전역 상태 관리를 위해 Redux를 사용할 수도 있고, Zustand를 사용할 수도 있다. 즉, 프로젝트의 구조가 비교적 자유롭다.
심지어, main.jsx에서 <App />를 렌더링하라고 되어 있지만, 다른 컴포넌트를 렌더링 진입점으로 삼을 수도 있다.
프레임 워크와 라이브러리의 차이는 다음과 같이 정리해볼 수 있다.
- 프레임워크:
Application의 전체적인 구조와 흐름을 제어한다.
- 개발자는 정해진 틀 안에서 코드를 작성해야 한다.
Angular,Next.js가 대표적인 프레임워크로, 이러한 프레임워크는 우리가 아니라 프레임워크에서 우리의 코드를 필요에 따라 불러와 실행한다. 이를 제어의 역전(Inversion of Control, IoC) 라고 한다.
라이브러리
- 개발자가 필요할 때만 호출하여 사용하는 도구의 모음집
- 코드의 전체 흐름을 개발자가 직접 제어
1.1. 장점: React를 사용해야 하는 이유
React는 UI를 만드는 데 필요한 기능만 제공하는 **'라이브러리'**이므로, 개발자가 애플리케이션의 구조를 직접 설계하고 다른 라이브러리(상태 관리, 라우팅 등)를 자유롭게 조합하여 사용할 수 있는 높은 유연성을 가진다.
바로 이 점이 React의 가장 큰 매력이자 강력한 특징이다.
- UI 집중 라이브러리: React는 오직 UI에만 집중하고 있고, 다른 부가 기능은 원하는 라이브러리를 직접 선택하고 조합하여 사용할 수 있다.
- 컴포넌트 기반 Architecture: UI를 각각 독립적인 부품(컴포넌트)로으 분리하여 구성하고, 이는 재사용성과 유지 보수성을 높인다.
- 선언적 UI: 데이터가 변경될 때 UI가 어떻게 보일지만 선언하면, React가 알아서 화면을 업데이트한다.
- 가상 DOM(Virtual DOM): 메모리 상에서 가상 DOM을 사용하여 불필요한 렌더링을 줄이고, 성능을 최적화한다.
1.2. 단점: React를 피해야 할 때
물론 React가 모든 상황에 완벽한 해결책은 아니다. 아무리 Virtual-DOM(가상 돔)을 통해 렌더링 성능을 최적화 했지만, 근본적인 단점 또한 지니고 있다.
무거운 클라이언트(Client-Fat)
- React 기반의 앱(SPA; Single Page Application)은 처음에 비어있는 HTML 파일을 받고, 이후 브라우저가 JavaScript 번들을 다운로드하고 실행하여 화면을 그린다. 즉, 모든 작업을 사용자의 브라우저가 수행한다.
- 이 때문에 React는 SSR(서버에서 HTML을 만들어 보내는 방식)보다 초기 로딩 속도가 느릴 수밖에 없다.
- SEO(검색 엔진 최적화) 어려움: 이전 항목에서 처럼 React 앱은 처음에 비어있는 HTML을 보내기 때문에, 검색 엔진이 페이지의 콘텐츠를 제대로 수집하지 못할 수 있다.
이런 단점을 고려 했을 때, 콘텐츠 중심(블로그, 마케팅 페이지 등)의 경우나, 검색 엔진 노출이 중요한 프로젝트의 경우에는 React 보다는 Next.js나 Remix(React-Router) 등을 채택하여 SSR 방식을 사용하는 것이 좋다.
또는, 매우 간단한 페이지의 경우에도 React가 과한 선택일 수 있다. 몇몇 요소에 간단한 애니메이션, 이벤트 처리만 하는 경우에는 배보다 배꼽이 더 큰 격이다. 이런 경우, 다른 프레임워크를 사용하거나, 바닐라 JS를 선택하는 것이 좋다.
2. React 시작하기: Vite와 함께
오랫동안 React 프로젝트를 시작하는 표준적인 방법은 create-react-app(CRA)였다. CRA는 별도의 설정 없이 바로 React를 사용할 수 있게 해주는 도구였지만, 이는 공식적으로 Deprecated(사용 중단) 되었다.
CRA는 개발 서버의 구동과 빌드가 느리고, 최신 JS 표준인 ES모듈(ESM; ES-Module) 지원도 미흡하다. 이를 해결하고자 Vue.js의 창시자인 Evan You가 개발한 Vite(비트)가 등장했다. 이는 현재 React 커뮤니티에서도 공식적으로 추천하는 방법이다.
Vite를 사용하는 이유
압도적으로 빠름
- Vite는 개발 환경에서 Native ES Module을 사용하여 소스코드를 제공한다. 이 덕분에 개발 서버 구동이 매우 빠르고, 코드 수정 사항이 즉각적으로 반영된다.
빌드가 효율적임
- Production 빌드 시, Rollup을 사용하기 때문에 결과물이 매우 최적화되어 빌드된다.
- 설정이 유연하고, 매우 간결함
왜 Vite를 사용하는지까지 알아보았으니, 이제 React를 시작해보자.
Node.js와 npm이 모두 설치되어 있다고 가정하고 설명한다.2.1. create vite
프로젝트를 시작할 경로의 한 단계 상위 경로에서 터미널(커맨드 창)을 열고, 다음과 같이 입력한다.
그러면 다음과 같이 출력된다.
vite-project라고 적힌 곳에 커서가 있을 것이다. 그대로 프로젝트의 이름을 적어주고, Enter를 누른다. 그러면 그대로 아래에 이렇게 출력된다.
이 상태에서 화살표 키를 이용해 프레임워크를 선택할 수 있다.
참고로, React 외에 쓰여있는 모든 프레임워크는 Vite로 바로 시작가능하다.
○ React를 선택해준다.
그럼 또 variant를 선택하라고 한다.
이렇게 뭐가 많을 텐데, 하나씩 살펴볼 것이다.
특별한 이유가 없다면, TypeScript + SWC를 선택하면된다.
또는 JavaScript + SWC를 선택해도 되지만, TypeScript에 도전해보는 것도 좋은 선택이다.
2.1.1. TypeScript vs JavaScript
우선 TypeScript와 JavaScript로, 프로젝트에서 사용할 언어를 결정한다.
- JavaScript: 우리가 아는 웹 개발의 표준 언어이다. 별도의 타입 선언 없이 유연하게 코드를 작성할 수 있다.
- TypeScript: Microsoft에서 개발한 언어로, javascript 기반으로 만들어졌고, 여기에 C/C++처럼 정적인 타입 문법을 추가한 것이다. 코드에서 타입을 명시적으로 지정하여 오류를 미리 확인할 수 있고, 프로젝트의 안정성과 유지보수성을 높여준다.
tsc)를 25년 연말까지 Go언어로 Native Porting 작업을 수행하고 있다. 이를 통해 TypeScript를 JavaScript로 변환하는 작업(tsc의 작업)과 만들어진 앱(Visual Studio, VS Code 등)의 성능이 기존보다 약 10배 빠를 것으로 예상되고 있다.2.1.2. SWC
SWC는 Rust로 작성된 매우 빠른 컴파일러 및 트랜스파일러이다.
TS(TypeScript)의 경우, TS를 JS로 바꿔주는TSC대신 SWC를 사용한다. 기존보다 훨씬 빠른 빌드 및 개발 서버 구동 속도를 보여준다.JS(JavaScript)의 경우, 최신 JSX 문법을 처리하는 데에 사용된다. 이 또한Babel보다 속도가 빠르다.
특별한 이유가 없다면, SWC를 사용하는 것이 전체적인 개발 경험이 향상된다.
2.1.3. React Router v7
React 에서 가장 많이 사용되는 React Router의 최신 버전을 기본으로 설정한다. 이의 전신은 Remix로, 최근 Remix는 React Router v7으로 병합되었고, 기존의 Remix는 차후에 Preact 기반의 프로젝트로 나아갈 것으로 보인다.
2.1.4. TanStack Router
최근 주목받고 있는 라우팅 라이브러리이며, 타입 안정성과 검색 Parameter 관리에 강점을 가지고, 파일 기반 라우팅과 유사한 방식을 지원하기 때문에, 직관적이다.
2.1.5. Redweed JS
풀스택 프레임워크인 Redweed JS에 Vite 기반의 React를 통합한 프로젝트를 만들어준다.
2.1.6. RSC(React Server Components)
React의 최신 기능인 서버 컴포넌트를 실험적으로 사용해볼 수 있는 템플릿이다. 서버에서 렌더링되는 컴포넌트와 클라이언트에서 상호작용하는 컴포넌트를 함께 사용하여 성능을 최적화하는 것을 목표로 하고 있다.
즉, Next.js의 App Router와 비슷한 개념을 사용할 수 있다.
3. 프로젝트 설정
별다른 이유가 없다면 대부분 TypeScript + SWC 또는 JavaScript + SWC를 선택했을 것이다.
이제 node 의존 패키지들을 설치해주고, 간단하게 프로젝트 설정을 해보자.
프로젝트를 만든 상태에서, 터미널에 다음 명령어들을 입력한다.
조금 기다리면 npm을 통해 node 의존 패키지를 모두 설치할 것이다.
설치가 완료되면, 다음 명령어를 통해 프로젝트의 개발 서버를 시작할 수 있다.
해당 명령어를 입력하면 이와같이 출력된다.
이 화면에서 h를 입력하고 Enter를 누르면 단축키가 나온다.
o Enter는 브라우저에서 개발 서버를 열어볼 수 있고,
q Enter로 개발 서버를 종료할 수 있으니 참고하자.
이후 항목들은 모두 선택이니, 이후 바로 개발을 시작해도 좋고, 다음 내용을 진행해도 좋다.
3.1. path alias (경로 별칭)
프로젝트를 진행하다보면 다른 파일을 import하는 경우가 매우 많다. 이 때, 상대경로를 사용하게 되는데, 같은 경로에 있거나 경로가 간단하다면 상관 없지만, 프로젝트의 파일이 많이 폴더를 만들어 파일을 분류하다보면, 다음과 같이 불상사가 생기기도 한다.
경로 별칭은 이러한 경로를 다음과 같이 절대경로 처럼 간단히 만들 수 있다.
이렇게 별칭을 설정하면, 우선 vite.config.js(TypeScript는 vite.config.ts) 파일을 다음과 같이 상단의 import 구문과 alias를 추가하여 수정한다.
이 때, import path from 'path'; 구문에서 오류가 발생한다면, 프로젝트 경로의 터미널에서 다음과 같이 입력하여 @types/node를 설치한다.
TypeScript를 사용하는 경우, tsconfig도 함께 설정해주어야 한다. 별다른 설정을 하지 않은 최신버전의 Vite를 사용했다면, 프로젝트 폴더에는 tsconfig.app.json이 있을 것이다. ts.config.app.json를 다음과 같이 수정해야 한다.
3.2. ESLint
Vite에는 기본적으로 ESLint가 설치되어 있는데, ESLint 또한 코드의 일관성을 위해 설치하는 패키지이다.
"ESLint는 코드의 문법적 오류나 잠재적 버그(코드 퀄리티)를 방지한다. 함수를 무조건 화살표함수만 사용하도록 한다거나, 사용하지 않는 변수나 선언을 제거하도록 강제하는 등의 동작을 통해, 팀원들 간에 코드의 문법을 통일하고, 가독성 좋게 만들어준다.
VS Code를 사용하고 있다면 Extension에서 ESLint를 설치하면 더 편하게 사용할 수 있으니 참고하자.eslint.config.js를 통해 추가적인 설정을 해볼 수 있다.
3.2.1. JavaScript 프로젝트의 경우
만약 추가적인 규칙은 커스텀하고 싶다면 다음을 참고하여 본인의 입맛에 맞게, 또는 팀원과 상의하여 작성한다.
rules의 값에는 3가지가 있다.
error: 설정한 규칙에 위배되면 오류가 남 (실행이 중단 됨)warn: 규칙에 위배되면 경고를 띄움 (실행 시 노란색으로 경고)off: 해당 규칙을 비활성화 함
default 값은 따로 없고, 각 플러그인의 설정에 따라 recommended 값이 있다. 하단의 rules 목록은 recommended 값으로 설정되어 있다.
몇몇 설정에 대한 설명을 추가하자면,
react/react-in-jsx-scope- 모든
.jsx파일의 상단에는import React from 'react'를 포함해야 하는지 결정하는데, 이는 React17 부터는 명시하지 않아도 된다.
- 모든
react-hooks/rules-of-hooks- Hooks(
useState등)의 선언 위치를 다음과 같이 강제한다.
- Hooks(
react/prop-types- 리액트 컴포넌트가 받는 props의 타입을 다음과 같이 명시하도록 강제한다.
3.2.2. TypeScript 프로젝트의 경우
3.3. Prettier
Prettier는 ESLint와 달리, 작성한 코드의 **스타일(줄 바꿈, 따옴표 통일 등)**에 관여한다.
예를 들어, "~~", '~~' 방식의 쌍따옴표와 작은따옴표가 혼용될 수 있는데, 이를 두 가지 중 하나로만 바꿔주거나, tab을 했을 때, 들여쓰기 단계를 자동적으로 조정해주는 등 코드의 가독성을 향상시켜준다.
VS Code를 사용하고 있다면 Extension에서 Prettier를 설치하면 더 편하게 사용할 수 있으니 참고하자.우선 다음 명령어를 통해 프로젝트에 prettier를 설치한다.
eslint-config-prettier는 ESLint와 규칙이 충돌하지 않도록 도와주는 역할을 한다.프로젝트의 최상위 폴더에 .prettierrc 라는 파일을 하나 만들고, 다음과 같은 설정들을 본인의 입맛에 맞게, 또는 팀원과 상의하여 설정 항목을 작성한다.
기본값을 유지하는 경우, 항목을 적지 않아도 된다.
일반적으로는 printWidth, SingleQuote, semi, trailingComma를 많이 수행하고, 필자의 경우 endOfLine을 "lf"로, tabWidth를 2로 설정하는 편이다.
이후, eslint.config.js에 prettier를 추가한다.
4. 프로젝트의 시작
이제, src 폴더에서 .jsx 또는 .tsx 파일을 만들고, 프로젝트를 시작해보자.