server.js

// 설치한 라이브러리를 가져온다
const express = require('express');
const app = express();      // 기본적으로 express를 사용할 수 있는 변수를 생성

// express포트 설정
const PORT = process.env.PORT || 5000;


const bodyParser = require('body-parser');
const cors = require('cors');

// config body-parser
app.use(bodyParser.json());
app.use(cors());

// mysql 데이터베이스 사용
const mysql = require('mysql');

// db 접속 정보 
const db = mysql.createConnection({
    host: "127.0.0.1",
    user: "user_icia",
    password: "1111",
    port: "3306",
    database: "db_icia"
});

//db접속
db.connect((err)=>{
    if(!err){
        console.log('db접속 성공!');
    } else {
        console.log('db접속 실패!');
    }
});

// 서버 접속
app.listen(PORT, () => {
    console.log(`Server On : http://localhost:${PORT}`);
});

// 처음 express에 접속 했을 경우
app.get('/', (req, res) => {
    console.log('root!');
});


// 게시글 목록 불러오기
app.get('/list', (req, res) => {
    console.log(`app.get('/list')`);
    
    const sql = "select * from board order by id desc";
    db.query(sql, (err, data) => {
        if(!err){
            // console.log(data);
            res.send(data);
        } else {
            console.log(err);
        }
    });
});

// 게시글 상세보기
app.get('/view/:id', (req, res) => {
    const id = req.params.id;
    console.log(`app.get('/view/${id}')`);


    const sql = "select * from board where id=?";
    db.query(sql, [id], function(err, data) {
        if(!err){
            console.log(data);
            res.send(data);
        } else {
            console.log(err);
        }
    });
});




//게시글 등록
app.post('/insert', function(req, res) {
    const title=req.body.title;
    const contents=req.body.contents;
    const writer=req.body.writer;

    console.log(title, contents, writer);

    const sql='insert into board(title, contents, writer) values(?,?,?)';

    db.query(sql, [title, contents, writer], function(err, data){
        if(!err){
            console.log(data);
            res.sendStatus(200);
        } else {
            console.log(err);
        }
        
    });
});

//게시글 수정
app.post("/update/:id", function(req, res) {
    console.log(`수정 확인!`);

    const id = req.params.id;
    const title=req.body.title;
    const contents=req.body.contents;
    const writer=req.body.writer;

    console.log(id, title, contents, writer);

    const sql='update board set title=?, contents=?, writer=? where id=?';

    db.query(sql, [title, contents, writer, id], function(err, data){
        if(!err){
            console.log(data);
            res.sendStatus(200);
        } else {
            console.log(err);
        }
    });
});

// 게시글 삭제
app.post('/delete/:id', (req, res) => {
    
});

 

App.js

import './App.css';
import 'bootstrap/dist/css/bootstrap.min.css';
import BoardMain from './component/BoardMain';

function App() {

  return (
    <div className="App">
      <BoardMain />
    </div>
  );
}

export default App;

BoardMain.jsx

import { BrowserRouter, Routes, Route } from 'react-router-dom';
import BoardMain from './BoardMain';
import BoardWrite from './BoardWrite';
import BoardView from './BoardView';
import BoardList from './BoardList';
import BoardModify from './BoardModify';

const BoardMain = () => {

    return (
        <div id="board-main">
            <BrowserRouter>
                <Routes>
                    <Route path="/" element={<BoardList />} />
                    <Route path="/list" element={<BoardList />} />
                    <Route path="/write" element={<BoardWrite />} />
                    <Route path="/view/:id" element={<BoardView />} />
                    <Route path="/modify/:id" element={<BoardModify />} />
                </Routes>
            </BrowserRouter>
        </div>
    )
}

export default BoardMain;

BoardList.jsx

import { Table, Button} from 'react-bootstrap'
import { useEffect , useState } from 'react';
import axios from 'axios';
import {Link} from 'react-router-dom'

const BoardList = () => {

    const [boardList, setBoardList] = useState({});

    // hook의 일종
    // 마운트와 업데이트 사이
    // 컴포넌트가 랜더링 될 때 , 업데이트 될 때 실행
    
    const getBoardData = async () => {
        const boards = await axios('/list');
        console.log(boards);
        setBoardList(boards.data);
    }

    useEffect(() => {
        getBoardData()
    }, []); // 



    if(boardList.length>0){
        return(
            <div className='board-list'>
                <h1>게시글 목록</h1>

                <Table striped bordered hover>
                <thead>
                    <tr>
                        <th>번호</th>
                        <th>제목</th>
                        <th>작성자</th>
                        <th>작성일</th>
                    </tr>
                </thead>
                <tbody>
                        {boardList.map(boards=>(
                        <tr >
                            <td>{boards.id}</td>
                            <td><Link to={`/view/${boards.id}`}>{boards.title}</Link></td>
                            <td>{boards.writer}</td>
                            <td>{boards.reg_date}</td>
                        </tr>)
                        )}
                    </tbody>
                
            </Table>
            <Link to={`/write`} >
                    <Button className='mx-2 btnWrite'>작성하기</Button>
                </Link>
            </div>
                
           
        );
    }


}

export default BoardList;

BoardWrite.jsx

import axios from 'axios';
import React, { useState } from 'react'
import { Row, Col, Form, Button } from 'react-bootstrap'


const BoardWrite = () => {

    const [form, setForm] = useState({
        title: '',
        contents: '',
        writer: ''
    });

    const { title, contents, writer } = form;

    const onChange = (e) => {
        setForm({
            ...form, 
            [e.target.name] : e.target.value
        })
    }

    const onSubmit = async () => {
        if (title === '') {
            alert('제목을 입력하세요!');
        } else if (contents === '') {
            alert('내용을 입력하세요!');
        } else {
            if (window.confirm('게시글을 등록하시겠습니까?')) {
                await axios.post('/insert', form);
                window.location.href = "/list";
            }
        }
    }

    const onReset = () => {
        setForm({
            ...form,
            title: '',
            contents: '',
            writer: ''
        });
    }

    return (
        <Row className='my-5'>
            <Col className='p-5'>
                <h1 className='text-center my-5'>게시글 작성</h1>
                <Form>
                    <h4>제목</h4><Form.Control placeholder='제목을 입력하세요.'
                        className='my-3' name='title' value={title} onChange={onChange} />

                    <h4>작성자</h4><Form.Control placeholder='작성자를 입력하세요.'
                        className='my-3' name='writer' value={writer} onChange={onChange} />

                    <h4>내용</h4><Form.Control as='textarea' rows={10} placeholder='내용을 입력하세요.'
                        className='my-3' name='contents' value={contents} onChange={onChange} />

                    <div className='text-center'>
                        <Button className='mx-2 px-3 btn-sm' onClick={onSubmit}>저장</Button>
                        <Button className='mx-2 px-3 btn-sm' onClick={onReset} variant='secondary'>초기화</Button>
                    </div>
                </Form>
            </Col>
        </Row>
    )
}

export default BoardWrite;​

 

BoardView.jsx

import React, { useEffect, useState } from 'react';
import { useParams , Link  } from 'react-router-dom';
import axios from 'axios';
import {Row, Col, Button, Card} from 'react-bootstrap'


const BoardView = () => {

    const { id } = useParams(); // /board/:id와 동일한 변수명으로 데이터를 꺼낼 수 있습니다.
    const [board, setBoard] = useState({});

    const getBoard = async () => {
        const board = await axios.get(`/view/${id}`);
        console.log(`/view/${id}`);
        setBoard(board.data[0]);
    }

    useEffect(() => {
        getBoard();
    },[]);

    const onDelete = async() => {
        if(window.confirm(id + '번 게시글을 삭제하시겠습니까?')) {
            
        }
    }

    return (
        
        <div className="board-view">
            <Row className='my-5'>
            <Col className='px-5'>
                <h1 className='my-5 text-center'>{board.id}번 게시글 정보</h1>
                <div className='text-end my-2'>
                    <Link to={`/modify/${id}`}>
                        <Button className='btn-sm mx-2'>수정</Button>
                    </Link>
                    <Button className='btn-sm' variant='danger'
                        onClick={onDelete}>삭제</Button>
                </div>
                <Card>
                    <Card.Body>
                        <h5>[{board.id}] {board.title}</h5>
                        <hr/>
                        <div className='cArea'>{board.contents}</div>
                    </Card.Body>
                    <Card.Footer>
                        Created on {board.reg_date} by {board.writer}
                    </Card.Footer>
                </Card>
            </Col>
        </Row>
        </div>
    );
};

export default BoardView;

BoardModify.jsx

import React, { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
import axios from 'axios';
import { Row, Col, Form, Button } from 'react-bootstrap'


const BoardModify = () => {

    const { id } = useParams();

    const [board, setBoard] = useState({});
    const getBoard = async () => {
        const board = await (await axios.get(`/view/${id}`));
        setBoard(board.data[0]);
    };
    useEffect(() => {
        getBoard();
    },[]);
    
    
    const [form, setForm] = useState({
        title: '',
        contents: '',
        writer: ''
    });

    const { title, contents, writer } = form;

    const onChange = (e) => {
        setForm({
            ...form,
            [e.target.name]: e.target.value
        })
    }

    const onReset = () => {
        setForm({
            ...form,
            title: '',
            contents: '',
            writer: ''
        });
    }

    const onSubmit = async () => {
        if (title === '') {
            alert('제목을 입력하세요!');
        } else if (contents === '') {
            alert('내용을 입력하세요!');
        } else {
            if (window.confirm('게시글을 수정하시겠습니까?')) {
                await axios.post(`/update/${id}`, form);
                window.location.href = "/list";
            }
        }
    }

    

    return (
        <Row className='my-5'>
            <Col className='p-5'>
                <h1 className='text-center my-5'>게시글 수정</h1>
                <Form>
                    <h4>제목</h4> <Form.Control placeholder={board.title}
                        className='my-3' name='title' value={title} onChange={onChange} />

                    <h4>작성자</h4><Form.Control placeholder={board.writer}
                        className='my-3' name='writer' value={writer} onChange={onChange} />

                    <h4>내용</h4><Form.Control as='textarea' rows={10} placeholder={board.contents}
                        className='my-3' name='contents' value={contents} onChange={onChange} />
                    <div className='text-center'>
                        <Button className='mx-2 px-3 btn-sm'
                            onClick={onSubmit}>저장</Button>
                        <Button className='mx-2 px-3 btn-sm'
                            onClick={onReset} variant='secondary'>초기화</Button>
                    </div>
                </Form>
            </Col>
        </Row>
    );
};

export default BoardModify;​

 

package.json

{
  "name": "board-test",
  "version": "0.1.0",
  "private": true,
  "proxy": "http://localhost:5000/",
  "dependencies": {
    "@testing-library/jest-dom": "^5.17.0",
    "@testing-library/react": "^13.4.0",
    "@testing-library/user-event": "^13.5.0",

    "axios": "^1.5.1",
    "body-parser": "^1.20.2",
    "bootstrap": "^5.3.2",
    "cors": "^2.8.5",
    "express": "^4.18.2",
    "json": "^11.0.0",
    "mysql": "^2.18.1",
    "nodemon": "^3.0.1",
    "react": "^18.2.0",
    "react-bootstrap": "^2.9.0",
    "react-dom": "^18.2.0",
    "react-router-dom": "^6.16.0",
    "react-scripts": "5.0.1",
    "web-vitals": "^2.1.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

+ Recent posts