[Web] 웹개발 환경구축
1. Node.js 설치
우분투에서 개발 환경을 구축하여 진행하고자 한다.
Node.js 홈페이지에서 LTS 버전을 확인한 후에 아래 명령어를 실행한다.
아래 명령어에서 setup_18.x 부분은 버전에 맞게 수정한다.
$ curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
$ sudo apt install -y nodejs
2. Vite로 React 프로젝트 생성
설치 참고 : https://vitejs.dev/guide/
아래 명령어를 실행하여 리액트 프로젝트를 생성한다.
$ npm create vite@latest
- 생성된 폴더 내에서 
npm run dev명령어를 실행하면 실시간 미리보기가 가능하다. - 생성된 폴더 내에서 
npm run build명령어를 실행하면 build를 진행하며,npm run preview명령어를 실행하면 build된 결과를 preview로 볼 수 있다. 
3. Tailwind CSS 라이브러리 설치
(1) 설치
프로젝트 폴더 안에서 아래 명령어를 실행한다.
$ npm install tailwindcss @tailwindcss/vite
(2) vite.config.js 파일 수정
아래와 같이 파일을 수정한다.
import { defineConfig } from "vite";
import tailwindcss from "@tailwindcss/vite";
export default defineConfig({
  plugins: [tailwindcss()],
});
(3) index.css 파일 수정
파일에 아래 코드를 추가한다.
@import "tailwindcss";
(4) index.html 파일 수정
파일에 <link href="/src/styles.css" rel="stylesheet" /> 줄을 추가한다.
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <!-- 아래 줄 추가 -->
    <link href="/src/styles.css" rel="stylesheet" />
  </head>
  <body>
    <h1 class="text-3xl font-bold underline">Hello world!</h1>
  </body>
</html>
4. PWA 설정
웹페이지를 App처럼 PC나 모바일에 설치하고 오프라인으로 사용할 수도 있게 해주는게 PWA(Progressive Web App)이다.
(1) vite-plugin-pwa 설치
vite를 사용한다면 vite-plugin-pwa을 설치하여 좀 더 편하게 pwa를 사용할 수 있다.
아래와 같이 설치한다.
$ npm install vite-plugin-pwa -D
(2) 아이콘 이미지 생성
아이콘으로 사용할 이미지를 하나 만들어 https://www.favicon-generator.org/에서 기기, 크기 별 이미지로 변환한다.
변환된 이미지들은 public/img/icons 폴더에 넣어둔다.
(3) vite.config.js 파일 수정
vite.config.js 파일을 아래와 같이 수정한다.
import { VitePWA } from "vite-plugin-pwa";
export default defineConfig({
  plugins: [
    VitePWA({
      registerType: "autoUpdate",
      devOptions: {
        enabled: true,
      },
      workbox: {
        globPatterns: ["**/*.{js,css,html,ico,png,svg}"],
      },
      manifest: {
        name: "app name",
        short_name: "app short name",
        start_url: "/",
        scope: ".",
        display: "standalone",
        orientation: "portrait", // landscape // portrait // portrait-primary
        background_color: "#fff",
        theme_color: "#fff",
        description: "app description",
        dir: "ltr",
        lang: "ko-KR",
        icons: [
          {
            src: "/img/icons/android-icon-36x36.png",
            type: "image/png",
            sizes: "36x36",
          },
          {
            src: "/img/icons/android-icon-48x48.png",
            type: "image/png",
            sizes: "48x48",
          },
          {
            src: "/img/icons/android-icon-72x72.png",
            type: "image/png",
            sizes: "72x72",
          },
          {
            src: "/img/icons/android-icon-96x96.png",
            type: "image/png",
            sizes: "96x96",
          },
          {
            src: "/img/icons/android-icon-144x144.png",
            type: "image/png",
            sizes: "144x144",
          },
          {
            src: "/img/icons/android-icon-192x192.png",
            type: "image/png",
            sizes: "192x192",
          },
        ],
      },
    }),
  ],
});
import { VitePWA } from 'vite-plugin-pwa'추가- VitePWA 안에 registerType, devOptions (
dev에서 pwa 확인 가능하도록 설정), workbox (precache 할 파일들), manifest (manifest.webmanifest파일에 작성할 내용) 설정 
5. react-router-dom 라이브러리 설치
(1) 설치
설치 참고 : https://reactrouter.com/
리액트 프로젝트 폴더 안에서 아래 명령어를 실행하여 리액트 라우팅을 위한 외부라이브러리를 설치한다.
$ npm install react-router-dom@6
(2) 셋팅
src/main.jsx 파일을 아래와 같이 수정한다.
import React from "react";
import ReactDOM from "react-dom/client";
import { Provider } from "react-redux";
import { BrowserRouter } from "react-router-dom";
import App from "./App";
import "./index.css";
import store from "./store.js";
ReactDOM.createRoot(document.getElementById("root")).render(
  <React.StrictMode>
    <BrowserRouter>
      <Provider store={store}>
        <App />
      </Provider>
    </BrowserRouter>
  </React.StrictMode>
);
import { BrowserRouter } from "react-router-dom";추가<BrowserRouter>,</BrowserRouter>으로<App />을 감싸기
6. Redux toolkit 라이브러리 설치
(1) 설치
설치 참고 : https://redux-toolkit.js.org/
리액트의 state 사용을 편하게 하기 위해 Redux 개선 버전인 Redux toolkit을 설치한다.
리액트 프로젝트 폴더 안에서 명령어를 실행한다.
$ npm install @reduxjs/toolkit react-redux
(2) 셋팅
a. src/store.js 파일 생성
src/store.js 파일을 만들어 아래와 같이 작성한다.
이 파일을 통해 state 들을 보관한다.
import { configureStore } from "@reduxjs/toolkit";
const store = configureStore({
  reducer: {},
});
export default store;
b. src/main.jsx 파일 수정
src/main.jsx 파일을 아래와 같이 수정한다.
import React from "react";
import ReactDOM from "react-dom/client";
import { Provider } from "react-redux";
import { BrowserRouter } from "react-router-dom";
import App from "./App";
import "./index.css";
import store from "./store.js";
ReactDOM.createRoot(document.getElementById("root")).render(
  <React.StrictMode>
    <BrowserRouter>
      <Provider store={store}>
        <App />
      </Provider>
    </BrowserRouter>
  </React.StrictMode>
);
import { Provider } from "react-redux";추가import store from './store.js'추가<Provider store={store}>,</Provider>으로<App />을 감싸기
7. AXIOS 라이브러리 설치
(1) 설치
설치 참고 : https://axios-http.com/
리액트 프로젝트 폴더 안에서 아래 명령어를 통해 AJAX 외부라이브러리인 AXIOS를 설치한다.
$ npm install axios
(2) 사용
버튼 클릭 시에 데이터를 요청하는 아래 예시처럼 사용한다.
import axios from "axios";
function App() {
  return (
    <button
      onClick={() => {
        axios
          .get("https://url")
          .then((결과) => {
            console.log(결과.data);
          })
          .catch(() => {
            console.log("실패함");
          });
      }}
    >
      버튼
    </button>
  );
}
8. react-query 라이브러리 설치
(1) 설치
설치 참고 : https://tanstack.com/query/v4
실시간 데이터 ajax 처리 시에 편의성 향상을 준다는 react-query를 아래 명령어로 설치한다.
리액트 프로젝트 폴더 안에서 명령어를 실행한다.
$ npm install @tanstack/react-query
(2) 셋팅
a. 사용 시에 import 하기
import {
  QueryClient,
  QueryClientProvider,
  useQuery,
} from "@tanstack/react-query";
b. src/index.js 수정
src/index.js 파일을 아래와 같이 수정한다.
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
const queryClient = new QueryClient();
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <QueryClientProvider client={queryClient}>
    <Provider store={store}>
      <BrowserRouter>
        <App />
      </BrowserRouter>
    </Provider>
  </QueryClientProvider>
);
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'추가const queryClient = new QueryClient()추가<QueryClientProvider client={queryClient}>,</QueryClientProvider>으로<App/>부분 감싸기
(3) 사용
useQuery()로 ajax 요청을 감싸서 사용한다.
function App() {
  let result = useQuery("작명", () =>
    axios.get("https://url").then((a) => {
      return a.data;
    })
  );
  return (
    <div>
      {result.isLoading && "로딩중"}
      {result.error && "에러남"}
      {result.data && result.data.name}
    </div>
  );
}
- ajax요청이 로딩중일 땐 
result.isLoading이true - ajax요청이 실패시엔 
result.error가true - ajax요청이 성공시엔 
result.data안에 데이터가 들어옴 
9. ThreeJS 라이브러리 설치
(1) 설치
ThreeJS : https://threejs.org/
React-three-fiber : https://docs.pmnd.rs/react-three-fiber
React-three-drei : https://github.com/pmndrs/drei
3D 데이터를 다루기 위해 리액트 프로젝트 폴더에서 아래 명령어를 실행하여 관련 라이브러리를 설치한다.
$ npm install three
$ npm install @react-three/fiber
$ npm install @react-three/drei
10. Express 서버 설치
(1) 설치
별도의 서버를 위한 폴더를 새롭게 만든 후에 아래 명령어를 실행한다.
$ npm init -y
$ npm install express
$ npm install cors
$ npm install -g nodemon
(2) 서버 미리보기 실행
server.js 파일을 생성하여 아래 예시와 같이 작성한다.
const express = require("express");
const path = require("path");
const app = express();
const cors = require("cors");
app.use(express.json());
app.use(cors());
app.listen(8080, function () {
  console.log("listening on 8080");
});
아래 명령어를 통해 미리보기를 실행한다.
$ nodemon server.js
(3) React 연동
server.js 파일이 있는 폴더 안으로 연동할 리액트 프로젝트 폴더를 이동한다.
그 후에 server.js 파일에 아래와 같이 코드를 추가한다.
app.use(express.static(path.join(__dirname, "${리액트프로젝트이름}/build")));
app.get("/", function (요청, 응답) {
  응답.sendFile(
    path.join(__dirname, "/${리액트프로젝트이름}/build/index.html")
  );
});
리액트에서 라우팅을 하게 하려면 server.js 파일의 가장 하단에 아래 코드를 추가한다.
app.get("*", function (요청, 응답) {
  응답.sendFile(
    path.join(__dirname, "/${리액트프로젝트이름}/build/index.html")
  );
});