드디어 로그인, 회원가입을 끝내고 게시판 및 마이 프로필 등 다양한 기능들을 개발하기 시작했다.
내가 담당한 건 총 3가지
- 마이 프로필 (+ 비밀번호 수정)
- 게시판 메인 화면
- 작성 글 리스트
마이 프로필, 비밀번호 수정 화면을 만들 때 공통 섹션인 Header 영역을 재사용하기로 하였고, 이론으로만 배웠던 리액트의 재사용의 용이성을 실감하게 되었다.

가장 기본은 아래의 [비밀번호 변경] 처럼 로고 + 타이틀만 있는 헤더
import React from 'react';
import { useNavigate } from 'react-router-dom';
import koundaryLogo from '../../assets/images/koundary_logo.png';
const Header = ({ title = '내 프로필' }) => {
const navigate = useNavigate();
const handleLogout = () => {
localStorage.clear();
navigate('/login');
};
return (
<header className="border-b py-4">
<div className="max-w-screen-lg mx-auto px-4 flex justify-between items-center">
<div className="flex items-center gap-2">
<img src={koundaryLogo} alt="Koundary Logo" className="h-8 object-contain" />
<span className="text-xl font-semibold">{title}</span>
</div>
<button
onClick={handleLogout}
className="px-4 py-1 border rounded hover:bg-gray-100"
>
로그아웃
</button>
</div>
</header>
);
};
export default Header;
-> 기본값은 "내 프로필"로 유지하고, 필요하면 override할 수 있도록 만듦!
그렇다면 다른 페이지에서는 어떻게 재사용하나?
<Header />
<Header title="비밀번호 변경" />
이렇게 사용하니 하나의 Header.jsx 컴포넌트를 계속 재사용하면서
페이지마다 내 프로필, 비밀번호 변경, 회원가입 등 원하는 텍스트로 유연하게 표시가 가능했다.
정말 재사용하기 편한 구조였다..! 또한 코드에 대한 직관적인 이해도도 상승하는 느낌이었다.
하지만, 초기 와이어프레임에는 헤더의 또 다른 기능이 있었는데
아래의 사진 처럼 일부 페이지에는 [내 프로필], [로그아웃] 버튼이 필요했다.
그냥 Header2를 만드는 게 더 편할수도 있겠지만, 보다 쉬운 파일 관리를 위해 (파일 많으면 머리 아프다 🥹) 위의 Header.jsx 파일을 재사용하기로 마음먹었다.

그래서 아래의 코드를 상단에 추가했고, 필요할 때마다 SHOW_BUTTONS_PATHS에 경로를 추가하면 해당 페이지에는 두 개의 버튼이 출력되게 된다.
const BRAND = '#2e8ada';
// 버튼을 노출할 경로 prefix 목록 (필요에 맞게 수정)
const SHOW_BUTTONS_PATHS = ['/main', '/posts'];
const Header = ({ title = '' /* 필요 없으면 '' */ , showActions /* 강제 표시/숨김용 선택 프롭 */ }) => {
const navigate = useNavigate();
const location = useLocation();
// 경로 기반 자동표시: /main, /board, /board/123 ... 에서 true
const routeWantsButtons = SHOW_BUTTONS_PATHS.some(p =>
location.pathname.startsWith(p)
);
// showActions 프롭이 있으면 우선, 없으면 경로 규칙 사용
const shouldShowActions = typeof showActions === 'boolean' ? showActions : routeWantsButtons;

추가로 유용한 방식을 알게되었다!
이전까지는 백엔드와의 연결 전 UI 확인을 위해 더미 데이터를 하드코딩 했었다.
하지만, 연결 할 때는 하드코딩한 부분을 다 지우고 변수와 함수 등을 다시 짜서 넣어 일을 2번 하였는데!
.env파일에 코드 작성axiosInstance.jsx파일과 해당 기능을 사용하는 파일의 코드를 일부 수정
=> 간편하게 목업 데이터 + 스위치 기능이 추가!
상세한 코드는 아래에서 👇👇
VITE_API_BASE_URL= http://111.11.11.1.11
VITE_USE_MOCK=true
true면 더미 데이터로 동작, false면 실제 서버로 호출⭐ 주의: 저장 후 서버를 재시작해야 반영됨 → npm run dev 다시 실행
src/api/axiosInstance.jsimport axios from 'axios';
const axiosInstance = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL, // .env에서 읽음
headers: { 'Content-Type': 'application/json' },
timeout: 10000,
});
src/api/board.js (목업/실서버 자동 전환)import axiosInstance from './axiosInstance';
const USE_MOCK = import.meta.env.VITE_USE_MOCK === 'true';
const wait = (ms) => new Promise(r => setTimeout(r, ms));
export const getBoardList = async ({ category, page = 1, size = 20 }) => {
if (USE_MOCK) {
// --- 목업 데이터 ---
await wait(300); // 로딩감 주기
const total = 83;
const start = (page - 1) * size;
const items = Array.from({ length: size }).map((_, i) => {
const n = start + i + 1;
return {
id: n,
title: `[${category}] 더미 글 제목 ${n}`,
author: n % 3 === 0 ? '길동' : '홍길동',
createdAt: '2025.07.01',
};
});
return { items, total, page, size };
}
// --- 실서버 호출 ---
const { data } = await axiosInstance.get('/boards', {
params: { category, page, size },
});
return data; // 서버 응답 형식에 맞게 그대로 반환
};
이렇게 하면 아래와 같이 더미 데이터가 생성되며 .env 파일에 작성한 true 부분을 false로 변경한다면 더미 데이터가 사라진다!

로그인, 회원가입 이외에 다른 기능을 만들어보니 이론으로 배웠던 구조나 특징들이 직관적으로 이해되는 기분이었다.
나름 성장하고 있는 거겠지. . (아마)
벌써 2주밖에 안 남은 게 거짓말 같지만 남은 2주 알차게 써서 프로젝트 기분좋게 마무리하고 싶당
다들 파이팅입니닷 💪💪