본문 바로가기
프로젝트 기록/React, Node.js를 이용한 게시판 만들기

1. React와 Node.js를 사용한 게시판 웹 애플리케이션 만들기 - 게시판 만들기, 게시글 목록 자동 갱신, 글 추가, Router 설정, CORS 설정, MySQL

by jeong11 2024. 11. 6.
반응형

Todo

구현할 기능 : CRUD(게시글 작성, 조회, 수정, 삭제) 

RESTful API 이해하기

https://tiny-immj.tistory.com/88

 

RESTful API 이해하기 + Express로 간단 API 만들기, Postman 사용법

~ 포스팅 진행 순서  ~REST, REST APIRESTful설계원칙API 구현하기=> REST, REST API, RESTful의 기본 개념과 간단한 api 만드는 방법 진행=> RESTful API는 데이터를 표준화된 방식으로 주고 받을 수 있게 해주고,

tiny-immj.tistory.com

 


프로젝트 정보

프론트엔드 : React

백엔드 : Node.js

세팅 참조
https://tiny-immj.tistory.com/78

 

React, node.js를 이용한 기초 프로젝트 생성(for mac)

1. 개발 세팅 준비1-1. Node.js 설치하기 https://nodejs.org/ Node.js — Run JavaScript EverywhereNode.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.nodejs.org  pkg 파일이 다운받아지면 실행시켜 설치해주세

tiny-immj.tistory.com

DB : MySQL

DB 세팅

https://tiny-immj.tistory.com/79

 

React, node.js를 사용한 게시판 만들기 - db 세팅

이전에 node.js, npm, git 세팅을 하고 기초 프로젝트를 만들었다https://tiny-immj.tistory.com/78 React와 node.js를 이용한 기초 프로젝트 생성(for mac)1. 개발 세팅 준비1-1. Node.js 설치하기 https://nodejs.org/ Node.j

tiny-immj.tistory.com


 

0. 진행 방향

front : React로 구성되며, 게시글 리스트, 게시글 작성/수정 폼, 게시글 상세보기 등을 구현
back : Node.js와  Express를 사용해 API를 만들고 MySQL과 연결해 게시글 데이터를 처리 

 

프로젝트 구조 

프로젝트 구조 미리보기

src\components : React 프론트엔드

server 폴더 : Node.js 백엔드

db.js : MySQL 연결 설정

server.js : Express 서버 설정

 

 

1. Backend 백엔드

: Node.js와 Express로 API 구현하기

 

1-1. 프로젝트 생성

그냥 생성해서 세팅해도 되지만 귀찮아서 npx로 생성

npx create-react-app react-node-app

npx로 프로젝트 생성

▷ npx : 라이브러리 설치를 도와주는 명령어. Node.js 설치가 되어있어야 사용이 가능함

▷ create-react-app : React 세팅이 다 된 boilerplate를 만들기 쉽게 도와주는 라이브러리(Create React App 라이브러리)

▷ react-node-app : react-node-app 이름의 프로젝트를 만든다 

 

 

sucess! 사용할 수 있는 명령어도 알려준다

npm run start     //개발모드 서버 실행

☞ 개발 서버 실행으로 프로젝트가 잘 생성됬는지 확인해본다

 

 

1-2. MySQL과 Node.js 연결

1) MySQL 패키지 설치

npm install mysql

 

혹시 설치하다가 오류가 나면 참고해주세요

< npm install 명령어 실행시 warn - 해결방법 >

https://tiny-immj.tistory.com/90

 

[REACT] npm 패키지 설치 중 warn 이슈 - fsevents, requires a peer of typescript

* 이슈 증상* npm install mysql 해당 명령어 실행으로 패키지 설치 시 아래 경고들이 나타남 1. fsevents npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@2.3.3 (node_modules\fsevents): 혹은  npm WARN notsup SKIPPING

tiny-immj.tistory.com

 

 

2)  express 웹서버 프레임워크 설치

npm install express

 

 

3) MySQL 연결 설정 작성

> server\db.js 

db.js

// server/db.js
const mysql = require('mysql');

const connection = mysql.createConnection({
  host: 'localhost',
  user: 'yoor_userId',
  password: 'your_password',
  database: 'database_name'
});

connection.connect((err) => {
  if (err) {
    console.error('Error connecting to MySQL:', err);
    return;
  }
  console.log('Connected to MySQL');
});

module.exports = connection;

 

▷db.js에서 에러 발생

database를 처음 생성해줄 때 host 주소를 %로 지정해, 서버에서 사용할 수 있도록 만들어줬다 (MySQL에서 %는 와일드카드로 사용)

db.js의 host 부분을 host : '%'로 작성해줬더니 node server.js 명령어를 실행할 때 에러가 발생했다 

 

*에러 메시지 *

Error connecting to MySQL: Error: getaddrinfo ENOTFOUND % at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:69:26) -------------------- at Protocol._enqueue (D:\dev\REACT\react-node-app\node_modules\mysql\lib\protocol\Protocol.js:144:48) at Protocol.handshake (D:\dev\REACT\react-node-app\node_modules\mysql\lib\protocol\Protocol.js:51:23) at Connection.connect (D:\dev\REACT\react-node-app\node_modules\mysql\lib\Connection.js:116:18) at Object.<anonymous> (D:\dev\REACT\react-node-app\server\db.js:10:12) at Module._compile (internal/modules/cjs/loader.js:1072:14) at Object.Module._extensions..js (internal/modules/cjs/loader.js:1101:10) at Module.load (internal/modules/cjs/loader.js:937:32) at Function.Module._load (internal/modules/cjs/loader.js:778:12) at Module.require (internal/modules/cjs/loader.js:961:19) at require (internal/modules/cjs/helpers.js:92:18) { errno: -3008, code: 'ENOTFOUND', syscall: 'getaddrinfo', hostname: '%', fatal: true }

 

뭐가 잘못된건지 찾아봤더니 MySQL 데이터베이스에 연결하려고 할 때 ENOTFOUND 오류가 발생한 것으로, 해당 오류는 데이터베이스의 호스트 이름을 잘못 작성했을 때 발생하는 오류라고 한다

 

*해결 방법*

host : localhost

로 수정하였다 

 

 

1-3. 게시판 API 구현

> server\server.js

Express 서버와 게시판 api를 설정한다

const express = require('express');
const cors = require('cors');  // CORS 패키지 추가
const db = require('./db');
const app = express();

app.use(cors());  // CORS 미들웨어 추가
app.use(express.json()); // JSON 요청을 처리하기 위해 필요

// 게시글 목록 조회 API
app.get('/api/posts', (req, res) => {
  const query = 'SELECT * FROM posts';
  db.query(query, (err, results) => {
    if (err) {
      return res.status(500).send('Error fetching posts');
    }
    res.json(results);
  });
});

// 게시글 작성 API
app.post('/api/posts', (req, res) => {
  const { title, content } = req.body;
  const query = 'INSERT INTO posts (title, content) VALUES (?, ?)';
  db.query(query, [title, content], (err, result) => {
    if (err) {
      return res.status(500).send('Error creating post');
    }
    res.status(201).send('Post created successfully');
  });
});

// 게시글 상세 정보 가져오기
app.get('/api/posts/:id', (req, res) => {
  const { id } = req.params;
  db.query('SELECT * FROM posts WHERE id = ?', [id], (err, results) => {
    if (err) {
      console.error(err);
      return res.status(500).json({ message: '서버 오류' });
    }
    if (results.length === 0) {
      return res.status(404).json({ message: '게시글을 찾을 수 없습니다' });
    }
    res.json(results[0]);
  });
});

// 게시글 수정 API
app.put('/api/posts/:id', (req, res) => {
  const { id } = req.params;
  const { title, content } = req.body;
  const query = 'UPDATE posts SET title = ?, content = ? WHERE id = ?';
  db.query(query, [title, content, id], (err, result) => {
    if (err) {
      return res.status(500).send('Error updating post');
    }
    res.send('Post updated successfully');
  });
});

// 게시글 삭제 API
app.delete('/api/posts/:id', (req, res) => {
  const { id } = req.params;
  const query = 'DELETE FROM posts WHERE id = ?';
  db.query(query, [id], (err, result) => {
    if (err) {
      return res.status(500).send('Error deleting post');
    }
    res.send('Post deleted successfully');
  });
});

// 서버 실행
const PORT = 5001;
app.listen(PORT, () => {
  console.log(`Server running on http://localhost:${PORT}`);
});

 

React 앱(포트 : 3000), Express 서버(포트 : 5001) 에서 사용하도록 설정이 되어있기 때문에 

CORS 문제(Cross-Origin Resource Sharing)가 발생해 서버 접속 요청이 차단될 수 있다

 

▷CORS 문제를 해결하기 위해 Express 서버에 CORS를 추가해줘야 한다

1) CORS 패키지 설치

npm install cors

npm install cors로 설치

2) CORS 미들웨어 적용

//server.js

const express = require('express');
const cors = require('cors');	// CORS 패키지 추가
const db = require('./db');
const app = express();

app.use(cors());	//CORS 미들웨어 추가
app.use(express.json());	//JSON 요청을 처리하기 위해 필요

//나머지 API 처리 코드

cors() 미들웨어를 추가하면 다른 포트(예 : localhost:3000)에서 오는 요청을 허용하게 되어, React 앱에서 API 요청을 보내는데 문제가 없어진다 

 

 

1-4. MySQL 테이블 설정

MySQL 접속 및 database 사용

1) MySQL 접속 

mysql -u root -p

설정한 비번 입력 (여기서는 ReactNode1!로 설정)

 

2) 전에 생성했었던 my_database를 사용할 것이다

USE my_database;

 

* 만약 생성하지 않았다면 새로 만들어준다

* DB 생성 명령어

CREATE DATABASE DBName;

테이블 생성 및 확인

 

3) 사용할 posts 테이블 생성

CREATE TABLE posts (
    id INT AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(255),
    content TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

 

4) 생성한 테이블 확인 

show tables;

 

이제 프론트엔드로 넘어간다


2. Frontend 프론트엔드

: React로 UI 만들기

 

2-1. 게시글 목록 페이지 구현

> src\components\PostList.js 

게시판 글 목록 PostList.js

import React, { useState, useEffect } from 'react';
import axios from 'axios';

function PostList() {
  const [posts, setPosts] = useState([]);

  useEffect(() => {
    axios.get('/api/posts')
      .then((response) => setPosts(response.data))
      .catch((error) => console.error('Error fetching posts:', error));
  }, []);

  return (
    <div>
      <h1>게시판</h1>
      <ul>
        {posts.map(post => (
          <li key={post.id}>
            <h3>{post.title}</h3>
            <p>{post.content}</p>
          </li>
        ))}
      </ul>
    </div>
  );
}

export default PostList;

=> 게시글 목록을 보여주는 컴포넌트

 

 

2-2. 게시글 작성 페이지 구현

> src\components\PostForm.js

PostForm.js

import React, { useState } from 'react';
import axios from 'axios';

function PostForm() {
  const [title, setTitle] = useState('');
  const [content, setContent] = useState('');

  const handleSubmit = (e) => {
    e.preventDefault();
    axios.post('/api/posts', { title, content })
      .then(() => {
        alert('게시글이 작성되었습니다.');
        setTitle('');
        setContent('');
      })
      .catch((error) => console.error('Error creating post:', error));
  };

  return (
    <form onSubmit={handleSubmit}>
      <h2>새 게시글 작성</h2>
      <div>
        <label>제목</label>
        <input
          type="text"
          value={title}
          onChange={(e) => setTitle(e.target.value)}
        />
      </div>
      <div>
        <label>내용</label>
        <textarea
          value={content}
          onChange={(e) => setContent(e.target.value)}
        ></textarea>
      </div>
      <button type="submit">작성</button>
    </form>
  );
}

export default PostForm;

=> 게시글을 작성하는 컴포넌트 

 

 

2-3. CRUD 기능 설명

Create : 사용자가 새 게시글을 작성하고 이것을 서버로 전송
Read : 모든 게시글을 목록으로 보여주고 상세 게시글을 조회
Update : 게시글의 내용을 수정하고 서버에 반영
Delete : 특정 게시글을 삭제하고 이를 데이터베이스에서 삭제

 

 

2-4. 게시글 상세 - 게시글 선택해서 확인

> src\component\PostContent.js

PostContent.js

import React, { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
import axios from 'axios';

const PostContent = () => {
  const { id } = useParams();
  const [post, setPost] = useState(null);

  useEffect(() => {
    axios.get(`http://localhost:3000/api/posts/${id}`)
      .then(response => setPost(response.data))
      .catch(error => console.error('게시글 불러오기 오류:', error));
  }, [id]);

  if (!post) return <div>로딩 중...</div>;

  return (
    <div>
      <h2>{post.title}</h2>
      <p>{post.content}</p>
      <p><strong>작성일:</strong> {new Date(post.created_at).toLocaleString()}</p>
    </div>
  );
};

export default PostContent;

 

 

2-5. 게시글 API 결과를 보여주는 페이지 추가

>src\component\Posts.js, Router.js

 

* 에러 발생 *

원인 : PostList.js와 PostForm.js도 그렇고 axios.get/post('api/posts') 코드를 가지고 있는데 

api/posts에 대한 구현이 없었다 

404 Not found, Axios error

Get http://localhost:3000/api/posts 404 (Not Found)
Error fetching posts:
▶AxiosError {message: 'Request failed with status code 404'}

 

* 해결 방법 *

Posts.js를 생성해주고 Router.js에서 api/posts에 매핑

1) Posts.js 

/api/posts에 대한 직접적인 요청을 처리하는 컴포넌트로, 주로 관리자나 API 데이터 검증용으로 사용할 수 있다

// src/components/Posts.js
import React, { useState, useEffect } from 'react';
import axios from 'axios';

function Posts() {
  const [posts, setPosts] = useState([]);
  const [error, setError] = useState(null);

  useEffect(() => {
    axios.get('/api/posts')
      .then(response => setPosts(response.data))
      .catch(err => setError('게시글을 가져오는데 실패했습니다.'));
  }, []);

  return (
    <div>
      <h1>게시글 목록</h1>
      {error && <p>{error}</p>}
      <ul>
        {posts.map(post => (
          <li key={post.id}>
            <h3>{post.title}</h3>
            <p>{post.content}</p>
          </li>
        ))}
      </ul>
    </div>
  );
}

export default Posts;

 

 

2) Router.js 수정 필요 (밑 4-2에서 생성 및 작성 자세히 설명)

//Router.js

import Posts from '../components/Posts';

//<Routes></Routes> 태그 내 추가
<Route path="api/posts" element={<Posts />} /> {/* API 결과를 보여주는 페이지 */}

 

 


 

3. 클라이언트와 서버 통합

React의 프록시 설정을 이용해 프론트엔드와 백엔드 간 통신을 설정한다 

package.json에 프록시 설정을 추가해 개발 중에는 동일한 도메인에서 API 요청을 처리할 수 있도록 한다

 

> package.json 

//package.json
"proxy": "http://localhost:5001"

 

 

4. 웹 애플리케이션 실행을 위한 기타 세팅

4-1. 게시판 웹 애플리케이션 세팅

1) PostList.js 리액트 컴포넌트를 App.js로 가져오기

> App.js 수정

App.js

 

import './App.css';

import PostList from './components/PostLists';

function App() {
  return <PostList />;
}

export default App;

 

2) 웹 애플리케이션 실행

개발 서버를 실행해본다

npm run start

 

App.js 수정으로 변경된 화면

App.js 아직 글이 없어 비어있는 화면

 

☞ App.js에 PostList.js를 불러왔다

 

 


4-2. 페이지로 이동 구현하기

> react-router-dom으로 PostForm에 직접적으로 접근할 수 있는 방법 구현

현재  PostForm.js 화면은 아래와 같다

위에 작성한 PostForm.js코드는 이런 화면입니다

 

1) 먼저 react-router-dom을 설치해준다

<react-router-dom을 npm으로 설치하기>

https://tiny-immj.tistory.com/91

 

[REACT] Failed to compile. Module not found : Can't resolve 'react-router-dom'

* 이슈 상황 *리액트에서 버튼을 클릭하면 페이지가 이동하도록 만들어주는데 compile 에러가 발생했다(useNavigate를 사용해 이벤트를 설정 중) ※ 참고 : useNavigate란 ? 리액트 라우터 v6에서 새롭게

tiny-immj.tistory.com

package.json에서 설치된 react-router-dom을 확인해볼 수 있다

 

 

2) Router 사용

> Router.js 생성, App.js 수정

> share 폴더를 생성하여 Router.js를 만들어준다

<Routes> 태그 안에 <Route> 태그 작성 후 각 페이지 컴포넌트를 연결해준다 

<Routes>
	<Route path="/" element={<PostList />} />
	<Route path="postform" element={<PostForm />} />
    <Route path="post/:id" element={<PostContent />} />
    <Route path="api/posts" element={<Posts />} />
</Routes>

 

Router.js

전체 코드

//Router.js
import React from 'react';
// 1. react-router-dom을 사용하기 위해서 BrowserRouter, Route, Routes를 import한다
import { BrowserRouter, Route, Routes } from 'react-router-dom';
import PostList from '../components/PostLists';
import PostForm from '../components/PostForm';
import PostContent from '../components/PostContent';
import Posts from '../components/Posts';  //api/posts

// 2. Router라는 함수를 만들고 아래와 같이 작성
//BrowserRouter를 Router로 감싸는 이유는,
//SPA의 장점인 브라우저가 깜빡이지 않고 다른 페이지로 이동할 수 있게 만들기 위해서!
const Router = () => {
    return (
        <BrowserRouter>
            <Routes>
                <Route path="/" element={<PostList />} />
                <Route path="postform" element={<PostForm />} />
                <Route path="post/:id" element={<PostContent />} />
                <Route path="api/posts" element={<Posts />} /> {/* API 결과를 보여주는 페이지 */}
            </Routes>
        </BrowserRouter>
    );
};

export default Router;

 

 

그 후 App.js에 Router.js import 해준다

App.js 수정

 

//App.js
import './App.css';
import Router from './share/Router';

function App() {
  return <Router />;
}

export default App;

 

 

3) 결과

Router 설정

☞Router 설정으로 postform과 다른 페이지에 접근할 수 있게 되었다


 

5. 글 작성 확인(DB와 사이트) 및 코드 수정

5-1. MySQL로 테이블 데이터 넣어주기

db에 posts 테이블을 만들어줄 때 id, title, content, timestamp로 생성해주었다 

CREATE TABLE posts (
    id INT AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(255),
    content TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

 

Insert 쿼리 문법은 

INSERT INTO 테이블 이름 (필드(컬럼)명1, 필드(컬럼)명2, ...) VALUES (추가할 값1, 추가할 값2, ...);

 

1) id INT AUTO_INCREMENT, TIMESTAMP 제외

id는 자동으로 증가되기 때문에 INSERT 값을 입력하지 않아도 된다

TIMESTAMP도 자동으로 현재 시간이 들어간다

 

2) INSERT 사용 쿼리

INSERT INTO posts(title, content) VALUES ("MySQL테스트", "DB연결테스트입니다.");

 

3) 결과 

☞ DB로 확인 가능

INSERT 후 SELECT

☞ 매핑해준 페이지로 확인해보기

1) Express 서버 실행

터미널을 열고 server.js 파일이 있는 디렉토리로 이동

cd server  //server.js가 있는 server 디렉토리로 이동

 

아래 명령어를 실행해 서버를 시작한다

node server.js

 

이미 서버가 실행중이라면 강제로 종료하고 재시작해보기 

터미널에서 Ctrl+C를 눌러 Express 서버를 종료

MySQL 연결 성공

 

2) 서버와 클라이언트 연결이 잘 되는지 확인

http://localhost:5001/api/posts를 직접 입력해 게시글 목록을 확인해볼 수 있다

얏호! DB도 글 작성도 완료

 

 

 

5-2. 웹페이지에서 글 직접 작성해보기

postform에 들어가 글을 작성해본다

글 작성 테스트
글 작성 완료

※ 현재 코드로는 작성된 글이 게시글 목록에 저장되지 않는다 / 목록에 안 나온다는 뜻

 

 

5-3. 작성한 글이 게시글 목록에 반영되지 않는 문제 

▷ PostForm.js에서 글을 작성한 후 PostList.js에 작성된 게시글이 반영되지 않는 문제를 해결하려면, 

게시글 작성 후 PostList.js에서 게시글 목록을 다시 가져오거나 상태를 갱신해주면 된다 

 

* 구현 방법 *

1. PostForm.js에서 게시글을 작성한 후, 서버에 POST 요청을 보내고 성공하면  PostList.js를 갱신

2. PostList.js에서 새로운 게시글이 추가되었을 때, 기존의 게시글 목록을 업데이트하도록 수행

 

* 해결 방법 *

1. PostForm.js에서 글을 작성, 저장한 후 PostList.js의 게시글 목록을 갱신하는 방법 진행

▷PostList에서 상태를 직접 변경할 수 있도록 setPosts 함수를 부모 컴포넌트로부터 전달받아야 함

> PostForm.js 수정

소스코드 수정

// src/components/PostForm.js
import React, { useState } from 'react';
import axios from 'axios';
// 게시글을 작성한 후 게시글 목록을 갱신할 수 있도록 Navigate를 사용해 목록 페이지로 이동
import { useNavigate } from 'react-router-dom'; 

function PostForm({ setPosts }) { //setPosts를 props로 받기
  const [title, setTitle] = useState('');
  const [content, setContent] = useState('');
  const navigate = useNavigate();  // 글 작성 후 이동할 수 있도록 navigate 사용

  const handleSubmit = (e) => {
    e.preventDefault();

    // API에 POST 요청을 보내서 글 작성
    // axios.post('/api/posts', { title, content })
    axios.get('http://localhost:5001/api/posts', { title, content })
      .then((response) => {
        alert('게시글이 작성되었습니다.');
        setTitle('');
        setContent('');

        // 작성한 글을 목록에 추가
        axios.get('http://localhost:5001/api/posts')
          .then((response) => setPosts(response.data))  // 작성 후 PostList 업데이트
          .catch((error) => console.error('Error fetching posts:', error));

        // 글 작성 후 PostList 페이지로 이동 >>> 
        navigate('/');
         
      })
      .catch((error) => console.error('Error creating post:', error));
  };

  return (
    <form onSubmit={handleSubmit}>
      <h2>새 게시글 작성</h2>
      <div>
        <label>제목</label>
        <input
          type="text"
          value={title}
          onChange={(e) => setTitle(e.target.value)}
        />
      </div>
      <div>
        <label>내용</label>
        <textarea
          value={content}
          onChange={(e) => setContent(e.target.value)}
        ></textarea>
      </div>
      <button type="submit">작성</button>
    </form>
  );
}

export default PostForm;

☞ 게시글을 제출한 후, 게시글 목록을 갱신할 수 있도록 setPosts 함수나 navigate를 사용해 목록 페이지로 이동하도록 만들어줌

 

2. PostList.js에서 setPosts 함수를 전달받기

▷PostForm.js가 글을 작성한 후 setPosts를 통해 게시글 목록을 갱신하도록 하려면 

PostList.js에서 PostForm 컴포넌트를 렌더링할 때 setPosts를 props로 전달해야 함

> PostList.js 수정

PostList.js 코드 추가

// src/components/PostList.js
import React, { useState, useEffect } from 'react';
import axios from 'axios';
// import {useNavigate} from 'react-router-dom';
import { Link } from 'react-router-dom';  // 링크 추가
import { useNavigate } from 'react-router-dom'; // 추가: navigate 사용

function PostList() {
  // 게시물 데이터를 저장할 상태 변수
   const [posts, setPosts] = useState([]);

  useEffect(() => {
    // 게시글 목록 가져오기
    axios.get('http://localhost:5001/api/posts')
      .then((response) => setPosts(response.data))
      .catch((error) => console.error('Error fetching posts:', error));
  }, []);  // 처음 한 번만 실행

  return (
    <div>
      <h1>게시판</h1>
      <div>
        {/* 글 작성 페이지로 이동 */}
        <Link to="/postform">
          <button>글 작성</button>
        </Link>
      </div>
      <ul>
        {posts.map(post => (
          <li key={post.id}>
            <h3>{post.title}</h3>
            <p>{post.content}</p>
            {/* 추가 */}
            <Link to={`/post/${post.id}`}>상세보기</Link>
          </li>
        )) }
      </ul>
    </div>
  );
}

export default PostList;

 

PostList.js에서는 setPosts를 정의하고 이를 PostForm.js에 전달해야 한다

PostForm에서는 setPosts를 사용해 게시글 목록을 갱신함

 

3. Router.js에서 setPosts 전달

▷ Router.js에서는 PostForm 컴포넌트가 setPosts를 전달할 수 있도록

PostList에서 setPosts를 PostForm으로 전달해야 함(props)

> Router.js

Router.js 코드 수정

 

Router.js 전체 코드 

import React, { useState, useEffect } from 'react';
// 1. react-router-dom을 사용하기 위해서 BrowserRouter, Route, Routes를 import한다
import { BrowserRouter, Route, Routes } from 'react-router-dom';
import PostList from '../components/PostLists';
import PostForm from '../components/PostForm';
import PostContent from '../components/PostContent';
import Posts from '../components/Posts';  //api/posts
import axios from 'axios';

// 2. Router라는 함수를 만들고 아래와 같이 작성
//BrowserRouter를 Router로 감싸는 이유는,
//SPA의 장점인 브라우저가 깜빡이지 않고 다른 페이지로 이동할 수 있게 만들기 위해서!
const Router = () => {
    const [posts, setPosts] = useState([]);

    // 게시글 목록을 초기화하는 useEffect
    useEffect(() => {
    axios.get('http://localhost:5001/api/posts')
      .then((response) => setPosts(response.data))
      .catch((error) => console.error('Error fetching posts:', error));
    }, []); // 한 번만 실행

    return (
        <BrowserRouter>
            <Routes>
                <Route path="/" element={<PostList />} />
                <Route path="/" element={<PostList posts={posts} setPosts={setPosts} />} />  {/* posts와 setPosts를 전달 */}
                {/* <Route path="postform" element={<PostForm />} /> */}
                <Route path="/postform" element={<PostForm setPosts={setPosts} />} />  {/* setPosts 전달 */}                
                <Route path="post/:id" element={<PostContent />} />
                <Route path="api/posts" element={<Posts />} /> {/* API 결과를 보여주는 페이지 */}
            </Routes>
        </BrowserRouter>
    );
};

export default Router;

 

 

4. 결과

1) 글 작성 : PostForm에서 글을 작성하고 제출

2) 목록 갱신 : PostForm 제출 후, PostList의 게시글 목록이 갱신되어 새로운 게시글이 보임

3) 자동 리디렉션 :  글 작성 후, PostList 페이지로 자동으로 리디렉션되기 

postform에서 테스트로 새 글 작성
설정한 alert 완료
PostList에 새 글 등록 완료
게시글 상세(PageContent)도 정상 동작!

 

☞ 게시글 작성 및 PostList 리디렉션 완료

 

 

* 깃허브에 전체 소스 업로드 완료

https://github.com/minjeong-j/REACT-NODE-APP

 

GitHub - minjeong-j/REACT-NODE-APP: React와 Nodejs 웹 애플리케이션

React와 Nodejs 웹 애플리케이션. Contribute to minjeong-j/REACT-NODE-APP development by creating an account on GitHub.

github.com

 

 

다음 시간에는 이어서 게시판을 좀 더 편하게 사용할 수 있도록 수정해보려 한다

반응형