
2024.02.21(수)
| 특징 | ⚛️Create React App(CRA) | ⚡Vite | 
|---|---|---|
| 빌드 도구 | webpack | ESBuild | 
| 언어 | JavaScript (Node.js) | Golang | 
| 서버 | Express | Koa | 
| 빌드 | Source build | Module build | 
| 환경 변수 접근 | process.env.KEY | import.meta.env.KEY | 
| Hot Module Replacement (HMR) | 지원 | 지원 | 
| 장점 | 간편한 설정: 초기 설정을 자동화하여 React 애플리케이션을 빠르게 시작 가능 | 빠른 빌드 속도: ESBuild를 사용하여 빠른 모듈 번들링을 제공하므로 초기 빌드 및 개발 서버의 성능이 우수 | 
| 단점 | 느린 빌드 속도: 큰 규모의 프로젝트에서는 빌드 속도가 느릴 수 있음 | 상대적으로 새로운 도구: 지원 및 커뮤니티가 CRA보다는 상대적으로 작음 | 
npx create-react-app my-app --template typescript
cd my-app
npm startnpm create vite@latest my-app -- --template react-ts
cd my-app
npm install
npm run dev💡 실제로 둘 다 설치해보니 설치부터 서버 시작까지 걸리는 시간이 Vite가 훨씬 빠른 것을 확인할 수 있었다.
| Directory | Description | 
|---|---|
| pages | 라우트에 대응하는 페이지 컴포넌트(컨테이너) | 
| components | 공통 컴포넌트 및 각 페이지에서 사용되는 컴포넌트 | 
| utils | 유틸리티 | 
| hooks | 리액트 훅 | 
| model | 모델(타입) | 
| api | API 연동을 위한 fetcher 등 | 

"typecheck": "tsc --noEmit --skipLibCheck"npm run typecheck로 사용 가능tsc: TypeScript Compiler--noEmit: JavaScript 파일을 생성 ❌--skipLibCheck: 라이브러리 파일에 대한 유형 검사를 건너뛰기
src/components/layout/Layout.tsximport Footer from "../common/Footer";
import Header from "../common/Header";
interface LayoutProps {
    children: React.ReactNode;
}
function Layout({ children }: LayoutProps) {
    return (
        <>
            <Header />
            <main>{children}</main>
            <Footer />
        </>
    );
}
export default Layout;💡 JSX Element ⊂ React Element ⊂ React Node
React.ReactNode: 모든 유형 가능
interface ModalRendererProps {
  title: string;
  children: React.ReactNode;
}
React.ReactElement: JSX element만 가능
interface ModalRendererProps {
  title: string;
  children: React.ReactElement;
}
모든 HTML 요소에 대한 기본 스타일을 초기화시키는 스타일 시트
브라우저의 기본 스타일을 완전히 제거하지 않고 각 요소를 표준화시켜 브라우저 간의 스타일 차이를 보완하는 스타일 시트
normalize.css의 발전된 버전
- 설치:
 npm install sanitize.css --save- 적용:
 import "sanitize.css";

function Header() {
    return (
        <header>
            <h1>Book Store</h1>
        </header>
    );
}
export default Header;import styled from "styled-components";
function Header() {
    return (
        <HeaderStyle>
            <h1>Book Store</h1>
        </HeaderStyle>
    );
}
const HeaderStyle = styled.header`
    background-color: #333;
    h1 {
        color: white;
    }
`;
export default Header;
💡 보통 styled components 코드의 길이도 길기 때문에 파일을 분리하여 작성한다고 함
src/style/global.ts
import "sanitize.css";
import { createGlobalStyle } from "styled-components";
import { ThemeName } from "./theme";
interface Props {
    themeName: ThemeName;
}
export const GlobalStyle = createGlobalStyle<Props>`
    body {
        padding: 0;
        margin: 0;
    }
    h1 {
        margin: 0;
    }
    * {
        color: ${
          ({themeName}) => (themeName === "light") ? "black" : "white"
        };
    }
`;
src/style/theme.ts
Theme의 color 정의 방법
export type ThemeName = "light" | "dark";
interface Theme {
    name: ThemeName;
    color: {
        [key: string]: string;
    };
}
export type ThemeName = "light" | "dark";
type ColorKey = "primary" | "background" | "secondary" | "third";
interface Theme {
    name: ThemeName;
    color: {
        [key in ColorKey]: string
    }
}
ColorKey 타입에 있는 각 문자열 리터럴을 반복하여 해당 문자열 리터럴을 키로 갖는 객체를 생성
color: {
    primary: string;
    background: string;
    secondary: string;
    third: string;
}
Utility Types: Record<Keys, Type>
export type ThemeName = "light" | "dark";
type ColorKey = "primary" | "background" | "secondary" | "third";
interface Theme {
    name: ThemeName;
    color: Record<ColorKey, string>;
}
Keys: 키 집합을 나타내는 타입 (여러 개 가능)
Type: 각 키에 대응하는 값의 타입 (단일 값)
⇒ 각 키는 주어진 값 타입에 매핑됨
export type ThemeName = "light" | "dark";
type ColorKey = "primary" | "background" | "secondary" | "third";
interface Theme {
    name: ThemeName;
    color: Record<ColorKey, string>;
}
export const light: Theme = {
    name: "light",
    color: {
        primary: "brown",
        background: "lightgray",
        secondary: "blue",
        third: "green",
    }
};
export const dark: Theme = {
    name: "dark",
    color: {
        primary: "coral",
        background: "midnightblue",
        secondary: "darkblue",
        third: "darkgreen",
    }
};
src/App.tsx
import Layout from "./components/layout/Layout";
import Detail from "./pages/Detail";
import Home from "./pages/Home";
import { GlobalStyle } from './style/global';
import { ThemeProvider } from "styled-components";
import { dark, light } from "./style/theme";
function App() {
  return (
    <ThemeProvider theme={light}>
      <GlobalStyle themeName="light"/>
      <Layout>
        <Home />
        {/* <Detail /> */}
      </Layout>
    </ThemeProvider>
  );
}
export default App;
실제 theme은 state를 사용해서 사용자에게 입력받을 예정