안녕하세요! 정말 오랜만에 포스팅을 하네요..하핳 취업 준비하면서 과제도 있고, 면접도 계속 보러 다니느라 적을 시간이 많이 없었습니다ㅠㅠ 결과가 좋진 않았지만..어쨌든 다시 일주일에 두 번 정도씩은 꾸준하게 포스팅할 것 같습니다. 오늘 글은 이번에 새로 시작하는 프로젝트 환결 설정하는 과정을 기록하려고 합니다. 위의 기술 스택을 사용하는 분들에게 도움이 됐으면 좋겠네요:)
먼저 위의 기술들을 왜 사용하는지 정리하고 가겠습니다.
기술 스택 선정 이유
1. Vite
ES build를 사용해 종속성을 미리 묶으며 기존 번들링보다 훨씬 빠르게 빌드를 진행할 수 있도록 해줘서 사용합니다.
더 자세한 내용은 아래 글을 참고해주세요! 이데 대해 설명하는 글도 작성하겠습니다.
2. Tailwind CSS
미리 설정된 유틸리티 클래스를 사용해 빠른 스타일링이 가능하고 사용되지 않는 CSS 클래스를 빌드 과정에서 제거하여 최종 파일 크기가 작아지는 이점이 있어 사용합니다.
3. TanStack Query
효율적인 API 통신을 위해 사용합니다.
4. Zod
TypeScript는 런타임 단계에서는 타입 에러를 잡을 수 없는 한계가 있습니다. 이를 보완하는 Zod를 이용해 타입 안정성을 유지하고 API 응답 결과 체크를 위해 사용합니다.
5. Zustand
새로운 프로젝트는 기업과 협업하여 그들의 문제를 함께 해결하는 과정이기에 프로젝트의 규모가 작습니다. 그렇기에 패키지 설치 후 빠르게 Store를 만들어 상태 관리를 할 수 있는 Zustand를 사용합니다.
6. Jest, RTL, MSW
이번 프로젝트를 TDD 방식으로 진행하게 되어 테스트 코드를 작성하기 위해 Jest와 RTL을 사용합니다. MSW는 외부 API 모킹을 위해 사용합니다.
개발 환결 설정
1. 프로젝트 초기화
npm create vite@latest {이름} -- --template react-ts
Vite를 이용해 Reat + TypeScript 기반 프로젝트 초기화
2. 필요 패키기 설치
Tailwind CSS 설치 및 초기화
설치
npm install tailwindcss@latest postcss@latest autoprefixer@latest
Tailwind CSS를 설치해줍니다. postcss와 autofixer는 Tailwind CSS를 사용하기 위해 설치하는 패키지입니다.
post CSS : TailwindCSS는 PostCSS 플러그인 형태로 작동하기 때문에 설치해야합니다. Tailwind가 제공하는 유틸리티 클래스들을 자동으로 생성하고, 필요한 경우 최적화합니다.
autoprefixer : postCSS 플러그인 중 하나로, CSS에 자동으로 공급업체 접두사(vendor prefixes)를 추가하여 여러 브라우저 간의 호환성을 보장해줍니다. 예를 들어, Flexbox, Grid와 같은 최신 CSS 기능은 일부 구형 브라우저에서 직접 지원하지 않고, -webkit-이나 -ms-와 같은 공급업체 접두사가 필요합니다. autoprefixer가 이를 자동으로 추가해줍니다.
초기화
npx tailwindcss init
postcss.config.cjs 파일을 만들어 아래의 설정 코드를 입력해 줍니다.
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
}
}
tailwind.config.js 파일을 만들어 아래의 설정 코드를 입력해 줍니다.
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ["./src/**/*.{js,ts,jsx,tsx}"],
theme: {
extend: {},
},
plugins: [],
};
cjs 파일을 사용하는 이유 : Node.js는 package.json에 "type": "module"이 있는 경우, 모든 .js 파일을 ECMAScript 모듈로 해석합니다. 때문에 그냥 js파일로 만들 경우에는 module이라는 변수가 정의되지 않은 상태에서 읽게되며 ECMAScript 모듈로 해석됩니다. 하지만 PostCSS 설정 파일은 CommonJS 형식을 사용해야 하기 때문에 cjs 파일로 만들어줘 위와 같은 문제가 발생하지 않도록 방지합니다.
ts 파일로 설정하고 싶다면 Config를 import 해서 해주면 됩니다. 예시는 아래와 같습니다.
import { Config } from 'tailwindcss'
const config: Config = {
content: ['./src/**/*.{js,ts,jsx,tsx}'],
theme: {
extend: {},
},
plugins: [],
}
export default config
tailwind.config.ts의 경우 파일을 인식하지 못할 경우를 대비해 postcss.config.js 파일에 다음 코드를 추가해 줘야합니다.
// postcss.config.js
module.exports = {
plugins: {
tailwindcss: { config: './tailwind.config.ts' },
autoprefixer: {},
},
}
마지막으로 글로벌 css 파일에 다음 코드를 추가하면 됩니다.
@tailwind base;
@tailwind components;
@tailwind utilities;
TanStack Query 설치 및 설정
설치
npm i @tanstack/react-query
설정
main.tsx에 기본 설정을 해 줍니다.
QueryCilent와 QueryCilentProvider를 불러와 App을 감싸줍니다.
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import App from "./App.tsx";
import "./index.css";
const queryCilent = new QueryClient();
createRoot(document.getElementById("root")!).render(
<QueryClientProvider client={queryCilent}>
<StrictMode>
<App />
</StrictMode>
</QueryClientProvider>
);
Zod 설치
npm i zod
▼ Zod 사용 방법 예시
import { z } from 'zod'
const UserSchema = z.object({
name: z.string(), // 문자열인지 검사
age: z.number().min(18), // 18 이하의 숫자인지 검사
})
type User = z.infer<typeof UserSchema>
Zustand 설치
npm i zustand
설치 후 바로 스토어를 만들어 사용해 주면 됩니다.
▼ 스토어 예시
// src/store.ts
import create from 'zustand'
interface BearState {
bears: number
increase: () => void
}
export const useBearStore = create<BearState>((set) => ({
bears: 0,
increase: () => set((state) => ({ bears: state.bears + 1 })),
}))
Jest & RTL 설치 및 설정
설치
npm i jest @testing-library/react @testing-library/jest-dom @types/jest ts-jest jest-environment-jsdom
- jest: JavaScript 테스트 프레임워크
- @testing-library/react: React 컴포넌트 테스트 라이브러리
- @testing-library/jest-dom: Jest용 DOM 사용자 정의 매처
- @types/jest: TypeScript 환경에서 Jest의 타입 정의
- ts-jest: TypeScript 코드를 Jest에서 사용할 수 있도록 하는 프리셋
- jest-environment-jsdom: Jest 환경을 JSDOM으로 설정 (브라우저 환경 시뮬레이션)
설정
jest.config.ts 파일 생성
export default {
testEnvironment: "jsdom",
transform: {
"^.+\\.tsx?$": "ts-jest",
},
moduleNameMapper: {
"^.+\\.svg$": "jest-svg-transformer",
"\\.(css|less|sass|scss)$": "identity-obj-proxy",
},
setupFilesAfterEnv: ["<rootDir>/jest.setup.ts"],
};
jest.setup.ts
import "@testing-library/jest-dom";
다음으로 ts 설정 파일을 변경 해줘야합니다. vite로 React + Ts 프로젝트를 생성할 경우 tsconfig.app.json과 tsconfig.node.json 파일이 생성되기 때문에 기존 방식과 조금 다르게 설정을 해줘야 합니다.
위의 방식은 tsconfig.json 파일이 공통적인 설정을 공유하고 참조를 관리하는 용도로 사용합니다. 각 하위 파일은 각 프로젝트에 ts 설정을 해주기 위해 사용됩니다. 공통 설정은 tsconfig.base.json을 통해 관리해줍니다. 설정 과정을 작성해보겠습니다.
tsconfig.app.json에 Jest와 RTL 관련 타입 정의를 추가하여 Jest와 RTL을 프로젝트 전반에서 사용할 수 있도록 해주면 됩니다.
tsconfig.app.json
{
"compilerOptions": {
...
/* Bundler mode */
...
/* Linting */
...
/* Jest and RTL types */
"types": ["jest", "@testing-library/jest-dom"]
},
"include": ["src"]
}
이렇게 설정한 후 script에 test를 추가하여 test 코드를 작성한 후 npm run test로 테스트를 진행할 수 있습니다.
MSW 설치 및 설정
설치
npm i msw
설정
msw가 2.x로 업그레이드 하면서 에러 방지를 위해 설치해줘야 하는 것들이 생겼습니다.
제가 작성한 위의 포스팅을 보면 왜 해당 에러가 발생하고 어떻게 해결했는지 나와있습니다. 아래의 글은 발생하는 에러들을 해결할 때 참고한 공식문서입니다. 자세한 내용은 위의 글을 통해 확인해 주시면 감사하겠습니다. 지금은 설정해야 하는 것들만 작성하고 넘어가겠습니다.
jest.config.ts에 아래 코드 추가
export default {
testEnvironmentOptions: {
customExportConditions: [''],
},
}
jest.polyfills.js 파일을 만들어 아래 코드 작성
// jest.polyfills.js
/**
* @note The block below contains polyfills for Node.js globals
* required for Jest to function when running JSDOM tests.
* These HAVE to be require's and HAVE to be in this exact
* order, since "undici" depends on the "TextEncoder" global API.
*
* Consider migrating to a more modern test runner if
* you don't want to deal with this.
*/
const { TextDecoder, TextEncoder } = require('node:util')
Object.defineProperties(globalThis, {
TextDecoder: { value: TextDecoder },
TextEncoder: { value: TextEncoder },
})
const { Blob, File } = require('node:buffer')
const { fetch, Headers, FormData, Request, Response } = require('undici')
Object.defineProperties(globalThis, {
fetch: { value: fetch, writable: true },
Blob: { value: Blob },
File: { value: File },
Headers: { value: Headers },
FormData: { value: FormData },
Request: { value: Request },
Response: { value: Response },
})
이렇게 한 후 핸들러 파일과 서버 파일을 만들어 사용하면 됩니다.
React Router 설치와 설정
마지막으로 React Router를 설치하고 라우팅 해준 후 마무리 하겠습니다.
설치
npm install react-router-dom
설정
먼저 router.tsx 파일을 따로 만들고 createBrowserRouter를 이용해 라우터 설정을 해 준니다.
import { createBrowserRouter } from "react-router-dom";
import App from "../App";
export const router = createBrowserRouter([
{
path: "/",
element: <App />,
},
]);
이후 main.tsx에서 라우터 파일과 RouterProvider를 불러와 아래와 같이 설정해 주면 됩니다.
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { RouterProvider } from "react-router-dom";
import { router } from "./routes/router.tsx";
import "./index.css";
const queryCilent = new QueryClient();
createRoot(document.getElementById("root")!).render(
<QueryClientProvider client={queryCilent}>
<StrictMode>
<RouterProvider router={router} />
</StrictMode>
</QueryClientProvider>
);
이상입니다.