지금까지 살펴 본, Frontend에 Backend를 연동 시키는 동작의 기본을 정리해 본다. 물론 여기서 Web scrapping이나 다른 기능과 연동하는 작업들이 크지만, 좋은 시작점이 된다는 것을 파악했다. 그 내용을 정리해 보자.

전체 구성 요약

  • Frontend: React + Vite + Tailwind CSS v4
  • Backend: FastAPI + SQLite + SQLAlchemy
  • 기능 요약:
    • 과제 목록 조회 (ProjectList)
    • 과제 등록/수정 (ProjectForm)
    • DB 연동 (등록된 과제 저장/수정/삭제)
    • API 연동 (CORS, RESTful)

✅ 3단계: 과제 화면 구성

📌 파일 생성

  • src/pages/ProjectList.tsx
  • src/pages/ProjectForm.tsx
  • src/App.tsx 라우팅 설정

📌 라우팅 프롬프트

import { BrowserRouter, Routes, Route } from "react-router-dom";
import ProjectList from "./pages/ProjectList";
import ProjectForm from "./pages/ProjectForm";

export default function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<ProjectList />} />
        <Route path="/form" element={<ProjectForm />} />
        <Route path="/form/:id" element={<ProjectForm />} />
      </Routes>
    </BrowserRouter>
  );
}

✅ 4단계: 백엔드 FastAPI 구축

📌 FastAPI 설치

pip install fastapi uvicorn sqlalchemy

📌 main.py 예시

python

CopyEdit

from fastapi import FastAPI, Depends, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from sqlalchemy.orm import Session
from database import SessionLocal, engine, Base
from models import Project as ProjectModel
from pydantic import BaseModel
from typing import List

# 데이터베이스 테이블 생성
Base.metadata.create_all(bind=engine)

# FastAPI 앱 생성
app = FastAPI()

# CORS 설정 (React 개발 서버와 연동)
app.add_middleware(
    CORSMiddleware,
    allow_origins=["http://localhost:5173"],  # 필요시 도메인 추가
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# DB 세션 의존성
def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

# Pydantic 모델 정의
class ProjectBase(BaseModel):
    title: str
    schedule: str
    url: str
    leader: str
    startTime: str
    endTime: str
    interval: str

class ProjectCreate(ProjectBase):
    pass

class ProjectOut(ProjectBase):
    id: int

    class Config:
        orm_mode = True

# API 라우터

@app.post("/projects", response_model=ProjectOut)
def create_project(project: ProjectCreate, db: Session = Depends(get_db)):
    db_project = ProjectModel(**project.dict())
    db.add(db_project)
    db.commit()
    db.refresh(db_project)
    return db_project

@app.get("/projects", response_model=List[ProjectOut])
def list_projects(db: Session = Depends(get_db)):
    return db.query(ProjectModel).all()

@app.get("/projects/{project_id}", response_model=ProjectOut)
def get_project(project_id: int, db: Session = Depends(get_db)):
    project = db.query(ProjectModel).filter(ProjectModel.id == project_id).first()
    if not project:
        raise HTTPException(status_code=404, detail="Project not found")
    return project

@app.put("/projects/{project_id}", response_model=ProjectOut)
def update_project(project_id: int, updated: ProjectCreate, db: Session = Depends(get_db)):
    project = db.query(ProjectModel).filter(ProjectModel.id == project_id).first()
    if not project:
        raise HTTPException(status_code=404, detail="Project not found")
    for key, value in updated.dict().items():
        setattr(project, key, value)
    db.commit()
    db.refresh(project)
    return project

@app.delete("/projects/{project_id}")
def delete_project(project_id: int, db: Session = Depends(get_db)):
    project = db.query(ProjectModel).filter(ProjectModel.id == project_id).first()
    if not project:
        raise HTTPException(status_code=404, detail="Project not found")
    db.delete(project)
    db.commit()
    return {"ok": True}

model.py

from sqlalchemy import Column, Integer, String
from database import Base

class Project(Base):
    __tablename__ = "projects"

    id = Column(Integer, primary_key=True, index=True)
    title = Column(String)
    schedule = Column(String)
    url = Column(String)
    leader = Column(String)
    startTime = Column(String)
    endTime = Column(String)
    interval = Column(String)

database.py

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, declarative_base

DATABASE_URL = "sqlite:///./projects.db"

engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False})
SessionLocal = sessionmaker(bind=engine, autoflush=False, autocommit=False)
Base = declarative_base()

📌 실행

uvicorn main:app --reload

✅ 5단계: DB 모델, CRUD API 구성

📌 SQLite + SQLAlchemy 모델 정의 (예: Project 모델)

📌 주요 API

  • GET /projects: 목록 조회
  • POST /projects: 등록
  • GET /projects/{id}: 상세 조회
  • PUT /projects/{id}: 수정
  • DELETE /projects/{id}: 삭제

✅ 6단계: 프론트엔드 → 백엔드 연동

  • ProjectList.tsx에서 API 호출 후 리스트 렌더링
  • ProjectForm.tsx에서 등록/수정 처리 후 목록으로 라우팅

📌 예시

fetch("http://localhost:8000/projects", { method: "POST", ... })

``


✅ 7단계: UX 향상 + 기능 추가

  • 과제 클릭 시 수정 가능
  • 삭제 기능 추가
  • 기본값 설정 (06:00, 21:00, 1시간)

🧾 최종 상태 요약

구분 구현 완료 항목
UI Tailwind 기반 List + Form
기능 과제 CRUD
API FastAPI 기반 REST API
DB SQLite + SQLAlchemy
연동 React ↔ FastAPI 연결
배포 (추후 단계로 가능: Docker, Cloud Run 등)

 

+ Recent posts