본문 바로가기
React

[React] 리액트로 간단한 게시판 만들기 (simple board/ CRUD)

by yuraming 2023. 10. 6.

기본 설정

 

프로젝트 파일 생성

$ npx create-react-app '프로젝트명'

간단한 레이아웃과 css 적용을 위해 부트스트랩을 사용하겠습니다.  (필수 x)

참조 :  https://react-bootstrap.github.io/

 

react bootstrap 설치 

$ npm install react-bootstrap bootstrap

<App.js> 상단에 import 합니다.

import 'bootstrap/dist/css/bootstrap.min.css';

필요한 부트스트랩 component도 import.

 

 


서버 기본 세팅

XAMPP에서 서버 M SQL DB,  Apache server 실행

 

 

같은 root에 서버 폴더 생성하고 터미널에 명령어 입력

 

node express 서버 실행

//패키지 json 설치
$ npm init -y  

//express ,  body-parse, mysql  설치
$ npm install express body-parser mysql  

$ npm install nodemon


npm init -y  : Node.js 프로젝트를 초기화,  

(-y 플래그는 기본값으로 자동으로 초기화까지 실행)

명령어 실행 시 , 프로젝트에 대한 기본 정보와 종속성에 관한 정보가 담긴 package.json 파일이 생성

 

$ npm install express body-parser mysql 

Express 프레임워크, body-parser 미들웨어,  MySQL 드라이버 한번에 설치

Express: 웹 애플리케이션 및 API를 구축하기 위한 Node.js 프레임워크.  라우팅, 미들웨어 관리, HTTP 요청 및 응답 처리 등을 수행
body-parser:  Express에서  POST 요청의 바디를 파싱하는 역할을 하는 미들웨어. (클라이언트에서 전송된 데이터 사용 가능)
mysql:  MySQL 데이터베이스와 상호 작용하기 위한 Node.js 드라이버.  Node.js 애플리케이션에서 MySQL 데이터베이스에 연결하고 쿼리를 실행할 수 있음.


npm install nodemon

nodemon : Node.js 프로젝트에서 개발 서버를 자동으로 재시작하는 도구. 

코드를 수정-> 저장시 서버를 수동으로 다시 시작할 필요가 없게 해주는 편리한 도구로 Nodemon은 코드 변경을 감지하고 자동으로 서버를 재시작하여 개발 프로세스를 더 효율적으로 만들어줌

 

참조: https://expressjs.com/ko/

참조: https://expressjs.com/ko/starter/hello-world.html

 


in 서버 폴더 

생성한 서버 폴더 내에 불필요한 파일 정리 후, 

index.js 파일에서 작업, 

기본 포트 번호 확인, 

const express = require('express')
const app = express()
const port = 3000

app.get('/', (req, res) => {
  res.send('Hello World!')
})

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`)
})

터미널에서 index.js(작업중인 파일명) 으로 서버 실행

// 해당 파일 서버 실행
// node 파일명
$ node index.js

package json 에 추가

// package json에 추가
"scripts": {
    "test": "echo \\"Error: no test specified\\" && exit 1",
    "start": "node index.js",
    "dev" : "nodemon index.js"
    // 개발자 모드에서 확인하고 싶을떄
  },

 

$ npm run dev  //개발자 모드로 서버 실행

 

XAMPP → phpmyadmin( DBMS)

phpmyadmin에서 새로 데이터 베이스 생성 후, 테이블 생성

 

create table requested( rowno int );

const express = require('express')
const app = express()
const port = 3000

const mysql      = require('mysql');
const db = mysql.createConnection({
  host     : 'localhost',
  user     : 'root',   //사용자계정명
  password : '',   //사용자계정 암호
  database : 'react_bbs' //데이터베이스명
});

db.connect();


app.get('/', (req, res) => {
  // 서버에 접속하면 할일 
  res.send('Hello World!') 
  const sqlQuery = 'INSERT INTO requested (rowno) values (1)';
  db.query(sqlQuery, function(err, result) {
    if (err) throw err;
    //쿼리 실행 완료시, 
    res.send('Success!') 
  });  
})

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`)
})

db.end();
const cors = require('cors');
const express = require('express');
const app = express();
const port = process.env.port || 8000//프론트 단의 폴더 실행 시, 중복되지 않도록 port 변경 
const mysql = require('mysql');

app.use(express.json());   //json은 말 그대로 JSON 형태의 데이터 전달을 의미
app.use(express.urlencoded({extended: false}));

let corsOptions = {
origin: '*',
credentials:true //사용자 인증에 필요한 리소스 허용
}
app.use(cors(corsOptions));

//데이터 베이스 연결
const db = mysql.createConnection({
host : 'localhost',
user : 'react_bbs',    //사용자 계정 명
password : '12345' //사용자 암호 명
database : 'react_bbs'   //데이터베이스 
});

db.connect();

app.get('/', (req, res) => {
const sqlQuery = "INSERT INTO requested (rowno) values (1)";
db.query(sqlQuery, function(err, result) {
if (err) throw err;
res.send('success');
});
});
app.get('/list', (req, res) => {
 
const sqlQuery = "SELECT BOARD_ID, BOARD_TITLE, REGISTER_ID, DATE_FORMAT(REGISTER_DATE, '%Y-%m-%d') AS REGISTER_DATE FROM board";
db.query(sqlQuery, function(err, result) {
if (err) throw err;
res.send(result);
});
});
app.post('/insert', (req, res) => {
const {title, content} = req.body;

const sqlQuery = "INSERT INTO board (BOARD_TITLE, BOARD_CONTENT, REGISTER_ID) values (?, ?,'admin')";

db.query(sqlQuery,[title,content], function(err, result) {
if (err) throw err;
res.send(result);
});
});

app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})

// db.end();    //데이터 베이스 연결 종료

 

 

react에서 서버랑 통신하기위해서는 Axios (액시오스)가 필요합니다.

Axios 를 터미널에서 설치하고,  index.js  상단에  import .

 

Axios : 브라우저 및 Node.js에서 사용할 수 있는 Promise 기반의 HTTP 클라이언트 라이브러리.

Axios는 HTTP 요청을 수행하고 응답을 처리하는 간편하고 강력한 방법을 제공함.

https://axios-http.com/kr/docs/example

//axios 설치
$ npm install axios
import { Axios } from 'axios';

 

에러 시, 참고 :  https://www.npmjs.com/package/cors

서버 안전 여부 확인 → https://expressjs.com/en/resources/middleware/cors.html

 


[ READ ]

in 프론트 폴더 

src/BoardList.js 생성

import React, { Component } from "react";
import Table from "react-bootstrap/Table";
import Button from "react-bootstrap/Button";
import Axios from "axios";

/* eslint-disable react/prop-types */
class Board extends Component {
  render() {
    return (
      <tr>
        <td>
          <input
            type="checkbox"
            value={this.props.id}
            onChange={this.props.onCheckboxChange}
          />
        </td>
        <td>{this.props.id}</td>
        <td>{this.props.title}</td>
        <td>{this.props.REGISTER_ID}</td>
        <td>{this.props.REGISTER_DATE}</td>
      </tr>
    );
  }
}

/* eslint-disable react/prop-types */
class BoardList extends Component {
  state = {
    boardList: [],
    checkList: [],
  };

  getList = () => {
    Axios.get("<http://localhost:8000/list>")
      .then((result) => {
        const { data } = result;
        this.setState({
          boardList: data,
        });
        console.log(result);
      })
      .catch((error) => {
        // 에러 핸들링
        console.log(error);
      });
  };
  componentDidMount() {
    this.getList();
  }
  onCheckboxChange = (e) => {
    const list = this.state.checkList;
    list.push(e.target.value);
    this.setState({
      checkList: list,
    });
  };

  render() {
    console.log(this.state.checkList);
    return (
      <>
        <Table striped bordered hover>
          <thead>
            <tr>
              <th>선택</th>
              <th>#</th>
              <th>Title</th>
              <th>Wirter Id</th>
              <th>Date</th>
            </tr>
          </thead>
          <tbody>
            {this.state.boardList.map((item) => {
              return (
                <Board
                  /* eslint-disable react/prop-types */
                  key={item.BOARD_ID}
                  id={item.BOARD_ID}
                  title={item.BOARD_TITLE}
                  REGISTER_ID={item.REGISTER_ID}
                  REGISTER_DATE={item.REGISTER_DATE}
                  onCheckboxChange={this.onCheckboxChange}
                />
              );
            })}
          </tbody>
        </Table>
        <div className="d-flex gap-3">
          <Button variant="info">글쓰기</Button>
          <Button
            variant="secondary"
            onClick={() => {
              this.props.handleModify(this.state.checkList);
            }}
          >
            수정
          </Button>
          <Button variant="danger">삭제</Button>
        </div>
      </>
    );
  }
}
export default BoardList;

 

in 서버 폴더 

index.js에서 포트 번호 변경하고(프론트단이랑 겹치지 않도록), 

get 방식으로 db에서 데이터 가져오기

const cors = require("cors");
const express = require("express");
const mysql = require("mysql");
const app = express();
const port = process.env.port || 8000; //포트 번호 설정 

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

let corsOptions = {
  origin: "*",
  credentials: true, //사용자 인증에 필요한 리소스 허용
};
app.use(cors(corsOptions));

const db = mysql.createConnection({
  host: "localhost",
  user: "react_bbs",
  password: "12345",
  database: "react_bbs",
});

db.connect();

//get 방식으로 db에서 SELECT
app.get("/list", (req, res) => {
  const sqlQuery =
    "SELECT BOARD_ID, BOARD_TITLE, REGISTER_ID, DATE_FORMAT(REGISTER_DATE, '%Y-%m-%d') AS REGISTER_DATE  FROM board";
  db.query(sqlQuery, function (err, result) {
    if (err) throw err;
    res.send(result);
  });
});

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`);
});

아래 이미지 처럼 데이터 베이스의 데이터가 브라우저에 조회되는 것을 확인 할 수 있습니다.

데이터베이스 화면
브라우저 화면


[ CREATE ]

in 프론트 폴더 

src/Write.js 생성하고  Write 컴포넌트 생성 

class Write extends Component {
  state = {
    title: "",
    content: "",
  };

  write = () => {
    Axios.post("http://localhost:8000/insert", {
      title: this.state.title,
      content: this.state.content,
    })
      .then((result) => {
        console.log(result);
      })
      .catch((error) => {
        console.log(error);
      });
  };
 //input 값이 변경되면 할일
  handleChange = (e) => {  
    this.setState({
      [e.target.name]: e.target.value,
    });
  };

  render() {
    return (
      <>
        <Form>
          <Form.Group className="mb-3" controlId="exampleForm.ControlInput1">
            <Form.Label>Title</Form.Label>
            <Form.Control
              type="text"
              placeholder="writenp title"
              name="title"
              onChange={this.handleChange}
            />
          </Form.Group>
          <Form.Group className="mb-3" controlId="exampleForm.ControlTextarea1">
            <Form.Label>Content</Form.Label>
            <Form.Control
              as="textarea"
              rows={3}
              name="content"
              onChange={this.handleChange}
            />
          </Form.Group>
        </Form>
        <div className="d-flex gap-3 justify-content-end mt-5">
          <Button variant="primary" onClick={this.write}>
            Save
          </Button>
          <Button variant="secondary">Cancel</Button>
        </div>
      </>
    );
  }
}

export default Write;

 App/js에 Write 컴포넌트 import

import React from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import "./App.css";
import BoardList from "./BoardList";
import Write from "./Write";

function App() {
  return (
    <div className="App container">
      <h1>Simple Board</h1>
      <BoardList />
      <Write />
    </div>
  );
}

export default App;

 

in 서버 폴더 

post 방식으로 db 데이터 입력

const cors = require("cors");
const express = require("express");
const mysql = require("mysql");
const app = express();
const port = process.env.port || 8000; //포트 번호 설정 

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

let corsOptions = {
  origin: "*",
  credentials: true, //사용자 인증에 필요한 리소스 허용
};
app.use(cors(corsOptions));

const db = mysql.createConnection({
  host: "localhost",
  user: "react_bbs",
  password: "12345",
  database: "react_bbs",
});

db.connect();

app.get("/", (req, res) => {
  // res.send("Hello World!");
  const sqlQeury = "INSERT INTO requested (rowno) values (1)";
  db.query(sqlQeury, function (err, result) {
    if (err) throw err;
    res.send("success");
  });
});

app.get("/list", (req, res) => {
  const sqlQuery =
    "SELECT BOARD_ID, BOARD_TITLE, REGISTER_ID, DATE_FORMAT(REGISTER_DATE, '%Y-%m-%d') AS REGISTER_DATE  FROM board";
  db.query(sqlQuery, function (err, result) {
    if (err) throw err;
    res.send(result);
  });
});

app.post("/insert", (req, res) => {
  const { title, content } = req.body;
  const sqlQuery =
    "INSERT INTO board (BOARD_TITLE, BOARD_CONTENT, REGISTER_ID) values (?, ?,'admin')";
  db.query(sqlQuery, [title, content], function (err, result) {
    if (err) throw err;
    res.send(result);
  });
});

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`);
});

정상적으로 게시물 등록 됩니다.

게시판 글 작성
데이터 베이스 등록
데이터 베이스 조회

'React' 카테고리의 다른 글

[REACT] useMemo UseCallback  (1) 2024.02.12
[React] React Ajax 활용  (1) 2023.10.09
[React] Hooks 리액트 훅  (1) 2023.10.06
[React] 개발환경 설정 (기초)  (2) 2023.10.03