icon안동민 개발노트

지금까지 배운 내용을 종합한 미니 프로젝트 구현


 이 최종 프로젝트에서는 "Task Manager" 애플리케이션을 구현하며 지금까지 학습한 React 개념과 기술을 종합적으로 적용해볼 것입니다.

 이 애플리케이션은 사용자가 작업을 생성, 조회, 수정, 삭제할 수 있는 기능을 제공합니다.

프로젝트 요구사항

  1. 사용자 인증 (로그인 / 로그아웃)
  2. 작업 목록 표시
  3. 새 작업 추가
  4. 작업 수정 및 삭제
  5. 작업 필터링 및 정렬
  6. 반응형 디자인

1단계 : 프로젝트 설정

 Create React App을 사용하여 프로젝트를 생성합니다.

npx create-react-app task-manager
cd task-manager
npm install react-router-dom axios styled-components

2단계 : 컴포넌트 구조 설계

src/
  components/
    Auth/
      Login.js
      Signup.js
    Tasks/
      TaskList.js
      TaskItem.js
      TaskForm.js
    Layout/
      Header.js
      Footer.js
  pages/
    Home.js
    Dashboard.js
  context/
    AuthContext.js
    TaskContext.js
  api/
    auth.js
    tasks.js
  hooks/
    useAuth.js
    useTasks.js
  App.js

3단계 : 라우팅 구현

 App.js에서 라우팅을 설정합니다.

import React from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import Home from './pages/Home';
import Dashboard from './pages/Dashboard';
import Login from './components/Auth/Login';
import Signup from './components/Auth/Signup';
import { AuthProvider } from './context/AuthContext';
 
function App() {
  return (
    <AuthProvider>
      <Router>
        <Switch>
          <Route exact path="/" component={Home} />
          <Route path="/dashboard" component={Dashboard} />
          <Route path="/login" component={Login} />
          <Route path="/signup" component={Signup} />
        </Switch>
      </Router>
    </AuthProvider>
  );
}
 
export default App;

4단계 : 상태 관리 전략

 Context API를 사용하여 전역 상태를 관리합니다.

AuthContext.js
import React, { createContext, useState, useContext } from 'react';
 
const AuthContext = createContext();
 
export const AuthProvider = ({ children }) => {
  const [user, setUser] = useState(null);
 
  const login = (userData) => {
    setUser(userData);
  };
 
  const logout = () => {
    setUser(null);
  };
 
  return (
    <AuthContext.Provider value={{ user, login, logout }}>
      {children}
    </AuthContext.Provider>
  );
};
 
export const useAuth = () => useContext(AuthContext);

5단계 : API 통합

 axios를 사용하여 API 요청을 처리합니다.

api/tasks.js
import axios from 'axios';
 
const API_URL = 'https://api.example.com';
 
export const getTasks = async () => {
  const response = await axios.get(`${API_URL}/tasks`);
  return response.data;
};
 
export const createTask = async (taskData) => {
  const response = await axios.post(`${API_URL}/tasks`, taskData);
  return response.data;
};
 
// 추가 API 요청 함수들...

6단계 : 컴포넌트 구현

components/Tasks/TaskList.js
import React, { useState, useEffect } from 'react';
import { getTasks } from '../../api/tasks';
import TaskItem from './TaskItem';
 
function TaskList() {
  const [tasks, setTasks] = useState([]);
 
  useEffect(() => {
    const fetchTasks = async () => {
      const tasksData = await getTasks();
      setTasks(tasksData);
    };
    fetchTasks();
  }, []);
 
  return (
    <div>
      {tasks.map(task => (
        <TaskItem key={task.id} task={task} />
      ))}
    </div>
  );
}
 
export default TaskList;

7단계 : 폼 처리 및 유효성 검사

 TaskForm.js에서 React Hook Form을 사용하여 폼 처리와 유효성 검사를 구현합니다.

components/Tasks/TaskForm.js
import React from 'react';
import { useForm } from 'react-hook-form';
import { createTask } from '../../api/tasks';
 
function TaskForm() {
  const { register, handleSubmit, errors } = useForm();
 
  const onSubmit = async (data) => {
    try {
      await createTask(data);
      // 성공 처리
    } catch (error) {
      // 에러 처리
    }
  };
 
  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input
        name="title"
        ref={register({ required: 'Title is required' })}
        placeholder="Task title"
      />
      {errors.title && <span>{errors.title.message}</span>}
      <textarea
        name="description"
        ref={register}
        placeholder="Task description"
      />
      <button type="submit">Add Task</button>
    </form>
  );
}
 
export default TaskForm;

8단계 : 성능 최적화

  • React.memo를 사용하여 불필요한 리렌더링 방지
  • useCallback과 useMemo를 활용하여 함수와 값 메모이제이션
  • 리스트 렌더링 최적화를 위해 가상화 기법 적용

9단계 : 스타일링

 styled-components를 사용하여 컴포넌트 스타일링을 적용합니다.

import styled from 'styled-components';
 
const TaskItemWrapper = styled.div`
  background-color: #f0f0f0;
  border-radius: 4px;
  padding: 16px;
  margin-bottom: 8px;
`;
 
function TaskItem({ task }) {
  return (
    <TaskItemWrapper>
      <h3>{task.title}</h3>
      <p>{task.description}</p>
    </TaskItemWrapper>
  );
}

10단계 : 테스팅

 Jest와 React Testing Library를 사용하여 컴포넌트 테스트 작성하기

import React from 'react';
import { render, screen } from '@testing-library/react';
import TaskItem from './TaskItem';
 
test('renders task title', () => {
  const task = { id: 1, title: 'Test Task', description: 'Test Description' };
  render(<TaskItem task={task} />);
  const titleElement = screen.getByText(/Test Task/i);
  expect(titleElement).toBeInTheDocument();
});

11단계 : 배포

 Netlify를 사용하여 애플리케이션 배포

  1. Netlify 계정 생성
  2. GitHub 저장소와 연동
  3. 빌드 설정 : npm run build
  4. 배포 트리거 : main 브랜치에 push

프로젝트 확장 제안

  1. 작업 우선순위 설정 기능 추가
  2. 작업 완료 날짜 추적 및 알림 기능
  3. 팀 협업 기능 (작업 할당, 공유 등)
  4. 드래그 앤 드롭으로 작업 순서 변경
  5. 데이터 시각화 (작업 진행 상황 차트 등)

개발 과정 회고

 이 프로젝트를 통해 React의 핵심 개념들을 실제로 적용해보았습니다. 컴포넌트 구조 설계, 상태 관리, 라우팅, API 통합 등 각 단계에서 배운 내용을 종합적으로 활용할 수 있었습니다. 특히 Context API를 사용한 전역 상태 관리와 커스텀 훅을 통한 로직 재사용은 코드의 구조화와 재사용성 향상에 큰 도움이 되었습니다.

 성능 최적화 과정에서는 React의 렌더링 최적화 기법들을 적용해보며, 대규모 애플리케이션에서의 성능 관리의 중요성을 체감할 수 있었습니다. 또한, 테스팅 과정을 통해 안정적인 애플리케이션 개발의 기초를 다질 수 있었습니다.

추가 개선 방향

  1. 서버 사이드 렌더링 도입 : Next.js를 활용하여 초기 로딩 성능 개선
  2. 상태 관리 라이브러리 도입 : Redux나 MobX를 사용하여 더 복잡한 상태 관리 시나리오 대응
  3. 마이크로 프론트엔드 아키텍처 적용 : 대규모 확장을 위한 구조 개선
  4. 접근성 개선 : ARIA 속성 추가 및 키보드 네비게이션 지원
  5. 국제화(i18n) 지원 : 다국어 지원을 위한 구조 도입

 이 프로젝트는 React 개발의 기초부터 고급 기술까지 다양한 측면을 경험할 수 있는 좋은 시작점입니다.

 앞으로 React 생태계의 다양한 도구와 라이브러리를 탐험하며, 더 복잡하고 규모 있는 애플리케이션을 개발할 수 있는 기반을 마련했습니다.

 지속적인 학습을 통해 더 나은 React 개발자로 성장할 수 있기를 바랍니다.