재우니의 블로그

React.js와 Node.js를 활용한 TODO List 개발: CORS 문제를 해결하는 시나리오

React.js와 Node.js로 간단한 TODO List 애플리케이션을 개발할 때 CORS(Cross-Origin Resource Sharing) 문제가 발생하는 상황을 직접 경험하며 해결하는 방법을 알아보겠습니다. 이 시나리오는 CORS 설정을 생략한 상태에서 시작하여 오류를 디버깅하고, CORS 패키지를 설치하고 적용하는 과정을 다룹니다.


📌 프로젝트 개요 및 목표

목표

  1. React.js를 이용해 TODO List UI를 개발.
  2. Node.js(Express)를 이용해 RESTful API 서버 구성.
  3. CORS 오류를 직접 경험하고 이를 해결하는 방법 익히기.

프로젝트 구조

react-node-todo/
├── backend/      # Node.js 서버 코드
├── frontend/     # React.js 클라이언트 코드

🔧 프로젝트 설치 및 초기화

1. Node.js와 npm 설치 확인

먼저, Node.js와 npm이 설치되어 있는지 확인합니다.

node -v
npm -v

설치되지 않았다면 Node.js 공식 웹사이트에서 최신 버전을 다운로드하세요.


2. 프로젝트 디렉터리 생성

mkdir react-node-todo
cd react-node-todo
mkdir frontend backend

🛠️ 백엔드(Node.js) 설정

1. 백엔드 초기화 및 패키지 설치

cd backend
npm init -y
npm install express

2. server.js 생성 및 작성

backend/server.js 파일을 생성하고 다음 코드를 작성합니다:

const express = require('express');
const app = express();

app.use(express.json()); // JSON 요청 처리

let todos = []; // 메모리 데이터베이스

// GET: 모든 TODO 조회
app.get('/api/todos', (req, res) => {
  res.json(todos);
});

// POST: 새로운 TODO 추가
app.post('/api/todos', (req, res) => {
  const { text } = req.body;
  if (!text) return res.status(400).json({ error: 'Text is required' });

  const newTodo = { id: todos.length + 1, text };
  todos.push(newTodo);
  res.json(newTodo);
});

const PORT = 5000;
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));

3. 서버 실행

node server.js

🎨 프론트엔드(React.js) 설정

1. React 프로젝트 초기화

cd ../frontend
npx create-react-app .
npm install axios

2. TODO List 컴포넌트 생성

frontend/src/components/TodoList.js를 생성하고 다음 코드를 작성합니다:

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

const TodoList = () => {
  const [todos, setTodos] = useState([]);
  const [newTodo, setNewTodo] = useState('');

  // 서버에서 TODO 가져오기
  useEffect(() => {
    axios.get('http://localhost:5000/api/todos')
      .then(response => setTodos(response.data))
      .catch(error => console.error('Error fetching todos:', error));
  }, []);

  // 새로운 TODO 추가
  const addTodo = () => {
    axios.post('http://localhost:5000/api/todos', { text: newTodo })
      .then(response => {
        setTodos([...todos, response.data]);
        setNewTodo('');
      })
      .catch(error => console.error('Error adding todo:', error));
  };

  return (
    <div>
      <h1>TODO List</h1>
      <ul>
        {todos.map(todo => (
          <li key={todo.id}>{todo.text}</li>
        ))}
      </ul>
      <input
        type="text"
        value={newTodo}
        onChange={(e) => setNewTodo(e.target.value)}
        placeholder="Enter a new TODO"
      />
      <button onClick={addTodo}>Add TODO</button>
    </div>
  );
};

export default TodoList;

3. App.js에 컴포넌트 추가

import React from 'react';
import TodoList from './components/TodoList';

function App() {
  return (
    <div className="App">
      <TodoList />
    </div>
  );
}

export default App;

🚨 CORS 문제 시나리오

1. 오류 발생

React 앱을 실행하고 브라우저 개발자 도구의 콘솔에서 다음과 같은 오류를 확인할 수 있습니다:

 

Access to XMLHttpRequest at 'http://localhost:5000/api/todos' 
from origin 'http://localhost:3000' has been blocked by CORS policy: 
No 'Access-Control-Allow-Origin' header is present on the requested resource.

2. 원인 분석

React 클라이언트(localhost:3000)와 Node.js 서버(localhost:5000)는 서로 다른 도메인에서 실행되기 때문에, 브라우저는 보안상의 이유로 요청을 차단합니다.


✅ CORS 문제 해결

1. CORS 패키지 설치

Node.js 백엔드에 CORS 패키지를 설치합니다:

npm install cors

2. server.js에 CORS 설정 추가

server.js 파일을 수정하여 CORS 설정을 추가합니다:

const cors = require('cors');
app.use(cors()); // 모든 도메인 허용

3. 특정 도메인만 허용 (선택 사항)

특정 도메인만 허용하고 싶다면 다음과 같이 설정합니다:

app.use(cors({
  origin: 'http://localhost:3000', // React 앱 도메인
  methods: ['GET', 'POST'], // 허용할 메서드
}));

🚀 실행 및 확인

1. 백엔드 실행

cd backend
node server.js

2. 프론트엔드 실행

cd frontend
npm start

3. 브라우저에서 확인

React 앱에서 TODO를 추가하고 목록을 확인하세요. CORS 오류가 해결된 상태로 요청이 정상적으로 처리됩니다.


🔍 주니어 개발자를 위한 팁

  1. CORS 문제를 학습 기회로 활용하세요
    CORS는 초보 개발자가 자주 마주하는 문제입니다. 직접 해결 과정을 경험하며 보안 정책의 중요성을 이해할 수 있습니다.
  2. 디버깅 습관 기르기
    • 브라우저 개발자 도구의 네트워크 탭콘솔에서 요청과 응답을 확인하세요.
    • Node.js 서버 로그를 확인하여 요청이 제대로 처리되는지 파악하세요.
  3. 프록시 설정 활용
    React 개발 환경에서만 사용할 경우, package.json 파일에 프록시 설정을 추가하여 문제를 임시로 해결할 수 있습니다:
  4. "proxy": "http://localhost:5000"

✅ 결론

이 시나리오에서는 CORS 설정을 생략한 상태에서 발생하는 문제를 해결하며, Node.js와 React.js 간의 통신을 안정적으로 구성하는 방법을 배웠습니다.

  • CORS 문제는 보안 정책을 이해하는 중요한 기회가 됩니다.
  • 백엔드와 프론트엔드를 협력적으로 개발하는 기술을 익힐 수 있습니다.

🎯 추가 과제

  • TODO 삭제 기능 추가.
  • MongoDB를 연동하여 데이터 저장.

🔗 관련 태그

  • react.js
  • node.js
  • todo-list
  • cors-문제
  • axios

 

CORS 가 왜 생겼고, 왜 필요한가요?

 

https://aspdotnet.tistory.com/3327

 

🌐 CORS(Cross-Origin Resource Sharing) '동일 출처 정책' 이란 무엇인가요?

CORS의 역사와 필요성을 최대한 간단하고 직관적으로 설명해 보겠습니다.🌍 CORS: 웹이 우리를 안전하게 지켜주는 방법인터넷은 어떻게 안전하게 발전했을까요?인터넷은 처음 개발된 이후로 많

aspdotnet.tistory.com