웹(WEB)/파이썬(Python)

[Python] FastAPI Windows 웹 서버 구현

마달랭 2025. 1. 12. 03:05
반응형

개요

FastAPI를 활용한 Windows 환경에서의 웹 서버를 구현해 보자

간단한 토이 프로젝트 형식으로 로컬 환경에서 클라이언트, 웹 서버, DB 서버를 구현할 예정이다.

 

[사용 툴]

  • 웹 클라이언트 : vue
  • 웹 서버 : FastAPI
  • DB 서버 : PostgreSQL

FastAPI의 장점인 비동기 처리를 구현하는게 목적이다.

또한 트랜잭션 처리에서 ACID를 정확하게 지키는 것 또한 구현하고자 한다.

 

vue와 관련된 내용은 이전 Flask 프로젝트를 진행하며 사용했던 그대로 사용할 예정이다.

따라서 vue관련 내용은 다루지 않을 것이며 HTTP 요청 시 URL에서 포트번호만 변경해 주면 된다.

 

[Python] Flask 클라이언트 GET 요청 처리

 

[Python] Flask 클라이언트 GET 요청 처리

개요이번엔 클라이언트로 부터 요청을 플라스크에 전달하고, 요청 내용을 토대로 클라이언트에 값을 반환해 보자진행 순서는 다음과 같다.웹 클라이언트에서 Flask로 요청을 전달요청을 라우트

zzzz955.tistory.com

 

 

프로젝트 설정

FastAPI 실습을 진행할 프로젝트를 생성해 준다.

나는 파이참 IDE 환경에서 서버를 구현할 예정이다.

python -m venv venv

 

프로젝트 생성 후 가상화를 설정해 준다.


.\venv\Scripts\activate

 

가상화 폴더가 생성되었다면 가상화를 진행해 준다.


python -m pip install --upgrade pip

 

pip의 버전을 최신 버전으로 업그레이드 해준다.


pip install fastapi uvicorn psycopg2 sqlalchemy

 

FastAPI와 PostgreSQL 연동을 위해 필요한 라이브러리를 설치한다.


 pip freeze > .\requirement.txt

 

필요한 모듈 정보를 requirement.txt에 저장해 준다. (선택)

 

 

models.py

데이터베이스 모델 정의 관련 로직을 작성해 준다.

from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

# 데이터베이스 연결 URL (PostgreSQL에 연결)
SQLALCHEMY_DATABASE_URL = "postgresql://postgres:password@localhost/exampledb"

# SQLAlchemy 기본 설정
Base = declarative_base()

# 세션 만들기
engine = create_engine(SQLALCHEMY_DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)


# 테이블 모델 정의
class Item(Base):
    __tablename__ = 'item'

    id = Column(Integer, primary_key=True, index=True, autoincrement=True)
    name = Column(String(80), nullable=False)
    description = Column(String(200), nullable=False)


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

 

  • SQLAlchemy를 사용하여 item 테이블 모델을 정의한다.
  • 데이터베이스 URL에 맞게 username, password를 설정해야 한다.
  • 실제 데이터베이스와 동일한 이름과 타입으로 모델을 정의해 주어야 한다.

 

 

main.py

FastAPI 서버에 클라이언트의 CRUD 요청을 처리할 로직을 구현해 보자

from fastapi import FastAPI, HTTPException, Depends
from sqlalchemy.orm import Session
from models import SessionLocal, Item
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel

# FastAPI 앱 초기화
app = FastAPI()

# CORS 설정 추가
origins = ["*"]  # 모든 도메인 허용

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,  # 허용할 오리진 (프론트엔드 주소)
    allow_credentials=True,
    allow_methods=["*"],  # 모든 HTTP 메서드 허용
    allow_headers=["*"],  # 모든 헤더 허용
)

# Pydantic 모델 정의
class ItemCreate(BaseModel):
    name: str
    description: str

class ItemUpdate(BaseModel):
    name: str
    description: str

class ItemResponse(BaseModel):
    id: int
    name: str
    description: str

# 데이터베이스 세션을 만드는 함수
def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

# 1. 모든 항목 조회
@app.get("/items", response_model=list[ItemResponse])
def read_items(db: Session = Depends(get_db)):
    items = db.query(Item).all()
    return items

# 2. 특정 id 조회
@app.get("/items/{item_id}", response_model=ItemResponse)
def read_item(item_id: int, db: Session = Depends(get_db)):
    item = db.query(Item).filter(Item.id == item_id).first()
    if item is None:
        raise HTTPException(status_code=404, detail="Item not found")
    return item

# 3. 아이템 생성
@app.post("/items", response_model=ItemResponse)
def create_item(item: ItemCreate, db: Session = Depends(get_db)):
    db_item = Item(name=item.name, description=item.description)
    db.add(db_item)
    db.commit()
    db.refresh(db_item)
    return db_item

# 4. 아이템 수정
@app.put("/items/{item_id}", response_model=ItemResponse)
def update_item(item_id: int, item: ItemUpdate, db: Session = Depends(get_db)):
    db_item = db.query(Item).filter(Item.id == item_id).first()
    if db_item is None:
        raise HTTPException(status_code=404, detail="Item not found")

    db_item.name = item.name
    db_item.description = item.description
    db.commit()
    db.refresh(db_item)
    return db_item

# 5. 아이템 삭제
@app.delete("/items/{item_id}")
def delete_item(item_id: int, db: Session = Depends(get_db)):
    db_item = db.query(Item).filter(Item.id == item_id).first()
    if db_item is None:
        raise HTTPException(status_code=404, detail="Item not found")

    db.delete(db_item)
    db.commit()
    return {"message": f"Item with id {item_id} deleted"}

 

 

실행

파이참 터미널에서 FastAPI서버를 실행해 준다.


위와 같이 uvicorn.exe main:app --reload를 통해 서버를 시작할 수 있다.

이후 vue에서 HTTP요청을 보내면 웹 서버가 관련 URL을 받아 특정 메서드를 실행시킨다.

FastAPI의 기본 포트는 8000번을 사용하므로 localhost:8000으로 URL을 요청한다.

 

 

HTTP 요청

1. get요청

 

정상적으로 PostgreSQL에 저장된 데이터를 받아온 것을 확인할 수 있다.


2. post요청


정상적으로 신규 데이터가 추가되었다.


3. PATCH/PUT 요청

 

tempdata에 대한 설명을 변경하였고, 정상적으로 반영되었다.



4. DELETE 요청

 

tempdata2를 삭제 요청하였고, 정상적으로 반영되었다.

 

 

트러블 슈팅

vue에서 웹 서버로 요청을 보내기 위해선 CORS세팅이 되어 있어야 한다.

이는 main.py의 CORS 설정 추가 부분에서 확인할 수 있다.

 

DatabaseURL 설정 시 사용자, 비밀번호, 엔드포인트, db명이 일치해야 한다.

만약 존재하지 않는 사용자거나 비밀번호가 틀릴 경우 오류를 발생시킨다.

또한 엔드포인트가 정확하게 설정되어 있어야 하며 참조할 db 또한 일치해야 한다.

 

테이블의 구조와 FastAPI에 정의된 내용이 일치해야 한다.

테이블 구조가 다를 경우 입력되는 데이터에 따라 어떠한 오류가 발생할지 모른다.

 

클라이언트로 부터 전달 받은 파라미터 형식이 일치해야 한다.

주로 json형식으로 파라미터가 전달될 텐데 이를 BaseModel을 통해 타입을 명시해 줘야 한다.

 

 

기타

현재 구현 내용은 로컬 환경에서 간단한 CRUD를 진행하는 토이 프로젝트로 구현되어 있다.

필요에 따라 클라이언트, 웹 서버, DB 서버를 분리하여 작동해야 한다.

또한 웹 서버 로직을 필요에 맞게 모듈화 해주면 유지보수 측면에서 크게 도움을 받을 수 있다.

엔드포인트와 사용자 등 보안에 유의해야 할 항목 또한 추가적으로 고민해야 하는 요소이다.

 

728x90
반응형