본문 바로가기
Programming

쇼핑몰 관리자 페이지에 쓰이는 코드 모음

by 디자이너 슈 2025. 2. 16.

관리자 페이지를 구현하기 위한 전체 코드(프론트엔드, 백엔드, API-재고 관리 시스템을 기반으로)
관리자는 상품 추가/수정/삭제주문 내역 확인이 가능해야 함.


1. 시스템 아키텍처

[React Admin Frontend] ← HTTP → [Flask Backend API] ←→ [메모리 DB]

2. 백엔드 (Python Flask)

(1) server.py 확장 (관리자 API 추가)

from flask import Flask, request, jsonify
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

# 임시 DB (상품 & 주문 데이터)
products = {
    "A": { "id": "A", "name": "상품 A", "price": 10000, "stock": 10 },
    "B": { "id": "B", "name": "상품 B", "price": 20000, "stock": 5 }
}

orders = []

# ----------------------------
# 관리자 전용 API
# ----------------------------

# 1. 모든 상품 조회 (GET)
@app.route('/api/admin/products', methods=['GET'])
def get_all_products():
    return jsonify(list(products.values()))

# 2. 상품 추가 (POST)
@app.route('/api/admin/products', methods=['POST'])
def add_product():
    data = request.get_json()
    product_id = data['id']

    if product_id in products:
        return jsonify({ "success": False, "error": "이미 존재하는 상품 ID" }), 400

    products[product_id] = data
    return jsonify({ "success": True, "product": data })

# 3. 상품 수정 (PUT)
@app.route('/api/admin/products/<product_id>', methods=['PUT'])
def update_product(product_id):
    if product_id not in products:
        return jsonify({ "success": False, "error": "상품 없음" }), 404

    data = request.get_json()
    products[product_id].update(data)
    return jsonify({ "success": True, "product": products[product_id] })

# 4. 상품 삭제 (DELETE)
@app.route('/api/admin/products/<product_id>', methods=['DELETE'])
def delete_product(product_id):
    if product_id not in products:
        return jsonify({ "success": False, "error": "상품 없음" }), 404

    del products[product_id]
    return jsonify({ "success": True })

# 5. 모든 주문 내역 조회 (GET)
@app.route('/api/admin/orders', methods=['GET'])
def get_all_orders():
    return jsonify(orders)

if __name__ == '__main__':
    app.run(debug=True, port=5000)

3. 프론트엔드 (React)

(1) 관리자 페이지 컴포넌트 구조

src/
├── AdminProductList.js   // 상품 목록 & 삭제
├── AdminAddProduct.js    // 상품 추가 폼
├── AdminEditProduct.js   // 상품 수정 폼
├── AdminOrderHistory.js  // 주문 내역
└── App.js                // 라우팅

(2) src/AdminProductList.js

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

function AdminProductList() {
  const [products, setProducts] = useState([]);

  // 상품 데이터 불러오기
  useEffect(() => {
    axios.get('http://localhost:5000/api/admin/products')
      .then(res => setProducts(res.data))
      .catch(err => console.error("상품 불러오기 실패:", err));
  }, []);

  // 상품 삭제
  const handleDelete = (productId) => {
    if (window.confirm("정말 삭제하시겠습니까?")) {
      axios.delete(`http://localhost:5000/api/admin/products/${productId}`)
        .then(() => {
          setProducts(products.filter(p => p.id !== productId));
        })
        .catch(err => console.error("삭제 실패:", err));
    }
  };

  return (
    <div>
      <h2>상품 관리</h2>
      <table>
        <thead>
          <tr>
            <th>ID</th>
            <th>이름</th>
            <th>가격</th>
            <th>재고</th>
            <th>액션</th>
          </tr>
        </thead>
        <tbody>
          {products.map(product => (
            <tr key={product.id}>
              <td>{product.id}</td>
              <td>{product.name}</td>
              <td>{product.price}원</td>
              <td>{product.stock}</td>
              <td>
                <button onClick={() => handleDelete(product.id)}>삭제</button>
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

export default AdminProductList;

(3) src/AdminAddProduct.js

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

function AdminAddProduct() {
  const [formData, setFormData] = useState({
    id: "",
    name: "",
    price: 0,
    stock: 0
  });

  const handleSubmit = (e) => {
    e.preventDefault();
    axios.post('http://localhost:5000/api/admin/products', formData)
      .then(res => {
        alert("상품 추가 성공!");
        setFormData({ id: "", name: "", price: 0, stock: 0 });
      })
      .catch(err => alert("추가 실패: " + err.response?.data.error));
  };

  return (
    <div>
      <h2>상품 추가</h2>
      <form onSubmit={handleSubmit}>
        <input
          placeholder="상품 ID"
          value={formData.id}
          onChange={(e) => setFormData({ ...formData, id: e.target.value })}
          required
        />
        <input
          placeholder="상품명"
          value={formData.name}
          onChange={(e) => setFormData({ ...formData, name: e.target.value })}
          required
        />
        <input
          type="number"
          placeholder="가격"
          value={formData.price}
          onChange={(e) => setFormData({ ...formData, price: e.target.value })}
          required
        />
        <input
          type="number"
          placeholder="재고"
          value={formData.stock}
          onChange={(e) => setFormData({ ...formData, stock: e.target.value })}
          required
        />
        <button type="submit">추가</button>
      </form>
    </div>
  );
}

export default AdminAddProduct;

(4) src/AdminOrderHistory.js

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

function AdminOrderHistory() {
  const [orders, setOrders] = useState([]);

  useEffect(() => {
    axios.get('http://localhost:5000/api/admin/orders')
      .then(res => setOrders(res.data))
      .catch(err => console.error("주문 불러오기 실패:", err));
  }, []);

  return (
    <div>
      <h2>주문 내역</h2>
      <ul>
        {orders.map((order, index) => (
          <li key={index}>
            {order.productId} - {order.quantity}개
          </li>
        ))}
      </ul>
    </div>
  );
}

export default AdminOrderHistory;

(5) src/App.js (라우팅)

import React from 'react';
import { BrowserRouter as Router, Route, Link, Routes } from 'react-router-dom';
import AdminProductList from './AdminProductList';
import AdminAddProduct from './AdminAddProduct';
import AdminOrderHistory from './AdminOrderHistory';

function App() {
  return (
    <Router>
      <div>
        <nav>
          <Link to="/">상품 관리</Link>
          <Link to="/add">상품 추가</Link>
          <Link to="/orders">주문 내역</Link>
        </nav>

        <Routes>
          <Route path="/" element={<AdminProductList />} />
          <Route path="/add" element={<AdminAddProduct />} />
          <Route path="/orders" element={<AdminOrderHistory />} />
        </Routes>
      </div>
    </Router>
  );
}

export default App;

4. 실행 방법

  1. 백엔드 실행
  2. python server.py # http://localhost:5000
  3. 프론트엔드 실행
  4. cd frontend npm start # http://localhost:3000

5. 기능 설명

기능 API 엔드포인트 HTTP 메서드
상품 전체 조회 /api/admin/products GET
상품 추가 /api/admin/products POST
상품 수정 /api/admin/products/{id} PUT
상품 삭제 /api/admin/products/{id} DELETE
주문 내역 조회 /api/admin/orders GET

6. 추가 고려 사항

  1. 인증/인가: JWT 토큰을 이용한 관리자 권한 검증 추가 필요
  2. 유효성 검사: 프론트/백엔드 모두에서 입력값 검증 강화
  3. 페이징: 대량 데이터 처리 시 페이지네이션 구현
  4. 실시간 업데이트: WebSocket을 이용한 실시간 동기화
  5. 데이터베이스: SQLite, MySQL 등 영구 저장소 연동

이 코드를 기반으로 관리자 페이지를 완성하고 필요에 따라 기능을 확장해보세요! 🔧