diff --git a/src/App.js b/src/App.js
index f0a576f..66530ae 100644
--- a/src/App.js
+++ b/src/App.js
@@ -5,7 +5,9 @@ import Footer from './components/Footer';
import Home from './pages/Home';
import About from './pages/About';
import PostList from './pages/PostList';
+import PostDetail from './pages/PostDetail';
import PostCreate from './pages/PostCreate';
+import PostEdit from './pages/PostEdit';
import PostCategory from './pages/PostCategory';
import Login from './pages/Login';
import { AuthProvider } from './context/AuthContext';
@@ -21,7 +23,9 @@ function App() {
} />
} />
} />
+ } />
} />
+ } />
} />
} />
diff --git a/src/pages/PostDetail.js b/src/pages/PostDetail.js
new file mode 100644
index 0000000..d6fee8b
--- /dev/null
+++ b/src/pages/PostDetail.js
@@ -0,0 +1,66 @@
+import React, { useEffect, useState } from 'react';
+import { useParams, useNavigate } from 'react-router-dom';
+import blogApi from '../api/blogApi';
+import { useAuth } from '../context/AuthContext';
+
+const PostDetail = () => {
+ const { id } = useParams();
+ const navigate = useNavigate();
+ const { isLoggedIn } = useAuth();
+ const [post, setPost] = useState(null);
+
+ useEffect(() => {
+ blogApi.get(`/api/blog/posts/${id}/`)
+ .then(res => setPost(res.data))
+ .catch(err => console.error('게시글 조회 실패:', err));
+ }, [id]);
+
+ const handleDelete = async () => {
+ if (!window.confirm('정말 삭제하시겠습니까?')) return;
+
+ try {
+ await blogApi.delete(`/api/blog/posts/${id}/`);
+ alert('게시글이 삭제되었습니다.');
+ navigate('/posts');
+ } catch (err) {
+ console.error(err);
+ alert('삭제 중 오류가 발생했습니다.');
+ }
+ };
+
+ if (!post) return
Loading...
;
+
+ return (
+
+
+
{post.title}
+ {isLoggedIn && (
+
+ navigate(`/posts/${id}/edit`)}
+ className="bg-yellow-500 text-white px-4 py-2 rounded hover:bg-yellow-600"
+ >
+ 수정
+
+
+ 삭제
+
+
+ )}
+
+
+
작성자: {post.author_name}
+
+ 작성일: {new Date(post.created_at).toLocaleString()}
+
+
+ {post.content}
+
+
+ );
+};
+
+export default PostDetail;
diff --git a/src/pages/PostEdit.js b/src/pages/PostEdit.js
new file mode 100644
index 0000000..8b0a821
--- /dev/null
+++ b/src/pages/PostEdit.js
@@ -0,0 +1,70 @@
+import React, { useEffect, useState } from 'react';
+import { useParams, useNavigate } from 'react-router-dom';
+import blogApi from '../api/blogApi';
+import { useAuth } from '../context/AuthContext';
+
+const PostEdit = () => {
+ const { id } = useParams();
+ const navigate = useNavigate();
+ const { isLoggedIn } = useAuth();
+ const [title, setTitle] = useState('');
+ const [content, setContent] = useState('');
+
+ useEffect(() => {
+ blogApi.get(`/api/blog/posts/${id}/`)
+ .then(res => {
+ setTitle(res.data.title);
+ setContent(res.data.content);
+ })
+ .catch(err => {
+ console.error('게시글 불러오기 실패:', err);
+ alert('게시글을 불러오지 못했습니다.');
+ });
+ }, [id]);
+
+ const handleSubmit = async () => {
+ try {
+ await blogApi.put(`/api/blog/posts/${id}/`, { title, content });
+ alert('게시글이 수정되었습니다.');
+ navigate(`/posts/${id}`);
+ } catch (err) {
+ console.error(err);
+ alert('수정 실패: ' + (err.response?.data?.detail || '서버 오류'));
+ }
+ };
+
+ if (!isLoggedIn) return 로그인이 필요합니다.
;
+
+ return (
+
+
게시글 수정
+
setTitle(e.target.value)}
+ />
+
+
+
+ 저장
+
+ navigate(-1)}
+ className="bg-gray-300 text-gray-800 px-6 py-2 rounded hover:bg-gray-400"
+ >
+ 취소
+
+
+
+ );
+};
+
+export default PostEdit;
diff --git a/src/pages/PostList.js b/src/pages/PostList.js
index 88b37c8..803a4ae 100644
--- a/src/pages/PostList.js
+++ b/src/pages/PostList.js
@@ -31,7 +31,11 @@ const PostList = () => {