react 라이브러리를 사용한다면 늘 Create React App을 통하여 프로젝트를 시작했었지만, 해당 강의에서는 처음 부터 하나하나 시작하는 점이 좋았습니다. webpack 및 babel 설정은 아주 오래전 한번 정도 해본 경험이 있는데 다시 한번 간단하게 흐름을 파악할 수 있어 도움이 되었습니다. 무엇보다 지금까지 편하게 쓰고 있었던 핫 리로딩 기능 및 Typescript에서 Javascript로 변환되는 과정에 대해서 좀 더 자세히 알 수 있었습니다.
# React 개발 환경에서 Hot Module Replacement위한 모듈
webpack-dev-server : 변경된 코드 전달
react-refresh : React 컴포넌트를 상태 보존하며 교체
@pmmmwh/react-refresh-webpack-plugin : 위 둘을 연결하는 Webpack 플러그인
강의 학습 후 Create React App을 통하여 환경 세팅을 보니 react-scripts 모듈을 통하여 모든 세팅을 관리하는 걸로 보였습니다. 상세한 커스터마이징은 제한적으로 보이므로 상황에 맞게 프로젝트를 구성하면 좋아 보였습니다.
react 에서 Router 기능을 손 쉽게 구현하기 위해서는 react-router 사용하면 됩니다. 강의 시점과 달리 현재 react-router 는 버전이 많이 달라진 결과 사용 방법도 조금 차이가 있습니다. 해당 노트에는 V7의 react-router 를 이용한 Router 구현 방법을 기록하였습니다.
// front/clinet/tsx
import React from 'react';
import App from '@layouts/App';
import { createRoot } from 'react-dom/client';
import { BrowserRouter } from 'react-router';
const root = createRoot(document.querySelector('#app') as HTMLElement);
root.render(
<BrowserRouter>
<App />
</BrowserRouter>,
);
BrowserRouter 를 이용하여 전체 앱을 감싸줍니다.
// front/layouts/App.tsx
import React from 'react';
import { Navigate, Route, Routes } from 'react-router';
import Login from '@pages/Login';
import SingUp from '@pages/SingUp';
const App = () => {
return (
<Routes>
<Route path="/" element={<Navigate to="/login" replace />} />
<Route path="/login" element={<Login />} />
<Route path="/signup" element={<SingUp />} />
</Routes>
);
};
export default App;
Route 를 이용하여 경로와 해당 경로에 출력 될 페이지를 연결시켜줍니다. 그리고 Route 들을 Routes 감싸줍니다.
큰 차이가 있지는 않지만 V7의 react-router 는 패키지가 간소화 되어 react-router-dom 을 사용하지 않아도 됩니다.
강의에서는 코드 스플리팅을 위해 외부 패키지를 사용하지만 현 시점의 React 에서는 자체적인 코드 스플링팅 기능이 있어 손 쉽게 사용가능합니다.
// 스플리팅 X
import Login from '@pages/Login';
import SingUp from '@pages/SingUp';
// 스플리팅 O
import { lazy } from 'react';
const Login = lazy(() => import('@pages/Login'));
const SingUp = lazy(() => import('@pages/SingUp'));
lazy를 사용하여 코드를 스플리팅할 수 있습니다.
import React, { lazy, Suspense } from 'react';
import { Navigate, Route, Routes } from 'react-router';
const Login = lazy(() => import('@pages/Login'));
const SingUp = lazy(() => import('@pages/SingUp'));
const App = () => {
return (
<Suspense fallback={<div>loading...</div>}>
<Routes>
<Route path="/" element={<Navigate to="/login" replace />} />
<Route path="/login" element={<Login />} />
<Route path="/signup" element={<SingUp />} />
</Routes>
</Suspense>
);
};
export default App;
또한 Suspense 를 사용하여 스플리팅된 코드를 로드하는 동안 화면에 대체 UI를 보여줄 수 있습니다. 스플리팅 할 코드들을 Suspense 로 감싸주어 사용 가능합니다.
Emotion은 JavaScript로 CSS 스타일을 작성하도록 설계된 라이브러리입니다.
그동안 스타일을 위한 라이브러리로는 Styled Components 와 Tailwind CSS 를 주로 사용해보았는데 Emotion 과 Styled Components 는 서로 많이 유사하여 바로 사용하기에 문제가 없어 보였습니다.
// styles.ts
import styled from '@emotion/styled';
export const Form = styled.form`
margin: 0 auto;
width: 400px;
max-width: 400px;
`;
export const Label = styled.label`
margin-bottom: 16px;
& > span {
display: block;
text-align: left;
padding-bottom: 8px;
font-size: 15px;
cursor: pointer;
line-height: 1.46666667;
font-weight: 700;
}
`;
// index.tsx
import { Form, Label } from './styles';
<Form onSubmit={onSubmit}>
<Label id="email-label">
<span>이메일 주소</span>
<div>
<input type="email" id="email" name="email" value={email} onChange={onChangeEmail} />
</div>
</Label>
</From>
Styled Components 와 비교하면 Emotion 은 css prop 기능을 이용하여 인라인 스타일을 클래스로 변환시켜 주며 SSR 에서 Styled Components 보다 더 간편하게 설정이 가능합니다.
버전 차이로 인한 설정 방법의 차이점이 있지만 덕분에 공식문서를 한번 더 확인할 수 있어 도움이 되었습니다. CRA를 사용하지 않고 처음부터 하나씩 프로젝트를 세팅하여 프로젝트의 구현 방식을 확인할 수 있어 큰 도움이 되었습니다.
wepback이 아닌vite로react프로젝트를 구현한다면 어떤 차이점이 있을까?