본문 바로가기
  • 인공지능
  • 블록체인
  • 정보보안
코딩 알로하 :: one/react.js

리액트 To-do 리스트 만들기 (7탄)

by nathan03 2022. 6. 3.
반응형

# 완성된 앱을 인터넷에 배포하기 

지금까지 우리가 개발 서버에서 사용한 파일들은 루트 경로의 src 와 public 폴더 안에 있는 파일들이었다. 개발 서버는 실시간으로 코드 변화를 감지해 컴파일하고 브라우저에 렌더링 하는 기능을 가지고 있기 때문에 매우 편리하지만, 실제 서비스로 사용하기에는 성능 면에서 적절하지 않다. 

실제 프로덕션 환경에서는 자바스크립트와 CSS파일을 최적화하는 Build 단계를 거치게 되는데, 이를 Create-react-app 으로 리액트 앱을 만들때 같이 설치되었던 Webpack 이 수행하게 된다. 

npm run build

 

# 배포 준비하기 
노드 서버 셋팅하기 
Node API 서버 프레임워크로 유명한 express 를 비롯한 패키지들을 설치해준다. 이전에 글로벌로 설치했던 json-server도 배포에 필요하기 때문에 로컬로 다시 한번 설치 한다. 

npm install json-server express path dotenv

그 다음 express server에서 구동하는데 필요한 server.js 파일을 만들어준다. 

//Server.js

const jsonServer = require("json-server");
const app = jsonServer.create();
const path = require("path");
const express = require("express");
const middlewares = jsonServer.defaults();
const router = jsonServer.router("src/db/data.json");

require("dotenv").config();
const port = process.env.PORT;

app.use('/api', middlewares, router);
app.use(express.static(path.join(__dirname, 'build')));
app.get('/*', function (req, res) {
res.sendFile(path.join(__dirname, 'build', 'index.html')); });
app.listen(port);
console.log(`Start server with port ${port}`)

위 코드에서 process.env 가 환경변수를 읽어오는 부분인데, 이를 위해서 .env 파일을 루트경로에 아래와 같이 만들어준다.

//.env

PORT=3000
REACT_APP_BACKEND_API_URI=/api

환경변수를 리액트에서도 사용할 수 있도록 하려면, REACT_APP이라는 prefix를 달아주어야 한다. 
이제 이 변수를 리액트에서 읽어오도록 index.js에 아래 두 라인을 추가한다.  

//Index.js

import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import dotenv from "dotenv"; // HERE dotenv.config(); // HERE
ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById("root")
);

이제 다른 컴포넌트에서 기존에 localhost:3001 으로 되어있던 경로를 모두 아래와 같이 교체한다.

`${process.env.REACT_APP_BACKEND_API_URI}/items/${todo.id}`
//Items.js

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

export default function Items({endpoint =""}) {
  const [data, setData] = useState([]);

  useEffect(() => {
    fetch(`${process.env.REACT_APP_BACKEND_API_URI}/items${endpoint}`)
      .then((res) => {
        return res.json();
      })
      .then((json_response) => {
        setData(json_response);
      });
  });

  return (
    <table>
        <td></td>
        <td>Task</td>
        <td>Due</td>
        <td>Status</td>
        {data.map(
          (item) => {
            return <Item key={item.id} item={item}/>
          }
        )}
    </table>
  );
}
//Item.js

import { useState } from "react";

export default function Item({ item: i }) {
  const [item, setItem] = useState(i);


  const toggle = () => {
    fetch(`${process.env.REACT_APP_BACKEND_API_URI}/items/${item.id}`, {
      method: "PUT",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        ...item,
        status: item.status ==="done"? "todo" : "done",
      })
    }).then((res) => {
      if (res.ok) {
        setItem({
        ...item,
        status: item.status ==="done"? "todo" : "done",
      });
      }
    });
  };

  const deleteItem = () => {
    if (window.confirm("삭제 하시겠습니까?")) {
      fetch(`${process.env.REACT_APP_BACKEND_API_URI}/items/${item.id}`, {
        method: "DELETE",
      }).then((res) => {
        if (res.ok) {
          setItem({ id: 0 });
        }
      });
    }
  };

  if (item.id === 0) {
    return null;
  }

  return (
    <tr>
      <td>
        <input
          type="checkbox"
          checked={item.status === "done" ? true : false}
          onClick={toggle}
        ></input>
      </td>
      <td>{item.task}</td>
      <td>{item.due}</td>
      <td>
        <button onClick={deleteItem}>Delete</button>
      </td>
    </tr>
  );
}
//CreateItem.js

import { useEffect, useRef, useState } from "react";
import { useNavigate } from "react-router-dom";

export default function CreateItem() {
  const [values, setValues] = useState({
    task: "",
    due: "",
  });

  const handleChange = (event) => {
    const { name, value } = event.target;
    setValues({
      ...values,
      [name]: value,
    });
  };

  const navigate = useNavigate();
  const ref = useRef();

  const onSubmit = (event) => {
      event.preventDefault();

      fetch("${process.env.REACT_APP_BACKEND_API_URI}", {
          method: "POST",
          headers: {
              "Content-Type" : "application/json"
          },
          body: JSON.stringify({
              task: values.task,
              due: values.due,
              status: "todo",
          }),
      }).then((res)=>{
          if(res.ok){
              alert("Created new item!");
              navigate("/todo");
          }
      });
  };

  return (
    <form onSubmit ={onSubmit}>
      <div className="input_area">
        <label>Task</label>
        <input
          type="text"
          name="task"
          value={values.task}
          onChange={handleChange}
        />
      </div>
      <div className="input_area">
        <label>Due</label>
        <input
          type="text"
          name="due"
          value={values.due}
          onChange={handleChange}
        />
      </div>
      <button>Create</button>
    </form>
  );
}

App.js 에 dotenv import 및 config 셋팅한다.

//App.js

import React from "react";
import Items from "./components/Items";
import Users from "./components/Users";
import Header from "./components/Header";
import CreateItem from "./components/CreateItem";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import dotenv from "dotenv";

dotenv.config();

export default function App() {
  return (
    <BrowserRouter>
      <div className="App">
        <Header />
        <Routes>
          <Route path="/" element={<Items />} />
          {/* <Route path="/user" element={<Users />} /> */}
          <Route path="/todo" element={<Items endpoint="?status=todo"/>} />
          <Route path="/done" element={<Items endpoint="?status=done"/>} />
          <Route path="/create_item" element={<CreateItem />} />
        </Routes>
      </div>
    </BrowserRouter>
  );
}

자, 여기까지 됐으면 이제 빌드를 해보자. 

npm run build


띠로리 빌드가 되지 않는다.!!!  dot.env 오류 ( 원인을 찾는중 )

그 다음 express server를 실행해 build 환경이 제대로 작동하는지 localhost:3001에서 체크할수 있다.

node server.js
반응형

댓글