리액트 강좌: useEffect에 대한 모든 것

리액트는 현대 웹 애플리케이션을 구축하기 위한 가장 인기 있는 JavaScript 라이브러리 중 하나입니다. 그중에서도 useEffect 훅은 컴포넌트의 생명 주기를 제어하고, 사이드 이펙트를 관리하는 데 매우 중요한 역할을 합니다. 이 글에서는 useEffect의 기본 개념, 사용법, 다양한 사례를 상세히 다루겠습니다.

1. useEffect란 무엇인가?

useEffect는 React 라이브러리에서 제공하는 훅 중 하나로, 함수형 컴포넌트에서 사이드 이펙트를 발생시키기 위해 사용됩니다. 사이드 이펙트란 데이터 가져오기, 수동 DOM 조작, 타이머 설정 또는 다른 외부 시스템과의 상호작용 등을 포함합니다.

리액트의 컴포넌트는 상태(state)와 속성(props)만을 작성하도록 설계되었지만, 때때로 컴포넌트가 렌더링될 때 다른 작업을 수행해야 할 필요가 있습니다. 이러한 작업을 수행하기 위해 useEffect 훅을 사용합니다.

2. useEffect의 기본 사용법

useEffect는 다음과 같은 구문으로 사용할 수 있습니다:

useEffect(() => {
  // 사이드 이펙트 코드
}, [의존성 배열]);

위 구문에서 첫 번째 매개변수는 사이드 이펙트를 수행하는 함수이며, 두 번째 매개변수는 의존성 배열입니다. 의존성 배열에는 해당 훅이 의존하는 상태나 props가 들어갑니다.

2.1. 간단한 예제

import React, { useEffect, useState } from 'react';

function ExampleComponent() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    document.title = \`Count: \${count}\`;
  }, [count]);

  return (
    

현재 카운트: {count}

); }

위 예제에서는 count가 변경될 때마다 문서 제목이 업데이트됩니다. count가 의존성 배열에 포함되어 있기 때문에, setCount 함수가 호출되어 count가 업데이트될 경우에만 사이드 이펙트가 실행됩니다.

3. useEffect의 실행 타이밍

useEffect는 컴포넌트가 렌더링된 후에 실행됩니다. 정리하자면 다음과 같습니다:

  • 컴포넌트가 처음 렌더링될 때 유효성 검사 후 실행
  • 의존성 배열에 명시된 값이 변경될 때 다시 실행

예를 들어, 의존성 배열이 비어 있는 경우:

useEffect(() => {
  // 최초 렌더링 후에만 실행
}, []);

3.1. 클린업 함수

useEffect는 클린업 함수를 반환할 수 있습니다. 이 클린업 함수는 컴포넌트가 언마운트될 때 또는 다음 효과가 실행되기 전에 호출됩니다. 이는 메모리 누수를 방지하는 데 매우 유용합니다.

useEffect(() => {
  const timer = setTimeout(() => {
    console.log('타이머 실행!');
  }, 1000);

  return () => {
    clearTimeout(timer); // 컴포넌트 언마운트 시 타이머 클리어
  };
}, []);

4. useEffect에 대한 고급 사용법

이제 기본 사용법을 익혔으니, useEffect의 고급 개념으로 넘어가 보겠습니다. 개체 관리를 위한 세부 매개변수 전달, 조건부 실행 등의 방법을 알아보겠습니다.

4.1. 조건부 실행

때때로 특정 조건이 충족될 때만 useEffect를 실행하고 싶을 수 있습니다. 조건문을 사용해 이를 구현할 수 있습니다:

useEffect(() => {
  if (count > 0) {
    console.log('Count is positive');
  }
}, [count]);

4.2. 여러 개의 useEffect 사용하기

하나의 컴포넌트에서 여러 개의 useEffect를 사용하여 각 효과를 독립적으로 관리할 수 있습니다. 각 효과는 자체 의존성 배열을 가질 수 있습니다.

useEffect(() => {
  // 데이터 가져오기
}, [url]);

useEffect(() => {
  // 클리어 타이머
  return () => {
    clearInterval(timerId);
  };
}, []);

5. useEffect 사례 연구

이제 실제 사용 사례를 통해 useEffect의 유용성을 살펴보겠습니다.

5.1. API 데이터 fetching

리액트 애플리케이션에서 API 데이터를 fetching하는 가장 일반적인 경우에서 useEffect를 사용합니다:

import React, { useEffect, useState } from 'react';

function DataFetchingComponent() {
  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetch('https://api.example.com/data')
      .then((response) => response.json())
      .then((data) => {
        setData(data);
        setLoading(false);
      });
  }, []);

  if (loading) return 

로딩 중...

; return (
    {data.map(item =>
  • {item.name}
  • )}
); }

5.2. 실시간 데이터 업데이트

WebSocket이나 서버 전송 이벤트(SSE)를 통해 실시간 데이터를 업데이트할 때 useEffect를 사용할 수 있습니다:

import React, { useEffect, useState } from 'react';

function RealTimeComponent() {
  const [messages, setMessages] = useState([]);

  useEffect(() => {
    const socket = new WebSocket('ws://your-websocket-url');

    socket.onmessage = (event) => {
      const newMessage = JSON.parse(event.data);
      setMessages(prevMessages => [...prevMessages, newMessage]);
    };

    return () => {
      socket.close();
    };
  }, []);

  return (
    
{messages.map((msg, index) => (
{msg.content}
))}
); }

6. useEffect vs 클래스 컴포넌트의 생명주기 메소드

함수형 컴포넌트의 useEffect는 클래스 컴포넌트에서 사용하는 생명주기 메소드(componentDidMount, componentDidUpdate, componentWillUnmount)의 역할을 수행합니다.

예를 들어, componentDidMountcomponentWillUnmount를 구현할 수 있는 useEffect의 사용은 다음과 같습니다:

useEffect(() => {
  // 컴포넌트가 마운트될 때 실행
  fetchData();

  return () => {
    // 컴포넌트가 언마운트될 때 실행
    cleanup();
  };
}, []);

7. 최적화 및 성능 고려 사항

useEffect를 사용할 때는 성능에 미치는 영향을 고려해야 합니다. 다음은 성능을 최적화하기 위한 몇 가지 팁입니다:

  • 의존성 배열을 올바르게 설정하세요. 불필요한 재렌더링을 방지할 수 있습니다.
  • 예를 들어, 특정 상태가 변경될 때만 효과를 실행해야 한다면 이를 명확히 하십시오.
  • 지속하는 메모리 리소스를 해제하기 위해 클린업 함수를 적절히 사용하십시오.

8. 자주 묻는 질문(FAQ)

8.1. useEffect는 언제 호출되나요?

useEffect는 컴포넌트가 마운트되거나 의존성이 업데이트될 때 호출됩니다.

8.2. useEffect를 여러 번 사용할 수 있나요?

네, 한 컴포넌트에서 여러 개의 useEffect를 사용할 수 있습니다. 각 useEffect는 독립적이며, 다른 역활을 수행할 수 있습니다.

8.3. useEffect의 의존성 배열을 비워두면 어떻게 되나요?

의존성 배열을 빈 배열로 설정하면, 컴포넌트가 처음 마운트될 때만 실행되고 이후에는 실행되지 않습니다.

8.4. useEffect 내부에서 setState를 호출해도 괜찮나요?

예, 상태를 업데이트하기 위해 setState를 호출할 수 있으며, 이로 인해 컴포넌트가 재렌더링됩니다. 다만, 무한 루프를 피하기 위해 적절히 의존성을 관리해 주세요.

9. 마치며

이번 강좌에서는 리액트의 useEffect 훅에 대해 자세히 알아보았습니다. useEffect는 사이드 이펙트를 관리하는 데 필수적인 도구로, 리액트 애플리케이션에서 흔히 사용됩니다. 처음에는 어렵게 느껴질 수 있지만, 계속해서 사용하다 보면 자연스럽게 익숙해질 것입니다.

이 글을 통해 useEffect의 강력한 기능과 활용 방법에 대해 이해하고, 자신의 프로젝트에 실제로 적용해 보시길 바랍니다. 앞서 언급한 예제와 같은 다양한 사용 사례를 실습하면서 추가적인 경험을 쌓아보세요!

리액트 강좌: To Do 앱 예제, 기능 구현 준비하기

안녕하세요! 이번 강좌에서는 React를 사용하여 To Do 앱을 만드는 방법에 대해 알아보겠습니다. React는 사용자 인터페이스를 구축하기 위한 라이브러리로, 특히 컴포넌트 기반의 아키텍처로 인해 개발자가 재사용 가능한 UI 구성 요소를 만들 수 있게 해줍니다. To Do 앱은 리액트를 처음 배우는 사람에게 적합한 프로젝트로, 기본적인 CRUD(Create, Read, Update, Delete) 작업을 이해하는 데 도움을 줍니다.

1. 프로젝트 개요

이번 프로젝트에서는 사용자가 할 일을 추가하고, 삭제하며, 완료 여부를 체크할 수 있는 간단한 To Do 앱을 만들어 보겠습니다. 이 앱은 React의 상태 관리 및 이벤트 처리의 기초를 이해하는 데 유용합니다.

2. 필요한 도구 및 라이브러리

  • Node.js: Javascript 런타임 환경. React 프로젝트를 설정하고 실행하기 위해 필요합니다.
  • npm: Node.js 패키지 매니저로, 필요한 라이브러리를 설치하는 데 사용됩니다.
  • React: 사용자 인터페이스를 구축하기 위한 JavaScript 라이브러리입니다.
  • Visual Studio Code: 코드 편집기로, 개발 환경을 설정하는 데 사용됩니다.

3. 환경 설정

우선, Node.js가 설치되어 있는지 확인하세요. 설치되어 있지 않다면, Node.js 공식 웹사이트에서 다운로드하여 설치합니다.

설치가 완료되면 다음 명령어를 이용해 새로운 React 앱을 생성합니다:

npx create-react-app todo-app

앱 생성이 완료되면, 생성된 디렉터리로 이동하여 앱을 실행합니다:

cd todo-app
npm start

브라우저에서 http://localhost:3000을 열면 기본 React 앱이 표시될 것입니다.

4. 프로젝트 구조 이해하기

프로젝트가 생성되면 다음과 같은 폴더 구조를 확인할 수 있습니다:


todo-app/
├── node_modules/
├── public/
└── src/
    ├── App.css
    ├── App.js
    ├── index.css
    ├── index.js
    └── logo.svg

여기서 주로 수정할 파일은 src/App.js입니다. 이 파일의 내용을 수정하여 To Do 앱의 기능을 구현해 나갈 것입니다.

5. 컴포넌트 설계

To Do 앱은 다음과 같은 컴포넌트로 구성될 것입니다:

  • ToDoApp: 앱의 주요 컴포넌트로 모든 서브 컴포넌트를 포함합니다.
  • ToDoList: 추가된 할 일 목록을 표시합니다.
  • ToDoItem: 개별 할 일을 나타내며, 완료 및 삭제 기능을 지원합니다.
  • AddToDo: 새로운 할 일을 추가하는 폼을 제공합니다.

5.1 ToDoApp 컴포넌트 설정

src/App.js 파일을 열고 다음과 같이 내용을 수정합니다:

import React, { useState } from 'react';
import ToDoList from './ToDoList';
import AddToDo from './AddToDo';
import './App.css';

const ToDoApp = () => {
    const [todos, setTodos] = useState([]);

    const addTodo = (todo) => {
        setTodos([...todos, todo]);
    };

    const deleteTodo = (index) => {
        const newTodos = todos.filter((_, i) => i !== index);
        setTodos(newTodos);
    };

    const toggleTodo = (index) => {
        const newTodos = [...todos];
        newTodos[index].completed = !newTodos[index].completed;
        setTodos(newTodos);
    };

    return (
        

To Do List

); }; export default ToDoApp;

5.2 ToDoList 컴포넌트 생성

할 일 목록 컴포넌트를 생성하기 위해 src/ToDoList.js 파일을 생성하고 다음 내용을 추가합니다:

import React from 'react';
import ToDoItem from './ToDoItem';

const ToDoList = ({ todos, deleteTodo, toggleTodo }) => {
    return (
        
    {todos.map((todo, index) => ( ))}
); }; export default ToDoList;

5.3 ToDoItem 컴포넌트 생성

개별 할 일 항목을 표시하는 컴포넌트를 만들기 위해 src/ToDoItem.js 파일을 생성하고 아래와 같이 작성합니다:

import React from 'react';

const ToDoItem = ({ todo, deleteTodo, toggleTodo, index }) => {
    return (
        
  • toggleTodo(index)}>{todo.text}
  • ); }; export default ToDoItem;

    5.4 AddToDo 컴포넌트 생성

    새로운 할 일을 추가하는 폼을 생성하기 위해 src/AddToDo.js 파일을 생성하고 다음 코드를 추가합니다:

    import React, { useState } from 'react';
    
    const AddToDo = ({ addTodo }) => {
        const [inputValue, setInputValue] = useState('');
    
        const handleSubmit = (e) => {
            e.preventDefault();
            if (inputValue.trim()) {
                addTodo({ text: inputValue.trim(), completed: false });
                setInputValue('');
            }
        };
    
        return (
            
    setInputValue(e.target.value)} placeholder="할 일을 입력하세요" />
    ); }; export default AddToDo;

    6. 스타일링

    이제 기본적인 기능 구현이 끝났으니, 앱을 조금 더 예쁘게 만들기 위해 스타일링을 추가해보겠습니다. src/App.css 파일을 수정하여 다음과 같이 스타일을 추가합니다:

    .todo-app {
        max-width: 500px;
        margin: 0 auto;
        padding: 20px;
        border: 1px solid #ccc;
        border-radius: 5px;
        box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
    }
    
    h1 {
        text-align: center;
    }
    
    form {
        display: flex;
        justify-content: space-between;
    }
    
    form input {
        flex: 1;
        margin-right: 10px;
    }
    
    ul {
        list-style-type: none;
        padding: 0;
    }
    
    li {
        display: flex;
        justify-content: space-between;
        padding: 10px 0;
    }
    
    .completed {
        text-decoration: line-through;
        color: gray;
    }

    7. 앱 실행 및 테스트

    모든 컴포넌트와 스타일이 준비되었으므로, 앱을 실행해 보세요. 브라우저에서 http://localhost:3000을 열고 할 일을 추가하고, 삭제 및 완료 상태를 변경하는 기능이 제대로 작동하는지 확인합니다.

    8. 마무리 및 추가 기능

    이제 기본적인 To Do 앱이 완성되었습니다. 하지만 리액트를 더 잘 활용하기 위해 추가 기능을 고려해볼 수 있습니다. 예를 들어:

    • 할 일 리스트를 로컬 스토리지에 저장하여 새로고침 후에도 유지하기
    • 할 일을 편집하는 기능 추가하기
    • 필터 기능 추가하여 완료된 할 일만 보기

    이번 강좌에서 배운 내용을 바탕으로 여러분의 아이디어를 적용해보세요! 감사합니다!

    리액트 강좌: To Do 앱 예제, 프로젝트 준비하기

    React는 Facebook이 개발한 라이브러리로, 사용자 인터페이스를 구축하는 데 사용됩니다. 리액트를 이용하여 효율적이고 재사용 가능한 UI 컴포넌트를 만들 수 있습니다. 본 강좌에서는 To Do 앱을 예제로 사용하여 리액트를 이용한 프로젝트 준비하는 방법을 배우게 됩니다. 이 강좌를 통해 리액트의 기본 개념과 프로젝트를 준비하는 과정에 대해 자세히 알아보도록 하겠습니다.

    1. 프로젝트 개요

    To Do 앱은 사용자가 할 일을 추가하고 삭제할 수 있는 간단한 애플리케이션입니다. 본 앱을 통해 다음과 같은 기능을 구현하게 됩니다:

    • 할 일 추가 기능
    • 할 일 삭제 기능
    • 할 일 완료 표시 기능
    • 할 일 필터링 기능 (모두, 진행중, 완료)

    이 프로젝트는 리액트를 처음 접하는 개발자들에게 좋은 연습이 될 것입니다. 단계별로 진행하면서 다양한 리액트 개념을 익힐 수 있습니다.

    2. 개발 환경 설정

    To Do 앱을 개발하기 위해서는 먼저 개발 환경을 설정해야 합니다. 아래의 단계에 따라 진행해 주세요.

    2.1 Node.js 설치

    React는 Node.js 환경에서 실행됩니다. Node.js가 설치되어 있지 않다면, 다음 링크에서 다운로드하여 설치합니다: Node.js 공식 사이트. 설치가 완료된 후, 아래의 명령어로 Node.js가 잘 설치되었는지 확인합니다.

    node -v
    npm -v

    2.2 Create React App 사용

    React 프로젝트를 빠르게 설정하기 위해 Create React App을 사용합니다. 아래의 명령어로 새로운 프로젝트를 생성합니다.

    npx create-react-app todo-app

    위 명령어는 `todo-app`이라는 이름의 새로운 리액트 프로젝트를 생성합니다. 생성이 완료된 후 해당 디렉토리로 이동합니다.

    cd todo-app

    2.3 프로젝트 구조 이해하기

    생성된 리액트 프로젝트에는 기본적으로 여러 폴더와 파일이 생성됩니다. 주요 폴더 구조는 다음과 같습니다:

    • node_modules: 프로젝트의 의존성이 저장되는 폴더입니다.
    • public: 정적 파일이 저장되는 폴더입니다.
    • src: 리액트 컴포넌트와 앱의 주요 로직이 들어가는 폴더입니다.
    • package.json: 프로젝트의 메타 정보를 담고 있는 파일입니다.

    3. To Do 앱 구현하기

    이제 본격적으로 To Do 앱을 구현해보겠습니다. 다음 단계들을 따라가며 코드를 작성해보세요.

    3.1 App 컴포넌트 만들기

    `src` 폴더 안에 `App.js` 파일을 열어서 아래와 같이 수정합니다.

    
    import React, { useState } from 'react';
    import './App.css';
    
    function App() {
        const [todos, setTodos] = useState([]);
        const [inputValue, setInputValue] = useState('');
    
        const addTodo = () => {
            if (inputValue.trim()) {
                setTodos([...todos, { text: inputValue, completed: false }]);
                setInputValue('');
            }
        };
    
        return (
            

    To Do List

    setInputValue(e.target.value)} placeholder="할 일을 입력하세요" />
      {todos.map((todo, index) => (
    • {todo.text}
    • ))}
    ); } export default App;

    3.2 할 일 삭제 기능 추가하기

    이제 각 할 일을 삭제할 수 있는 기능을 추가해보겠습니다. `addTodo` 함수 아래에 아래의 함수를 추가합니다.

    
    const removeTodo = (index) => {
        setTodos(todos.filter((_, i) => i !== index));
    };
    

    그리고 `

  • ` 태그 안에 삭제 버튼을 추가합니다.
  • 
    {todos.map((todo, index) => (
        
  • {todo.text}
  • ))}

    3.3 완료 표시 기능 추가하기

    사용자가 할 일을 완료 상태로 변경할 수 있는 기능도 추가해보겠습니다. 먼저, 할 일 항목의 상태를 업데이트하는 함수를 추가합니다.

    
    const toggleComplete = (index) => {
        const newTodos = [...todos];
        newTodos[index].completed = !newTodos[index].completed;
        setTodos(newTodos);
    };
    

    그 다음, `

  • ` 태그에 완료 시 스타일을 추가하고 클릭 시 변경되도록 합니다.
  • 
    
  • toggleComplete(index)}> {todo.text}
  • 3.4 필터링 기능 추가하기

    마지막으로 할 일을 필터링할 수 있는 기능을 추가하겠습니다. 필터 상태를 관리하기 위해 상태 변수를 추가합니다.

    
    const [filter, setFilter] = useState('all');
    

    아래의 조건문을 사용하여 할 일 목록을 필터링합니다.

    
    const filteredTodos = todos.filter(todo => {
        if (filter === 'completed') return todo.completed;
        if (filter === 'active') return !todo.completed;
        return true;
    });
    

    마지막으로 필터 버튼을 추가하여 사용자가 선택할 수 있게 합니다.

    
    
    
    
    
      {filteredTodos.map((todo, index) => (
    • toggleComplete(index)}> {todo.text}
    • ))}

    4. 마무리 및 배포

    To Do 앱의 모든 기능을 구현하였습니다. 마지막으로 앱을 테스트한 후, 배포를 진행할 차례입니다.

    4.1 앱 테스트하기

    로컬에서 앱을 실행하여 기능이 잘 작동하는지 확인합니다. 아래의 명령어로 로컬 서버를 시작합니다.

    npm start

    4.2 배포하기

    앱이 잘 작동하면, 이제 배포할 차례입니다. 여러 배포 옵션이 있지만, Create React App이 제공하는 `build` 명령어를 사용하여 최적화된 코드를 생성할 수 있습니다.

    npm run build

    생성된 `build` 폴더를 서버에 업로드하거나, Netlify, Vercel과 같은 플랫폼을 사용하여 배포할 수 있습니다.

    5. 결론

    이제 리액트를 사용하여 간단한 To Do 앱을 만들어 보았습니다. 이 과정을 통해 리액트의 핵심 개념과 앱 개발의 기본 프로세스를 이해할 수 있었습니다. 앞으로 더욱 복잡한 애플리케이션을 개발할 수 있는 기반이 되었기를 바랍니다.

    추가적으로 이 프로젝트에 기능을 더하거나 디자인을 수정하여 더 발전된 버전을 만들어보는 것도 좋은 연습이 될 것입니다. 리액트를 응용하여 다른 프로젝트도 시도해 보세요!

    리액트 강좌: To Do 앱 예제, UI 구현하기

    안녕하세요. 이번 글에서는 리액트로 To Do 앱을 만드는 방법에 대해 알아보겠습니다. 이 강좌에서는 UI/UX 설계와 함께 기능 구현까지 다룰 것입니다. 리액트는 컴포넌트 기반의 자바스크립트 라이브러리로, 동적인 사용자 인터페이스를 쉽게 만들 수 있도록 도와줍니다.

    프로젝트 준비하기

    시작하기 전에, 프로젝트의 기본 설정을 해야 합니다. 다음과 같은 과정으로 개발 환경을 구축할 수 있습니다.

    npx create-react-app my-todo-app

    위 명령어를 실행하면 my-todo-app이라는 폴더에 리액트 앱의 기본 템플릿이 생성됩니다. 생성된 폴더로 이동하고 앱을 실행해 보겠습니다.

    cd my-todo-app
    npm start

    브라우저에서 http://localhost:3000에 접속하면 기본 리액트 앱이 실행되는 것을 볼 수 있습니다.

    컴포넌트 구조 설계하기

    To Do 앱의 기본적인 기능은 할 일을 추가하고, 완료 상태를 토글하며, 삭제하는 것입니다. 아래와 같은 컴포넌트 구조를 설계할 수 있습니다.

    • App: 애플리케이션의 루트 컴포넌트
    • TodoList: 할 일 목록을 표시하는 컴포넌트
    • TodoItem: 각 할 일 항목을 표시하는 컴포넌트
    • AddTodo: 할 일을 추가하는 폼 컴포넌트

    컴포넌트 구현하기

    이제 각 컴포넌트를 구현해 보겠습니다.

    1. App 컴포넌트

    먼저 App.js 파일을 열어 기본 상태를 정의해 보겠습니다.

    import React, { useState } from 'react';
    import TodoList from './components/TodoList';
    import AddTodo from './components/AddTodo';
    
    const App = () => {
        const [todos, setTodos] = useState([]);
    
        const addTodo = (todo) => {
            setTodos([...todos, todo]);
        };
    
        const toggleComplete = (index) => {
            const newTodos = todos.map((todo, i) => {
                if (i === index) {
                    return { ...todo, completed: !todo.completed };
                }
                return todo;
            });
            setTodos(newTodos);
        };
    
        const deleteTodo = (index) => {
            const newTodos = todos.filter((_, i) => i !== index);
            setTodos(newTodos);
        };
    
        return (
            <div className="App">
                <h1>To Do List</h1>
                <AddTodo addTodo={addTodo} />
                <TodoList todos={todos} toggleComplete={toggleComplete} deleteTodo={deleteTodo} />
            </div>
        );
    };
    
    export default App;

    2. TodoList 컴포넌트

    다음으로 TodoList.js를 구현합니다. 이 컴포넌트는 할 일 목록을 렌더링합니다.

    import React from 'react';
    import TodoItem from './TodoItem';
    
    const TodoList = ({ todos, toggleComplete, deleteTodo }) => {
        return (
            <ul>
                {todos.map((todo, index) => (
                    <TodoItem 
                        key={index} 
                        todo={todo} 
                        toggleComplete={() => toggleComplete(index)} 
                        deleteTodo={() => deleteTodo(index)} 
                    />
                ))}
            </ul>
        );
    };
    
    export default TodoList;

    3. TodoItem 컴포넌트

    이제 각 할 일 항목을 표현하는 TodoItem.js를 작성합니다.

    import React from 'react';
    
    const TodoItem = ({ todo, toggleComplete, deleteTodo }) => {
        return (
            <li style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}>
                {todo.text}
                <button onClick={toggleComplete}>완료</button>
                <button onClick={deleteTodo}>삭제</button>
            </li>
        );
    };
    
    export default TodoItem;

    4. AddTodo 컴포넌트

    마지막으로, 할 일을 추가하는 폼을 구현합니다.

    import React, { useState } from 'react';
    
    const AddTodo = ({ addTodo }) => {
        const [inputValue, setInputValue] = useState('');
    
        const handleSubmit = (e) => {
            e.preventDefault();
            if (inputValue.trim()) {
                addTodo({ text: inputValue, completed: false });
                setInputValue('');
            }
        };
    
        return (
            <form onSubmit={handleSubmit}>
                <input 
                    type="text" 
                    value={inputValue} 
                    onChange={(e) => setInputValue(e.target.value)} 
                    placeholder="할 일을 입력하세요" 
                />
                <button type="submit">추가</button>
            </form>
        );
    };
    
    export default AddTodo;

    스타일링 추가하기

    이제 기본적인 기능이 구현되었으니, CSS를 사용해 UI를 더욱 아름답게 꾸며봅시다. App.css 파일에 다음의 스타일을 추가합니다.

    body {
        font-family: 'Arial', sans-serif;
        background-color: #f4f4f4;
    }
    
    .App {
        max-width: 600px;
        margin: 50px auto;
        padding: 20px;
        background: white;
        border-radius: 8px;
        box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
    }
    
    h1 {
        text-align: center;
    }
    
    form {
        display: flex;
        justify-content: space-between;
        margin-bottom: 20px;
    }
    
    input[type="text"] {
        flex: 1;
        padding: 10px;
        border: 1px solid #ccc;
        border-radius: 4px;
    }
    
    button {
        padding: 10px 15px;
        margin-left: 10px;
        border: none;
        border-radius: 4px;
        background: #4A90E2;
        color: white;
        cursor: pointer;
    }
    
    button:hover {
        background: #357ABD;
    }
    
    ul {
        list-style-type: none;
        padding: 0;
    }

    테스트 및 배포

    이제 앱이 완성되었으니, 테스트 및 배포를 진행할 수 있습니다. npm run build 명령어를 통해 프로덕션 빌드를 생성할 수 있습니다.

    npm run build

    생성된 build 폴더를 서버에 배포하면 여러분의 To Do 앱이 세상에 선보이게 됩니다.

    결론

    이번 강좌에서는 리액트를 사용하여 기본적인 To Do 앱을 구현해보았습니다. 리액트의 컴포넌트 기반 아키텍처와 상태 관리를 활용하여 효율적으로 UI를 구축할 수 있었습니다. 다음에는 더 복잡한 기능 추가나 상태 관리 라이브러리인 Redux를 사용해보는 것도 추천드립니다.

    리액트를 통한 프로젝트 개발은 반복과 개선의 과정입니다. 계속해서 학습하고 실습하여 여러분만의 멋진 애플리케이션을 만들어보세요!

    리액트 강좌: To Do 앱 예제, Update: 할 일 수정하기

    이번 강좌에서는 리액트를 사용하여 간단한 To Do 앱을 만들어 보겠습니다. 이 강좌에서는 할 일을 수정하는 기능을 추가하는 방법에 대해 깊이 있게 다룰 것입니다. 리액트를 처음 사용하는 분들도 이해할 수 있도록 기초부터 차근차근 설명할 예정이니 걱정하지 마세요.

    1. 리액트 소개

    리액트는 사용자 인터페이스를 구축하기 위한 JavaScript 라이브러리입니다. 페이스북에서 개발하였으며, 하나의 페이지에서 동적인 웹 애플리케이션을 쉽게 만들 수 있도록 도와줍니다. 리액트의 가장 큰 장점 중 하나는 컴포넌트 기반 구조입니다. 이로 인해 코드의 재사용성이 높아지고, 유지보수가 용이해집니다.

    1.1 컴포넌트

    리액트에서 모든 것은 컴포넌트로 이루어져 있습니다. 컴포넌트는 화면의 일부를 구성하는 독립적인 블록으로 생각할 수 있습니다. 각 컴포넌트는 자체의 상태(State)와 속성(Props)을 가질 수 있으며, 이를 통해 상위 컴포넌트와 데이터를 주고받을 수 있습니다.

    2. To Do 앱 기본 구조 설정

    처음에는 To Do 앱의 기본 구조를 설정할 것입니다. 아래의 단계를 따라 진행해 보세요.

    2.1 프로젝트 생성

    npx create-react-app todo-app

    위 명령어를 통해 새로운 리액트 프로젝트를 생성합니다. todo-app이라는 폴더 안에 필요한 파일이 생성될 것입니다.

    2.2 기본 컴포넌트 구조 만들기

    src 폴더 안에 Todo.js 파일을 생성하고, 아래와 같이 기본 구조를 작성합니다.

    import React, { useState } from 'react';
    
    const Todo = () => {
        const [todos, setTodos] = useState([]);
        const [inputValue, setInputValue] = useState('');
    
        const handleAdd = () => {
            if (!inputValue) return;
            setTodos([...todos, { text: inputValue, isEditing: false }]);
            setInputValue('');
        };
    
        return (
            

    할 일 목록

    setInputValue(e.target.value)} />
      {todos.map((todo, index) => (
    • {todo.text}
    • ))}
    ); }; export default Todo;

    3. 할 일 수정 기능 추가하기

    이제 To Do 앱에 할 일 수정 기능을 추가해 보겠습니다. 사용자가 할 일을 클릭했을 때 해당 항목을 수정할 수 있도록 구현할 것입니다.

    3.1 상태 관리 추가

    상태 관리 기능을 추가하기 위해, 각 할 일 항목에 대해 편집 모드를 추가해야 합니다. Todo.js 파일을 아래와 같이 수정합니다.

    const handleEdit = (index) => {
        const updatedTodos = todos.map((todo, idx) => {
            if (idx === index) {
                return { ...todo, isEditing: !todo.isEditing };
            }
            return todo;
        });
        setTodos(updatedTodos);
    };
    
    const handleUpdate = (index, newText) => {
        const updatedTodos = todos.map((todo, idx) => {
            if (idx === index) {
                return { text: newText, isEditing: false };
            }
            return todo;
        });
        setTodos(updatedTodos);
    };

    3.2 수정하는 UI 만들기

    이제 수정하는 UI를 작성하여 사용자가 쉽게 할 일을 수정할 수 있도록 해야 합니다. 아래 코드를 return 문 안에 붙여넣습니다.

    {todos.map((todo, index) => (
        
  • {todo.isEditing ? (
    handleUpdate(index, e.target.value)} />
    ) : (
    handleEdit(index)}>{todo.text}
    )}
  • ))}

    3.3 전체 코드

    이제 전체 코드는 다음과 같습니다.

    import React, { useState } from 'react';
    
    const Todo = () => {
        const [todos, setTodos] = useState([]);
        const [inputValue, setInputValue] = useState('');
    
        const handleAdd = () => {
            if (!inputValue) return;
            setTodos([...todos, { text: inputValue, isEditing: false }]);
            setInputValue('');
        };
    
        const handleEdit = (index) => {
            const updatedTodos = todos.map((todo, idx) => {
                if (idx === index) {
                    return { ...todo, isEditing: !todo.isEditing };
                }
                return todo;
            });
            setTodos(updatedTodos);
        };
    
        const handleUpdate = (index, newText) => {
            const updatedTodos = todos.map((todo, idx) => {
                if (idx === index) {
                    return { text: newText, isEditing: false };
                }
                return todo;
            });
            setTodos(updatedTodos);
        };
    
        return (
            

    할 일 목록

    setInputValue(e.target.value)} />
      {todos.map((todo, index) => (
    • {todo.isEditing ? (
      handleUpdate(index, e.target.value)} />
      ) : (
      handleEdit(index)}>{todo.text}
      )}
    • ))}
    ); }; export default Todo;

    4. 마무리

    축하합니다! 이제 리액트를 사용하여 To Do 앱을 만들고, 할 일을 수정하는 기능까지 추가했습니다. 이 강좌를 통해 리액트의 기본 개념을 이해하고, 실습을 통해 코드를 작성하는 방법을 학습하셨습니다. 향후에는 더 복잡한 상태 관리나 다양한 라이브러리와의 연동을 통해 더욱 많은 기능을 추가해 보세요.

    5. 다음 강좌 예고

    다음 강좌에서는 To Do 앱에 추가 기능을 더 추가하거나, 리액트 Router를 활용하여 페이지를 관리하는 방법에 대해 다룰 예정입니다. 많은 기대 부탁드립니다!