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