Front_end

React 개발자를 위한 가장 쉬운 Node.js 백엔드 연동 가이드

Ta_m 2025. 11. 3. 18:50

 

1. 백엔드 서버 구축하기 (Node.js & Express)

React로 만든 프론트엔드 애플리케이션은 결국 데이터를 주고받거나 완성된 HTML 파일을 사용자에게 제공할 '서버'가 필요합니다.

먼저 Node.jsExpress를 사용해 간단한 웹 서버를 만들어 보겠습니다.

1단계: 개발 환경 준비

  1. Node.js 설치: 구글에서 'Node.js'를 검색하여 공식 사이트에서 LTS (Long Term Support) 버전을 다운로드하여 설치합니다. Node.js를 설치하면 패키지 관리 도구인 npm도 함께 설치됩니다.
  2. 작업 폴더 생성: 프로젝트를 진행할 폴더를 하나 만듭니다. (예: my-project) 폴더 이름은 가급적 영어로 설정하는 것이 좋습니다.
  3. 에디터로 열기: VS Code와 같은 코드 에디터로 방금 만든 폴더를 엽니다.

2단계: 서버 파일 작성 및 설정

  1. server.js 파일 생성: 폴더 내에 server.js라는 이름의 파일을 만듭니다.
  2. 기본 서버 코드 작성: 아래 코드를 server.js 파일에 입력합니다.
    const express = require('express');
    const path = require('path');
    const app = express();
    
    app.listen(8080, function () {
      console.log('8080 포트에서 서버가 대기 중입니다...');
    });
    
    • express는 Node.js에서 웹 서버를 쉽게 만들 수 있게 도와주는 프레임워크입니다.
    • app.listen(8080, ...)은 8080번 포트에서 사용자의 요청을 기다리도록 서버를 실행하는 명령어입니다.
  3. package.json 생성: 터미널을 열고(VS Code  터미널 사용 가능) 다음 명령어를 입력합니다.
    npm init -y
    
    • 이 명령어는 현재 폴더를 Node.js 프로젝트로 초기화하고, 프로젝트의 정보와 의존성을 관리하는 package.json 파일을 생성합니다.
  4. Express 설치: 서버 코드에서 require('express')를 사용했으므로, 실제로 Express 라이브러리를 설치해야 합니다.
    npm install express
    

3단계: 서버 실행하기

이제 서버를 실행할 준비가 되었습니다. 터미널에 다음 명령어를 입력하세요.

node server.js

"8080 포트에서 서버가 대기 중입니다..."라는 메시지가 뜨면 성공입니다.

nodemon 사용하기
node server.js로 서버를 실행하면, 코드를 수정할 때마다 서버를 껐다가 다시 켜야 하는 번거로움이 있습니다. nodemon을 사용하면 코드가 변경될 때마다 서버를 자동으로 재시작해 줍니다.

# nodemon 설치 (컴퓨터 전역에 설치)
npm install -g nodemon

# nodemon으로 서버 실행
nodemon server.js

2부: 프론트엔드 구축하기 (React)

이제 사용자에게 보여질 화면을 만들 React 프로젝트를 생성해 보겠습니다.

1단계: React 프로젝트 생성 (Create React App)

보통 서버 폴더와 나란히 'client' 또는 'frontend' 같은 이름의 하위 폴더를 만들어 그 안에 React 프로젝트를 구성합니다.

  1. Node.js 설치: 1부에서 이미 설치했다면 통과합니다. 최신 버전인지 확인해 주세요.
  2. React 앱 생성: 터미널에서 다음을 입력합니다.
    npx create-react-app my-app
    
    • my-app은 원하는 프로젝트 이름으로 변경할 수 있습니다. (띄어쓰기 금지)
    • npx는 라이브러리를 설치하지 않고 일회성으로 실행하는 명령어입니다.

(참고) Vite 사용하기
최근에는 create-react-app(CRA)보다 빌드 속도가 훨씬 빠른 Vite를 사용하는 추세입니다.

# Vite로 React 프로젝트 생성
npm create vite@latest
# (이후 React, Javascript 등 옵션 선택)

# 생성된 폴더로 이동
cd [프로젝트명]
# 의존성 설치
npm install
# 개발 서버 실행
npm run dev

2단계: 개발 및 빌드

  1. 프로젝트 폴더로 이동 및 실행:
    cd my-app
    npm start
    
    • npm start (CRA) 또는 npm run dev (Vite) 명령어를 입력하면 개발 서버가 실행되고, 브라우저에서 실시간으로 변경 사항을 확인할 수 있는 페이지가 열립니다.
  2. 개발: src 폴더 내의 파일들을 수정하며 원하는 UI와 기능을 개발합니다.
  3. 빌드 (Build):
    개발이 완료되면, 이 React 프로젝트를 실제 서버에 배포할 수 있는 정적 파일(HTML, CSS, JS)로 변환해야 합니다.
    npm run build
    
    • 이 명령어를 실행하면 build라는 폴더가 생성되고, 그 안에 압축되고 최적화된 파일들이 담깁니다.
    • 이제 1부에서 만든 Node.js 서버가build 폴더 안의 index.html 파일을 사용자에게 보내주도록 코드를 추가하면, 우리가 만든 React 앱을 서비스할 수 있게 됩니다.

3부: React 핵심 기능 익히기

React 프로젝트를 만들었다면, 이제 자주 사용하는 핵심 기능들을 알아봅시다.

1. 스타일링: styled-components

CSS를 JS 파일 내에서 컴포넌트 스타일로 직접 작성하게 해주는 라이브러리입니다.

  1. 설치:
    npm i styled-components
    
  2. 사용법:
    import styled from "styled-components";를 파일 상단에 추가하고, 스타일을 적용할 HTML 태그를 지정하여 컴포넌트를 만듭니다.
    import styled from "styled-components";
    
    // 'button' 태그에 스타일을 적용한 'StyledButton' 컴포넌트 생성
    const StyledButton = styled.button`
      background-color: blue;
      color: white;
      font-size: 16px;
      padding: 10px;
    `;
    
    function App() {
      return (
        <div>
          <StyledButton>클릭하세요</StyledButton>
        </div>
      );
    }
    

2. 페이지 나누기: react-router-dom

React는 기본적으로 '싱글 페이지 애플리케이션'(SPA)이므로, 여러 페이지를 만들려면 라우팅 라이브러리가 필요합니다.

  1. 설치:
    npm install react-router-dom
    
  2. 기본 설정 (index.js):
    src/index.js 파일에서 <App /> 컴포넌트를 <BrowserRouter>로 감싸줍니다.
    // index.js
    import React from 'react';
    import ReactDOM from 'react-dom/client';
    import App from './App';
    import { BrowserRouter } from 'react-router-dom';
    
    const root = ReactDOM.createRoot(document.getElementById('root'));
    root.render(
      <React.StrictMode>
        <BrowserRouter>
          <App />
        </BrowserRouter>
      </React.StrictMode>
    );
    
  3. 라우트(페이지) 정의 (App.js):
    App.js에서 <Routes><Route> 컴포넌트를 사용해 URL 경로별로 보여줄 컴포넌트를 지정합니다.
    // App.js
    import { Routes, Route } from 'react-router-dom';
    import DetailPage from './Detail'; // 상세 페이지 컴포넌트
    import AboutPage from './About'; // 어바웃 페이지 컴포넌트
    
    function App() {
      return (
        <Routes>
          {/* path="/" 는 메인 페이지입니다. */}
          <Route path="/" element={ <div>메인페이지임</div> } />
          <Route path="/detail" element={ <DetailPage /> } />
          <Route path="/about" element={ <AboutPage /> } />
        </Routes>
      );
    }
    
  4. 동적 라우트 (useParams):
    /detail/1, /detail/2처럼 URL 파라미터를 받는 페이지를 만들 수 있습니다.
    • 라우트 설정 (App.js):
      경로 뒤에 /:id 와 같이 변수명을 지정합니다.
      <Route path="/detail/:id" element={<Detail shoes={shoes}/>} />
      
    • 파라미터 사용 (Detail.js):
      useParams 훅(Hook)을 사용하여 URL의 :id 값을 가져올 수 있습니다.
      // Detail.js
      import { useParams } from 'react-router-dom';
      
      function Detail(props) {
        let { id } = useParams(); // URL의 /:id 값을 가져옴
        // id 변수에는 "1", "2" 같은 값이 들어옵니다.
      
        // props.shoes 배열에서 id에 맞는 상품을 찾아 보여줌
        // (id는 문자열이므로 숫자로 변환 필요)
        let product = props.shoes.find(item => item.id == id);
      
        return (
          <div>
            <h4>{product.title}</h4>
            <p>{product.content}</p>
          </div>
        );
      }
      

3. 컴포넌트 생명주기: useEffect

useEffect는 React 컴포넌트가 화면에 나타나거나(mount), 사라지거나(unmount), 업데이트(update)될 때 특정 코드를 실행할 수 있게 해주는 훅입니다.

import { useEffect, useState } from 'react';

function MyComponent() {
  useEffect(() => {
    // 1. 재렌더링마다 실행됨 (Mount + Update)
    console.log('컴포넌트가 렌더링되었습니다.');
  });

  useEffect(() => {
    // 2. Mount시 1회만 실행됨
    // (예: 처음 로드될 때 서버에서 데이터 가져오기)
    console.log('컴포넌트가 처음 마운트되었습니다.');
  }, []); // <-- 두 번째 인자로 빈 배열(Dependency Array) 전달

  useEffect(() => {
    // 3. Unmount시 1회 실행됨 (Cleanup 함수)
    // (예: 컴포넌트가 사라질 때 타이머 해제 등)
    return () => {
      console.log('컴포넌트가 언마운트됩니다.');
    }
  }, []);

  return <div>내 컴포넌트</div>;
}

4. 서버와 통신 (AJAX): axios

React 앱에서 서버와 데이터를 주고받을 때(AJAX) fetch를 사용하거나, 더 편리한 axios 라이브러리를 주로 사용합니다.

  1. 설치:
    npm install axios
    
  2. GET 요청 (데이터 가져오기):
    서버에 데이터를 요청할 때 사용합니다. useEffect와 함께 사용하여 컴포넌트가 마운트될 때 데이터를 가져오는 경우가 많습니다.
    import axios from 'axios';
    
    // ...
    
    // 버튼 클릭 시 데이터 가져오기
    <button onClick={() => {
      axios.get('https://codingapple1.github.io/shop/data2.json')
        .then((result) => {
          // 요청 성공 시
          console.log(result.data); // 서버가 보낸 데이터
        })
        .catch((error) => {
          // 요청 실패 시
          console.error('데이터를 가져오는 데 실패했습니다:', error);
        });
    }}>데이터 요청</button>
    
  3. POST 요청 (데이터 보내기):
    서버에 데이터를 전송할 때(예: 로그인, 회원가입) 사용합니다.
    axios.post('https://서버URL/login', {
      username: 'kim',
      password: '123'
    })
    .then((result) => {
      console.log('전송 성공:', result.data);
    });
    
  4. 동시 요청:
    여러 개의 요청을 동시에 보내고, 모든 요청이 완료되었을 때 처리할 수 있습니다.
    Promise.all([
      axios.get('https://서버URL/data1'),
      axios.get('https://서버URL/data2')
    ])
    .then(([result1, result2]) => {
      // 두 요청이 모두 성공했을 때 실행
      console.log('데이터 1:', result1.data);
      console.log('데이터 2:', result2.data);
    });
    

4부: 고급 상태 관리

useState로 상태를 관리하는 것이 기본이지만, 앱의 규모가 커지면 여러 컴포넌트가 동일한 상태를 공유해야 하는 복잡한 상황이 발생합니다.

1. 전역 상태 관리: Redux Toolkit

Redux는 모든 컴포넌트가 공유하는 전역 상태 저장소(Store)를 만들어 상태 관리를 용이하게 합니다.

  1. 설치:
    npm install @reduxjs/toolkit react-redux
    
  2. store.js 셋팅:
    src 폴더에 store.js 파일을 만들고 아래 코드를 작성합니다. 이 파일이 상태(state)들을 보관하는 저장소입니다.
    // src/store.js
    import { configureStore } from '@reduxjs/toolkit';
    
    export default configureStore({
      reducer: {
        // 여기에 state들을 등록합니다. (예: user: userSlice.reducer)
      }
    });
    
  3. index.js 셋팅:
    index.js에서 앱 전체를 <Provider>로 감싸고, 위에서 만든 store를 주입합니다.
    // index.js
    import { Provider } from 'react-redux';
    import store from './store.js'; // 방금 만든 store.js
    
    root.render(
      <React.StrictMode>
        <Provider store={store}>
          <BrowserRouter>
            <App />
          </BrowserRouter>
        </Provider>
      </React.StrictMode>
    );
    
    이제 앱 내의 모든 컴포넌트가 Redux store에 접근할 수 있게 되었습니다.

2. 서버 상태 관리: React Query

React Queryaxios 같은 AJAX 요청을 더욱 쉽고 강력하게 관리해 주는 라이브러리입니다. 특히 서버에서 받아온 데이터(서버 상태) 관리에 특화되어 있으며, 캐싱, 실시간 업데이트 등을 자동으로 처리해 줍니다.

  1. 설치: (v3 기준)
    npm install react-query@3 --legacy-peer-deps
    
  2. 기본 사용법 (useQuery):
    useQuery는 데이터를 가져오는(GET) hook입니다.
    import { useQuery } from 'react-query';
    import axios from 'axios';
    
    function UserProfile() {
      // useQuery('작명', '데이터 가져오는 함수')
      let result = useQuery('userData', () =>
        axios.get('https://codingapple1.github.io/userdata.json')
          .then((a) => { return a.data })
      );
    
      // result 객체에는 다양한 상태가 포함됩니다.
      if (result.isLoading) return <div>로딩 중...</div>;
      if (result.error) return <div>에러 발생!</div>;
    
      // 데이터 로딩 성공 시
      return <div>사용자 이름: {result.data.name}</div>;
    }
    
    useQuery는 'userData'라는 이름으로 데이터를 캐싱하며, 다른 컴포넌트에서 동일한 이름으로 useQuery를 호출하면 서버에 재요청하지 않고 캐시된 데이터를 즉시 반환하여 성능을 향상시킵니다.