본문 바로가기

Web Frontend/React

React + Express 개발 환경 세팅

728x90

초보 개발자에게 있어 개발 프로젝트에서 넘어야 하는 첫 번째 난관은 개발 환경 세팅입니다. 개발 환경 세팅으로 몇 분, 혹은 몇 시간을 삽질로 태우게 된다면 '시작이 반이다' 라는 말에 격하게 공감하게 될 것입니다. 저도 공감하고 싶지는 않았습니다.

오늘은 React, Typescript, Tailwind를 사용하는 프론트엔드 개발 환경 설정과 Express로 서버를 만들어 client에서 data fetching을 할 수 있도록 하는 과정에 대해 설명하고자 합니다.

우선 프로젝트의 루트 폴더로 이동해서 server 디렉토리를 만들고 server로 이동해주세요

Express 서버 만들기

npm init -y

위의 코드로 package.json 파일을 만듭니다. 뒤에 붙는 -y는 모든 값을 디폴트로 하겠다는 의미입니다.

npm i express
npm i nodemon

express와 nodemon을 설치해 주세요.

touch server.js

server.js 파일을 생성하고 아래와 같이 작성해주세요.

// server.js
const express = require("express");
const app = express();
const port = 8080;

app.listen(port, () => {
  console.log("Server started!");
});

서버 실행을 nodemon으로 하기 위해 package.json을 수정합니다.

  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "nodemon server"
  },

이제 npm start를 입력하면 서버를 nodemon으로 실행할 수 있습니다.

하지만 실행해도 Cannot GET / 밖에 안 보일겁니다.

Frontend 환경 세팅

서버는 그대로 놔두고 터미널을 하나 더 열어봅시다.

vite를 이용해 개발 환경을 구성해봅시다
Project name은 client로 해주고
framework랑 variant는 자유롭게 설정해주시면 됩니다.
저는 React, TS + SWC를 선택했습니다.

cd client
npm i
npm run dev

위의 과정을 거쳐 npm run dev까지 입력하면 vite에서 기본 제공하는 까리한 웹페이지를 볼 수 있습니다. 하지만 저희에겐 필요없기 때문에 파일들을 정리해보겠습니다.

우선 public, assets 폴더를 통째로 지워줍니다.
App.css, App.tsx, index.css 3개의 파일은 내용을 전부 지워줍니다.

3개의 파일을 채우기 전에 tailwindcss 부터 설정해보겠습니다.

npm i tailwindcss postcss autoprefixer
npx tailwindcss init -p

tailwindcss, postcss, autoprefixer 를 설치하고 tailwind.config.js 와 postcss.config.js 파일을 생성하는 코드입니다. 왜인지는 모르지만 postcss와 autoprefixer를 설치 안하면 묘하게 tailwind가 적용되지 않으니 일단 시키는대로 전부 다 설치합니다.

순서대로 tailwind.config.js, App.css, App.tsx, index.css 파일을 아래와 같이 작성해주세요.

// tailwind.config.js
/** @type {import('tailwindcss').Config} */
export default {
  content: [
    "./pages/**/*.{ts,tsx}",
    "./components/**/*.{ts,tsx}",
    "./app/**/*.{ts,tsx}",
    "./src/**/*.{ts,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
};
 /* App.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
 // App.tsx
import "./App.css";

function App() {
  return <div className="text-red-500">COMIT</div>;
}

export default App;

마지막으로 index.css에는
http://meyerweb.com/eric/tools/css/reset/ 의 코드를 복붙해줍니다

// package.json  
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
    "preview": "vite preview",
    "start": "npx vite --port 3000"
  },

마지막으로 아래와 같이 start에 npx vite --port 3000을 설정해주면 npm start를 입력하는 것으로 코드를 실행할 수 있습니다. 실행하면 "text-red-500"으로 text가 빨간 것으로 보아 tailwindcss가 잘 적용된 것을 볼 수 있습니다.

혹시나 따라오는 도중에
'JSX.IntrinsicElements' 인터페이스가 없으므로 JSX 요소는 암시적으로 'any' 형식입니다
와 같은 에러가 발생하는 경우 vscode를 껐다가 다시 켜주시면 해결됩니다!

API 서버 생성 및 data fetching

다시 server로 돌아와 server.js에 간단한 API를 작성하겠습니다

const express = require("express");
const app = express();
const port = 8080;

app.get("/api/comit", (req, res) => {
  res.json({ message: "I love COMIT" });
});

app.listen(port, () => {
  console.log("Server started!");
});

/api/comit으로 GET 요청을 보내면
message: "I love COMIT"을 보내주는 간단한 API 입니다.
http://localhost:8080/api/comit 로 접속하면 확인할 수 있습니다.

이제 client에서 요청을 보내는 코드를 작성해보겠습니다.

import "./App.css";
import { useEffect, useState } from "react";

function App() {
  const [data, setData] = useState([{}]);
  useEffect(() => {
    fetch("http://localhost:8080/api/comit")
      .then((res) => res.json())
      .then((data) => setData(data));
  }, []);
  return <div className="text-red-500">{data.message}</div>;
}

export default App;

서버로 요청을 보내 data에 응답을 저장하고 data.message를 표시하는 코드입니다. 정상 작동한다면 "I love COMIT"이 보여야 하는데 아마 안 될 겁니다.

다시 server로 돌아와서 cors를 설치하고

npm i cors
const express = require("express");
const app = express();
const port = 8080;
const cors = require("cors");
const bodyParser = require("body-parser");

app.use(cors());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

app.get("/api/comit", (req, res) => {
  res.json({ message: "I love COMIT" });
});

app.listen(port, () => {
  console.log("Server started!");
});

위와 같이 server.js를 수정하면 정상 작동합니다.

위의 과정을 그대로 따라해도 잘 안된다면

client의 package.json에서 다음과 같이 proxy룰 추가해주세요

  "name": "client",
  "private": true,
  "version": "0.0.0",
  "proxy": "http://localhost:8080",
  "type": "module",

혹은 vite.config.ts 파일에서 proxy 설정을 할 수도 있습니다.

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react-swc";

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
  server: {
    proxy: {
      "/api": {
        target: "localhost:8080",
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, ""),
        secure: false,
        ws: true,
      },
    },
  },
});

마무리

이상 client, server 개발 환경 구축하는 과정에 대해 소개했습니다. 분명 한 번 해본 작업을 다시 정리해나가면서 글을 작성하고 있음에도 막히는 부분들이 있었습니다. 개발 환경 구축에 어려움을 느끼는 분들께 조금이나마 도움이 되길 바랍니다.

참고자료

https://www.youtube.com/watch?v=JoaTcz3K6do
https://tailwindcss.com/docs/guides/nextjs
https://abangpa1ace.tistory.com/entry/Expressjs-CORSCross-Origin-Resource-Sharing

728x90