1. Node.js 설치

설치 참고 : https://github.com/nodesource/distributions

우분투에서 개발 환경을 구축하여 진행하고자 한다.

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) 설치

설치 참고 : https://tailwindcss.com/docs/guides/vite

프로젝트 폴더 안에서 아래 명령어를 실행한다.

$ npm install -D tailwindcss postcss autoprefixer
$ npx tailwindcss init -p

(2) tailwind.config.cjs 파일 수정

아래와 같이 파일을 수정한다.

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./index.html",
    "./src/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}
  • content"./index.html", "./src/**/*.{js,ts,jsx,tsx}" 추가 작성

(3) index.css 파일 수정

파일에 아래 코드를 추가한다.

@tailwind base;
@tailwind components;
@tailwind utilities;


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.isLoadingtrue
  • ajax요청이 실패시엔 result.errortrue
  • 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'));
});


Updated: