Todo
구현할 기능 : CRUD (게시글 작성, 조회, 수정, 삭제)
<RESTful API 이해하기>
https://tiny-immj.tistory.com/88
RESTful API 간단한 API 만들기, Postman 사용법
~ 포스팅 진행 순서 ~REST, REST APIRESTful설계원칙API 구현하기=> REST, REST API, RESTful의 기본 개념과 간단한 api 만드는 방법 진행=> RESTful API는 데이터를 표준화된 방식으로 주고 받을 수 있게 해주고,
tiny-immj.tistory.com
프로젝트 정보 및 CR(게시글 작성, 조회)
<1. React와 Node.js를 사용한 게시판 웹 애플리케이션 만들기 - 게시판 만들기, 게시글 목록 자동 갱신, 글 추가, Router 설정, CORS설정, MySQL>
https://tiny-immj.tistory.com/92
1. React와 Node.js를 사용한 게시판 웹 애플리케이션 만들기 - 게시판 만들기(crud), 게시글 목록 자동
Todo구현할 기능 : CRUD(게시글 작성, 조회, 수정, 삭제) RESTful API 이해하기https://tiny-immj.tistory.com/88 REST, REST API, RESTful의 기본 개념과 간단한 api 만드는 방법 진행=> RESTful API는 데이터를 표준화된 방
tiny-immj.tistory.com
프로젝트 정보
프론트엔드 : React
백엔드 : Node.js
<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
1. 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
1. Backend 백엔드
1-1. 게시판 API 구현
1) 게시판 API
> server.js
지난 포스팅때 설정한 게시판 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}`);
});
2) API와 엔드포인트의 개념 설명과 차이점
API(Application Programming Interface) : 서로 다른 소프트웨어/시스템이 상호작용할 수 있도록 하는 프로토콜의 모음
Endpoint : API가 서버에서 리소스에 접근할 수 있도록 가능하게 하는 URL, API가 외부와 데이터를 주고받기 위해 지정된 URL
▷API는 특정 기능을 제공하고 개발자가 서버나 서비스에 접근해 필요한 작업을 수행할 수 있도록 도와준다
예를 들어 "게시물을 생성하는 API", "사용자 정보를 가져오는 API"가 있다
→ 기능의 개념
▷ Endpoint는 API가 실제로 실행되는 주소로, 예를 들어 "게시물을 생성하는 API"의 엔드포인트가 /posts/create라면 이 주소를 통해 클라이언트가 서버에 요청을 보내게 된다
1-2. 게시글 수정 API
수정 API 엔드포인트는 이렇게 만들었다
//server.js
// 게시글 수정 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');
});
});
1-3. 게시글 삭제 API
삭제 엔드포인트는 이렇게 만들어 놓았다
//server.js
// 게시글 삭제 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');
});
});
2. Frontend 프론트엔드
이제 만들어놓은 API를 호출하여 수정과 삭제 기능을 완성해볼 것이다
▷ React 컴포넌트에서 API를 호출하는 방법 진행 [ fetch 또는 axios 사용 ]
2-1. 게시글 수정 페이지 구현
수정 API 호출 함수(PUT 요청)
const editPost = async (postId, updatedData) => {
try {
const response = await fetch('/api/posts/${id}', {
method: 'PUT',
headers: {
'Conent-Type': 'application/json',
},
body: JSON.stringify(updatedData),
});
if(response.ok) {
alert('Post updated successfully');
//업데이트 후 게시글을 다시 가져오거나 UI를 업데이트한다
} else {
alert('Failed to update post');
}
} catch(error) {
console.error('Error updating post:', error);
}
};
updatedData는 수정된 title과 content 객체로,
예를 들어 {title: 'New Title', content: 'Updated content'} 형태가 된다
2-2. 게시글 삭제 구현
삭제 API 호출 함수(DELETE 요청)
const deletePost = async(postId) => {
try {
const response = await fetch('/api/posts/${id}', {
method: 'DELETE',
});
if(response.ok) {
alert('Post deleted successfully');
//삭제 후 게시글을 다시 가져오거나 UI를 업데이트한다
} else {
alert('Failed to delete post');
}
} catch (error) {
console.error('Error deleting post:', error);
}
};
▷PostContent.js에 추가해줘도 되고 별도의 API 관리 파일을 만들어 작성해도 된다
2-3. 수정과 삭제 API 관리
여러 컴포넌트에서 editPost나 deletePost를 사용할 수 있으므로 api.js를 새로 만들어 관리하려 한다
> api.js 생성
// src/share/api.js
export const editPost - async (id, updatedData) => {
try{
const response = await fetch('/api/posts/${id}'), {
method: 'PUT',
headers: { 'Content-Type' : 'application/json' },
body: JSON.stringify(updatedData),
});
if (response.ok) {
return { success: true };
} else {
throw new Error('Failed to update post');
}
} catch (error) {
console.error('Error updating post:', error);
return { success: false, error };
}
};
export const deletePost = async (id) => {
try {
const response = await fetch('/api/posts/${id}', {method: 'DELETE'});
if (response.ok) {
return {success:true };
} else {
throw new Erro('Failed to delete post');
}
} catch (error) {
console.error('Error deleting post:', error);
return { success: false, error };
}
};
2-4. 수정, 삭제 버튼에 이벤트 연결하기
> PostContent.js
게시글을 표시하는 컴포넌트에 수정과 삭제 버튼을 추가하고 해당 버튼에 API 호출 함수를 연결해준다
삭제는 PostContent.js에서 바로 이벤트 처리해주고
수정은 PostEdit.js로 이동해 수정할 수 있도록 만들어주려고 한다
내가 생각한 수정 프로세스 :
① PostContent.js에서 수정 버튼을 누르면
② PostEdit.js 페이지로 이동해 제목과 내용을 수정할 수 있게 해준다
③ 수정이 완료된 후에는 PostList.js 페이지로 이동해 게시글 목록을 보여준다
2-5. API 호출함수와 버튼을 추가
> PostContent.js 수정, PostEdit.js 생성
☞ api.js의 editPost, deletePost 불러오기
import { editPost, deletePost } from '../share/api'; //api.js에서 함수 불러오기
* 코드 수정 체크리스트 *
☞ PostContent.js
▷기존에 axios.put과 axios.delete로 처리하던 handleEdit 함수와 handleDelete 함수를
editPost와 deletePost 함수로 호출하도록 변경
▷editPost와 deletePost 함수는 이미 /api/posts/${id}로 요청을 보내므로 PostContent.js에서는 다시 해당 URL을 지정할 필요가 없으므로 제거
① PostContent.js에서 수정 버튼 클릭 시 PostEdit.js로 이동하는 부분 처리
//PostContent.js
import React, { useEffect, useState } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import { deletePost } from '../share/api'; //api.js에서 함수 불러오기
import axios from 'axios';
const PostContent = () => {
const { id } = useParams();
const navigate = useNavigate(); //navigate 변수 선언
const [post, setPost] = useState(null);
useEffect(() => {
axios.get('http://localhost:5001/api/posts/${id}')
.then(response => setPost(response.data))
.catch(error => console.error('게시글 불러오기 오류:', error));
}, [id]);
if(!post) return <div> 로딩 중...</div>;
//수정함수
const handleEdit = () => {
//수정 페이지로 이동하는 함수
navigate('/edit/${함수}');
};
// 삭제 함수
/*
// api.js 생성으로 인한 수정
const handleDelete = () => {
axios.delete('http://localhost:5001/api/posts/${id}')
.then(() => {
alert('Post deleted successfully');
navigate('/') //삭제 후 메인페이지로 이동
})
.catch(error => console.error('게시글 삭제 오류:', error));
}; */
const handleDelete = async () => {
const result = await deletePost(id);
if(result.success) {
alert('Post deleted successfully');
navigate('/'); //삭제 후 메인페이지로 이동
} else {
alert(result.error || 'Failed to delete post');
}
};
return (
<div>
<h2>{post.title}</h2>
<p>{post.content}</p>
<p><strong>작성일</strong> {new Date(post.created_at).toLocaleString()}</p>
{/* 버튼 추가 */}
<button onClick={handleEdit}>Edit</button>
<button onClick={handleDelete}>Delete</button>
</div>
);
};
export default PostContent;
② PostEdit.js에서 게시글을 수정가능하도록 구현
> PostEdit.js 생성
import React, { useEffect, useState } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import { editPost } from '../share/api'; //api.js에서 editPost 함수 불러오기
import axios from 'axios';
const PostEdit = () => {
const { id } = useParams(); //URL에서 post ID를 가져옴
const navigate = useNavigate(); //navigate 사용
const [title, setTitle] = useState('');
const [content, setContent] = useState('');
useEffect(() => {
// 게시글 데이터를 가져와서 수정할 수 있도록 제목과 내용 상태에 저장
axios.get('http://localhost:5001/api/posts/${id}')
.then(response => {
setTitle(response.data.title);
setContent(response.data.content);
})
.catch(error => console.error('게시글 불러오기 오류:', error));
},[id]);
const handleSave = async () => {
const updatedData = { title, content };
const result = await editPost(id, updatedData);
if (result.success){
alert('Post updated successfully');
navigate('/'); //수정 후 목록 페이지로 이동
} else {
alert(result.error || 'Failed to update post');
}
};
return (
<div>
<h2>Edit Post</h2>
<div>
<label>Title</label>
<input
type="text"
value={title}
onChange={(e) => setTitle(e.target.value)} //제목 입력값 상태에 반영
/>
</div>
<div>
<label>Content</label>
<textarea
value={content}
onChange={(e) => setContent(e.target.value)} //내용 입력값 상태에 반영
/>
</div>
<button onClick={handleSave}>Save</button>
<button onClick={() => navigate('/')}>Cancel</button>
</div>
);
};
export default PostEdit;
③ Router 설정
> Router.js 파일 수정
PostEdit.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 PostEdit from '../components/PostEdit';
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 />} />
{/* posts와 setPosts를 전달 */}
<Route path=:"/" element={<PostList posts={posts} setPosts={setPosts} />} />
{/* setPosts 전달 */}
<Route path="postForm" element={<PostForm setPosts={setPosts} />} />
<Route path="/post/:id" element={<PostContent />} />
{/* 게시글 수정 */}
<Route path="/edit/:id" element={<PostEdit />} />
{/* API 결과를 보여주는 페이지 */}
<Route path="api/posts" element={<Posts />} />
</Routes>
</BrowserRouter>
);
};
export default Router;
④ 수정 후 PostList.js 목록 갱신
이미 구현되어 있음
navigate('/')
⑤ Api.js 코드 참고
3. UI 업데이트
수정이나 삭제 작업이 완료된 후 게시글 목록을 다시 불러오거나 로컬 상태를 업데이트하여 UI가 즉시 반영되도록 한다
아래 두 가지 방법 중 선택 가능
1) 상태 업데이트 : 예를 들어 삭제 후에는 setPosts 등의 상태 업데이트 함수를 사용해 현재 게시글 목록에서 삭제된 게시글을 제거한다
2) 데이터 재요청 : 전체 게시글을 다시 불러오는 API를 호출해 최신 목록을 보여줄 수 있다
4. 실행 및 테스트
4-1. 서버 실행
Express 서버 실행 → MySQL 연결
cd server
node server.js
개발서버 실행
npm run start
4-2. 테스트
→ 글 작성 후 수정, 삭제까지 테스트
① 글 작성
② 게시글 목록 확인
게시글 목록 자동 갱신
③ 글 수정
title과 content 수정 후 Save 버튼 클릭
→ Post updated successfully 창이 뜸
④ 수정 확인
⑤ 글 삭제
삭제하려는 글을 누르고 Delete 버튼 클릭
Delete 버튼을 클릭하면 'Post deleted successfully' 창이 뜬다
'수정하기'라는 제목의 글도 똑같이 삭제 진행해준다
⑥ 삭제 확인
삭제된 후에는 자동으로 게시글 목록 이동
글 2개가 삭제된 것을 확인해볼 수 있다
게시판 CRUD 완료!

'프로젝트 기록 > React, Node.js를 이용한 게시판 만들기' 카테고리의 다른 글
4. 게시판 validation 만들기 - React와 Node.js 게시판 (0) | 2024.11.21 |
---|---|
3. 게시판 조회수 구현과 React bootstrap 사용한 껍데기 포장해보기 - React와 Node.js를 사용한 게시판 만들기 (1) | 2024.11.19 |
1. React와 Node.js를 사용한 게시판 웹 애플리케이션 만들기 - 게시판 만들기, 게시글 목록 자동 갱신, 글 추가, Router 설정, CORS 설정, MySQL (10) | 2024.11.06 |
RESTful API 간단한 API 만들기, Postman 사용법 (1) | 2024.10.31 |
React Context API로 전역 상태 관리 구현 (0) | 2024.10.30 |