
지금까지 모든 미션은 초기 환경이 이미 세팅된 레포를 받아 시작했다. 그래서 개발 환경을 직접 구축하거나, 어떤 도구를 사용할지 고민해볼 기회가 거의 없었다. 이에 몇 가지 불편함이 있었다. ESLint만 해도 버전이 올라갈수록 설정 방식이 달라지고, 기존 설정과 충돌이 생겼다. 세팅에 대한 기본 이해가 부족하다 보니 문제를 마주했을 때 제대로 대응하지 못했고, 결국 GPT에 의존하게 됐다.
게다가 미션은 Vite를 빌더 도구로 사용하고 있지만, 언젠가 Parcel을 써보고 싶어질 수도 있다는 생각이 들었다. 그럴 때 자유롭게 도구를 바꾸고, 원하는 구성 요소를 넣다 뺄 수 있으려면 환경에 대한 이해가 필요하다고 느꼈다.
그래서 이번엔 누군가 미리 깔아준 환경이 아니라, 바닥부터 직접 하나씩 쌓아올리는 방식을 택했다. create-react-app이나 create-vite처럼 손쉽게 초기 설정을 끝내주는 도구들도 일부러 사용하지 않았다.
노드 버전 확인 → 노드 설치 → 프로젝트 폴더 생성 및 이동
node -v
fnm install --lis
fnm list
mkdir my-app
cd my-app
code .npm init -y.gitignore 파일을 생성한다.
touch .gitignorenpm i -D typescriptnpx tsc --initJSX 파일을 쓰겠다고 선언하는 부분이다. 하지만 이 부분이 없어도 정상적으로 동작한다.
"jsx": "react-jsx"npm i -D eslintnpx eslint --init상황에 맞게 질문에 대답한다.
설치할까요? y
Eslint 어떤 거에 사용할까요? 모두
자바스크립트 모듈 어떤거 사용할까요? JavaScript (import/export)
프레임워크는 어떤 거 쓸까요? react
타입스크립트 사용하나요? y
Browser, Node? Browser
스타일 가이드를 따르세요? 아니면 매번 물어볼까요? 전자
스탠다드를 따르세요? xo를 따르세요? xo
설정파일 어떻게 잡으시겠어요? js
추가 설치해도 되나요? y
패키지 매니저 뭐 쓸까요? npm (기본)plugin:react/jsx-runtime을 extends에 추가하면 됐지만 현재는 안됨.export default defineConfig([
  { files: ["**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"], plugins: { js }, extends: ["js/recommended"], },
  { files: ["**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"], languageOptions: { globals: globals.browser}, 
  },
  tseslint.configs.recommended,
  pluginReact.configs.flat.recommended,
  {
    // 🚨 react version 명시
    settings: {
      react: { 
        version: "detect",
      },
    },
  },
  {
    // 🚨 'react/react-in-jsx-scope' 규칙을 'off'로 설정
    rules: {
      "react/react-in-jsx-scope": "off",
      "react/jsx-uses-react": "off",
      indent: ['error', 2],
    },
    // 🚨 ignore 설정
    ignores: ['**/node_modules/**', '**/dist/**', '**/build/**'],
  },
]);mkdir .vscode
touch .vscode/settings.jsonsettings.json 파일에는 Lint가 잡을 것을 설정한다.
예를 들어, 80열에서 줄 긋기, save하면 끝에 있는 줄 삭제를 추가할 수 있다.
{
  "editor.rulers": [80],
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": "always" // S/TS 파일을 저장할 때마다 ESLint를 실행하고 문제점을 고치게 설정
  },
  "trailing-spaces.trimOnSave": true
}npm i react react-domnpm i -D @types/react @types/react-dom// /index.html
<!DOCTYPE html>
<html lang="ko">
	<head>
		<meta charset="UTF-8">
		<meta http-equiv="X-UA-Compatible" content="IE=edge">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>Document</title>
	</head>
	<body>
		<div id="root"></div>
		<script type="module" src="main.tsx"></script>
	</body>
</html>// /main.tsx
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./src/App";
ReactDOM.createRoot(document.getElementById("root")!).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);// src/App.tsx
export default function App() {
  return <>Hello</>;
}  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "check": "tsc --noEmit",
    "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
    "test": "jest",
    "coverage": "jest --coverage --coverage-reporters html",
    "watch:test": "jest --watchAll",
    "preview": "vite preview",
    "storybook": "storybook dev -p 6006",
    "build-storybook": "storybook build"
  },세팅을 하면서 Velog 같은 레거시 문서를 참고하지 않고, 공식 문서를 참고했다. 이유는 버전이 바뀌면서 설치되는 파일도 달라지고 설정 방식도 바뀌었기 때문에 레거시 문서를 믿을 수 없었다.
예를 들어, ESLint도 예전에는 JSX 파일에서 React를 직접 import하지 않아도 되게 하려면 plugin:react/jsx-runtime을 extends에 추가하면 됐었다. 그런데 현재 사용하는 Flat config에서는 plugin: 접두사가 더 이상 지원되지 않기 때문에 이 설정을 쓸 수 없었다. 그래서 react/react-in-jsx-scope 규칙을 off로 설정해서 React import를 강제하지 않도록 바꿨다.
공식 문서를 따라가며 하나하나 설정해보니, 생각보다 어렵지 않았다. 앞으로는 create-react-app 같은 도구의 도움을 받더라도 필요한 설정은 직접 커스텀할 수 있겠다는 자신감이 생겼다.