Skip to main content

Command Palette

Search for a command to run...

React + Express 개발 환경 세팅

Updated
4 min read

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

오늘은 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

More from this blog

[ZSH] tree 사용하기

들어가며 큰 규모의 프로젝트를 출시한 뒤, 후일을 위해서 더 늦기 전에 파일 정리 및 문서화를 진행해야했다. 문서화 작업을 하는 중에 기왕 정리하는 거 파일 구조를 이쁘게 트리 구조로 나열하여 코멘트를 달면 나중에 보더라도 이해하기 더 쉬울 것 같았다. 어떻게 해야 간지나는 트리 구조를 만들 수 있을까 방법을 찾다보니 역시나 파일 구조를 트리로 이쁘게 출력해주는 커맨드 툴이 존재했다. tree 커맨드에 대해서 알아보고 알짜배기 내용만 정리했다....

Feb 21, 20242 min read

[Next.js] parallel routes & intercepting routes

트위터 로그인 모달창을 만들어보며 넥스트의 parallel routes 와 intercepting routes 을 학습한 내용을 정리해보았습니다. 트위터 로그인 창을 확인해봅시다. 루트 디렉토리 화면을 배경으로 i/flow/login 페이지가 동시에 표시되고 있습니다. 저는 app router 를 학습하기 전까지는 createPortal 을 사용하여 포탈 영역에 로그인 컴포넌트를 띄우는 방식을 사용했었습니다. const NoLogin =()=...

Feb 1, 20244 min read

C/C++ 이진 트리(binary tree) 개요 및 구현(1)

개요 트리는 노드들이 나무 가지처럼 연결된 비선형 계층적 자료구조이다. 하위 트리가 존재하고, 그 노드에 또 하위 트리가 존재하는 자료구조 이다. 트리의 맨 위에 있는 루트 노드가 존재한다. 우리가 알아볼 트리는 이진 트리이다. 이진 트리는 자식 노드(부모로부터 아래로 이어진 노드)가 2개 이하인 구조를 말한다. 트리의 사용 사례로는 다음과 같다 계층 적 데이터 저장(파일,폴더) 효율적인 검색 속도 힙 데이터 베이스의 인덱싱 트리에 ...

Jan 31, 20244 min read

[React] Server component (RSC)

React.js 18 에 도입된 리액트 서버 컴포넌트는 서버에서 동작하는 리액트 컴포넌트를 의미합니다. Next가 권장하는 라우팅 방식인 app router의 기반이 되는 컴포넌트이기 때문에 app router 를 이해하기 위해서는 server component 에 대한 이해가 필요합니다. server component 리액트는 클라이언트단만을 컴포넌트화하는 대신, server component라는 개념을 통해 서버 영역을 컴포넌트화합니다. ...

Jan 29, 20243 min read

Flutter, JavaScript

42 posts