내 MERN 스택 포트폴리오를 위한 동적 Admin Panel 구축 방법
Source: Dev.to
포트폴리오를 위한 관리자 패널을 구축해야 하는 이유?
처음에는 정적 콘텐츠만 표시하는 간단한 React 포트폴리오를 만들었습니다. 하지만 곧 모든 업데이트마다 코드 수정과 재배포가 필요했으며, 이는 시간도 많이 걸리고 오류가 발생하기 쉬웠습니다.
관리자 대시보드를 구축함으로써 다음을 달성했습니다:
- 실시간 콘텐츠 업데이트: UI를 통해 프로젝트, 스킬, 기타 프로필 데이터를 추가, 수정, 삭제할 수 있습니다.
- 보안 접근: JWT 인증을 사용해 나만 로그인하여 콘텐츠를 관리할 수 있습니다.
- 확장성: 프론트엔드를 수정하지 않고도 새로운 섹션이나 데이터 유형을 쉽게 확장할 수 있습니다.
- 더 나은 조직화: 하드코딩된 파일 대신 데이터베이스에 포트폴리오 콘텐츠를 저장합니다.
기술 스택 개요
| Layer | Technology |
|---|---|
| 프론트엔드 | React (functional components & hooks) |
| 백엔드 | Node.js + Express (REST APIs) |
| 데이터베이스 | MongoDB + Mongoose |
| 인증 | JWT (JSON Web Tokens) |
| 파일 저장 | Cloudinary (image & resume uploads) |
| 스타일링 | CSS Modules + UI libraries |
관리자 패널의 주요 기능
- 프로필 섹션: 바이오, 프로필 사진, 연락처 정보를 업데이트합니다.
- 스킬: 프로그래밍 스킬을 동적으로 추가, 업데이트 또는 제거합니다.
- 프로젝트: 프로젝트에 대한 CRUD 작업(제목, 설명, 이미지, 링크).
- 이력서: 이력서 파일을 업로드하고 업데이트합니다.
- 인증: 이메일 및 비밀번호를 사용한 보안 로그인, JWT를 이용한 보호된 라우트.
작동 방식 — 아키텍처 분석
1. 백엔드 API 설계
모든 포트폴리오 데이터를 위한 CRUD 작업을 처리하는 RESTful API를 만들었습니다.
예시 라우트
GET /api/projects // fetch all projects
POST /api/projects // add a new project
PUT /api/projects/:id // update project by ID
DELETE /api/projects/:id // delete project by IDAPI는 요청을 검증하고 Mongoose 모델을 사용해 MongoDB 컬렉션과 상호 작용합니다. 인증 미들웨어가 민감한 엔드포인트를 보호합니다.
2. JWT 인증
관리자 패널을 보호하기 위해 다음과 같은 로그인 시스템을 구축했습니다:
- bcrypt를 사용한 비밀번호 해싱.
- 로그인 시 JWT 토큰 생성.
- 프론트엔드와 백엔드 모두에서 유효한 토큰이 필요한 보호된 라우트.
3. React 관리자 대시보드 UI
API 호출을 위해 React 훅과 axios를 사용하여 다음과 같은 컴포넌트를 만들었습니다:
- Login Page: 인증하고 JWT를
localStorage에 저장합니다. - Dashboard: 포트폴리오 내용 개요.
- Forms: 기술 및 프로젝트 추가/수정을 위한 제어된 폼.
- File Uploads: 이미지와 이력서 업로드를 위해 Cloudinary API와 통합했습니다.
조건부 렌더링과 로딩 상태가 부드러운 사용자 경험을 제공합니다.
코드 스니펫 — 예시: 관리자 패널에서 프로젝트 가져오기
import React, { useEffect, useState } from "react";
import axios from "axios";
const AdminProjects = () => {
const [projects, setProjects] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchProjects = async () => {
try {
const token = localStorage.getItem("authToken");
const response = await axios.get("/api/projects", {
headers: { Authorization: `Bearer ${token}` },
});
setProjects(response.data);
} catch (error) {
console.error("Error fetching projects:", error);
} finally {
setLoading(false);
}
};
fetchProjects();
}, []);
if (loading) return <p>Loading projects...</p>;
return (
<div>
<h2>Manage Projects</h2>
{projects.length === 0 ? (
<p>No projects found.</p>
) : (
projects.map((project) => (
<div key={project._id}>
<h3>{project.title}</h3>
<p>{project.description}</p>
{/* Buttons for Edit/Delete can go here */}
</div>
))
)}
</div>
);
};
export default AdminProjects;도전 과제 및 교훈
- 파일 업로드 처리: Cloudinary의 서명된 URL을 통합하고 업로드 상태를 관리하는 데 추가적인 주의가 필요했습니다.
- 상태 관리: 특히 실시간 CRUD 업데이트 후에 백엔드 데이터와 관리자 UI를 동기화하는 것이 React 상태와 효과를 신중하게 사용해야 했습니다.
- 인증 흐름: 라우트를 보호하고 JWT 토큰을 관리하는 것이 무단 접근을 방지하는 데 중요했습니다.
- UX 고려사항: 간단하고 효과적인 폼과 명확한 피드백 메시지는 관리자 사용성을 크게 향상시켰습니다.
최종 생각
동적인 관리자 패널을 구축하면서 내 포트폴리오를 정적인 웹페이지에서 재배포 없이 제어할 수 있는 강력한 콘텐츠 관리 시스템으로 변모시켰습니다. 이를 통해 풀스택 개발, API 설계, 보안 인증, 파일 관리 등 현대 웹 개발자에게 필수적인 기술을 직접 체험할 수 있었습니다.
포트폴리오를 구축하거나 개선하려는 계획이 있다면, 관리자 대시보드를 추가하는 것을 강력히 추천합니다. 이는 기술 역량을 보여줄 뿐만 아니라 장기적으로 시간과 노력을 크게 절감해 줍니다.
포트폴리오를 직접 확인해 보세요:
[http://your-portfolio-link.com] (실제 URL로 교체)
https://adithyan-phi.vercel.app
질문이 있거나 경험을 공유하고 싶으신가요? 아래에 댓글을 남겨 주세요!
코딩 즐겁게 하세요!