[파이썬 Projects]/<파이썬 웹개발>

[파이썬] FastAPI - 메모 앱 프로젝트 1: 초기 설정, DB 연동

기록자_Recordian 2025. 5. 9. 11:17
728x90
반응형
이전 내용
 

[파이썬] FastAPI - 성능 개선 팁

이전 내용 [FastAPI] 미들웨어(middleware) - 3: GZip이전 내용 [FastAPI] 미들웨어(middleware) - 2: CORS이전 내용 [FastAPI] 미들웨어(middleware) - 1: TrustedHostMiddleware이전 내용 [FastAPI] 캐싱(caching)이전 내용 [FastAPI]

puppy-foot-it.tistory.com


메모 앱 만들기 프로젝트

파이썬과 FastAPI 프레임워크를 사용하여 실제로 작동하는 웹 애플리케이션을 만들어본다.

 

[주요 목표 및 과정]

  • 기본적인 웹 개발 프로세스 이해
  • 데이터베이스 연동: PostgreSQL을 활용하여 CRUD 구현
  • 사용자 인증 구현: SessionMiddleware 인증 방식을 통해 사용자 인증 구현
  • 상태 관리: FastAPI의 비동기 처리 방식을 활용하여 사용자 상태를 효율적으로 관리
  • MVC 패턴 적용: 모델, 뷰, 컨트롤러를 구분하여 프로젝트 구성
  • API 중심의 애플리케이션 완성

[메모 앱 주요 기능]

  • 사용자 등록 및 로그인: 사용자가 자신의 계정을 생성하고, 이를 통해 로그인
  • 메모 작성 및 관리: 로그인 후 메모를 작성하고, 이를 저장, 조회, 수정, 삭제 할 수 있다.
  • 토큰 기반 인증: SessionMiddleware를 사용하여 사용자의 로그인 상태를 관리하고 보안 강화
  • 프론트엔드: HTML, CSS, 자바스크립트 활용

프로젝트 기본 구조 설정

◆ 파이썬 가상환경

파이썬 라이브러리 간 버전 충돌을 방지하기 위해 가상환경을 사용하는 것을 권장한다. 이는 각 프로젝트가 서로 다른 라이브러리 요구 사항을 가질 때 유용하며, 프로젝트별로 독립적인 파이썬 환경을 제공한다.

conda create -n <환경명> python=<버전>

필자의 경우, 기존에 FastAPI를 위해 사용하던 가상환경을 그대로 사용할 것이므로, 가상환경 생성은 생략한다.

 

◆ 프로젝트 기본 폴더 구조

프로젝트 구조는 초반이므로, 기본 폴더 구조로 시작한다. 먼저, 프로젝트를 위한 폴더를 생성하고, 그 안에 백엔드 코드가 작성될 main.py 와 해당 코드를 실행하여 서버를 실행하는 명령문이 담긴 run.bat 파일을 만든다.

run.bat에는 Uvicorn을 사용하여 애플리케이션을 실행할 명령어를 작성하고, 추후 서버 실행 시에는 main.py 터미널에서 run.bat를 입력하여 실행하면 된다.

uvicorn main:app --reload

프로젝트 구조 내의 파일 및 하위 폴더들은 프로젝트가 진행됨에 따라 추가 생성 및 수정될 예정이다.


Jinja2 템플릿 사용

기본 프로젝트 구조에 템플릿을 추가한다. 이 프로젝트에서는 Jinja2 템플릿 엔진을 사용하여 HTML 템플릿을 렌더링한다.

Jinja2 템플릿 엔진을 사용할 것이므로, 만약 설치가 되어 있지 않다면 설치해 준다.

conda install jinja2

 

그리고 templates 라는 폴더를 생성하고, 그 안에 home.html 템플릿 파일을 생성한다.

 

[home.html]

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>메모 앱에 오신 것을 환영합니다!</title>
</head>
<body>
    <h1>메모 앱에 오신 것을 환영합니다!</h1>
    <p>간단한 온라인 메모장 애플리케이션 입니다.</p>
</body>
</html>

 

◆ FastAPI에서 템플릿 렌더링

이제 FastAPI 애플리케이션에서 루트('/') 경로에 대한 뷰 함수를 작성하여 Jinja2 템플릿을 렌더링한다.

 

[main.py]

from fastapi import FastAPI, Request
from fastapi.templating import Jinja2Templates

app = FastAPI()

templates = Jinja2Templates(directory="templates")

@app.get('/')
async def read_root(request: Request):
    return templates.TemplateResponse('home.html', {"request": request})

▶ 루트 URL에 대한 요청이 있을 때 home.html 템플릿을 렌더링하여 사용자에게 보여준다.

 

◆ 추가 라우팅 설정

프로젝트의 확장성을 위해 main.py의 기존 코드 아래 'About' 페이지를 추가한다. 

@app.get('/about')
async def about():
    return {"message": "메모 앱 소개 페이지 입니다."}

데이터베이스 연동

 

◆ PostgreSQL 설치

이제 PostgreSQL 데이터베이스를 연동해 본다.

PostgreSQL이 설치 되어 있지 않다면, 아래의 링크를 참고하여 다운로드 한다.

 

[SQL] PostgreSQL 다운로드 하기

PostgreSQL 란? PostgreSQL은 오픈 소스 객체-관계형 데이터베이스 관리 시스템(ORDBMS)으로, 많은 기능과 뛰어난 성능, 유연성을 제공하는 데이터베이스이다. [주요 특징]객체-관계형 데이터베이스: Postg

puppy-foot-it.tistory.com

 

◆ 데이터베이스 생성 (SQL Shell)

PostgreSQL를 이용한 데이터베이스를 생성하기 위해 SQL Shell을 켜고, 데이터베이스를 생성한다.

CREATE DATABASE memo_app;

 

◆ FastAPI 애플리케이션에 PostgreSQL 연동하기

데이터베이스를 생성했으므로, FastAPI 애플리케이션과 연동하는 작업을 진행해 줘야 하는데, 그 전에 데이터베이스 연동을 위한 라이브러리를 설치해 준다. (main.py의 터미널에서 아래 명령어 입력)

conda install sqlalchemy psycopg2

psycopg2는 PostgreSQL과 파이썬을 연결해준다.

SQLAlchemy는 SQL 데이터베이스와의 상호작용을 위한 ORM 라이브러리이다.

 

설치가 완료된 후 main.py 에서 SQLAlchemy 및 데이터베이스를 사용하여 PostgreSQL에 연결하고 모델을 정의한다.

from fastapi import FastAPI, Request, Depends
from fastapi.templating import Jinja2Templates
from sqlalchemy.orm import sessionmaker, Session
from sqlalchemy import create_engine, Table, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from pydantic import BaseModel
import psycopg2

app = FastAPI()
templates = Jinja2Templates(directory="templates")

# 데이터베이스 URL 설정
# postgresql://user명:비밀번호@host이름/db이름
DATABASE_URL = "postgresql://postgres:1234@localhost/memo_app" # 실무에서는 노출되지 않는 것이 좋음

# SQLAlchemy 설정
engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()

# 메모 테이블 정의, 필요한 칼럼 생성
class Memo(Base):
    __tablename__ = 'memo'
    id = Column(Integer, primary_key=True, index=True) # 정수형, PK 설정
    title = Column(String(100)) # 제목, 문자열
    content = Column(String(1000)) # 내용, 문자열

# pydantic 사용하여 데이터 검증 수행
class MemoCreate(BaseModel):
    title: str
    content: str

def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

Base.metadata.create_all(bind=engine)

@app.get('/')
async def read_root(request: Request):
    return templates.TemplateResponse('home.html', {"request": request})

# 'About' 페이지 추가
@app.get('/about')
async def about():
    return {"message": "메모 앱 소개 페이지 입니다."}

 

★ SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

이 코드의 목적은 특정 설정(자동 커밋 및 자동 플러시 제어 등)을 가진 SQLAlchemy의 세션을 생성하여, 데이터베이스와의 연결을 조직화하는 것이다. SessionLocal을 사용하여 새 세션을 생성하면, 이 설정이 적용된 세션이 반환되므로 애플리케이션의 데이터베이스 트랜잭션을 보다 유연하게 관리할 수 있다.

 

1. sessionmaker: 새 세션 객체 생성
sessionmaker는 SQLAlchemy에서 제공하는 함수로, 새 세션 객체를 생성하기 위해 사용된다. 이 함수는 주어진 설정에 따라 세션 클래스(여기서는 SessionLocal)를 반환한다.


2. autocommit: 트랜잭션 관리를 수동으로 제어할 수 있게 하여 데이터의 무결성을 높인다.
autocommit 인자는 기본적으로 False로 설정되어 있다. 이는 데이터베이스 트랜잭션이 명시적으로 커밋되지 않는 한 자동으로 데이터가 커밋되지 않도록 한다. 즉, 세션 내에서 실행된 모든 변경 사항은 명시적으로 commit() 메소드를 호출해야만 데이터베이스에 반영된다.  

 

3. autoflush: 유연한 쿼리 작성과 성능 관리를 위해 자주 사용되지 않도록 설정
autoflush는 기본적으로 True로 설정되어 있다. 이 설정이 활성화되면, 세션 내에서 쿼리가 실행되기 전에 현재 세션의 변경 사항이 자동으로 데이터베이스에 반영된다. autoflush=False로 설정하면, 사용자가 명시적으로 flush()를 호출해야 저장된 변경 사항이 데이터베이스에 반영된다.
유연한 쿼리 작성과 성능 관리를 위해 자주 사용되지 않도록 설정한다. 세션이 너무 자주 데이터베이스에 접근하는 것을 방지하여 성능을 개선할 수 있다.

 

4. bind: 세션이 특정 데이터베이스와 이를 통한 쿼리 수행
bind 인자는 세션에 연결할 데이터베이스 엔진을 지정한다. 이 엔진은 데이터베이스와의 연결 정보를 포함하고 있어야 한다. 여기서는 engine이라는 변수를 통해 데이터베이스와 연결된 엔진을 지정하고 있다.


★ Base.metadata.create_all(bind=engine): SQLAlchemy에서 데이터베이스 테이블 생성

애플리케이션이 처음 실행될 때 데이터베이스의 테이블 구조가 없을 경우, 이 코드를 통해 필요한 테이블을 자동으로 생성할 수 있다. 따라서 모델 클래스를 정의하기만 하면, 코드 한 줄로 데이터베이스 구조를 손쉽게 반영할 수 있다.

1. Base: 모델 클래스의 메타데이터와 구조 관리
Base는 SQLAlchemy의 선언적 설정을 위해 정의된 클래스다. 이 클래스는 데이터베이스 모델 클래스들이 상속받는 기본 클래스로, 모델 클래스의 메타데이터와 구조를 관리한다.
Base는 declarative_base() 함수를 통해 생성되며, 이를 통해 ORM(Object-Relational Mapping) 방식을 적용할 수 있다.

 

2. metadata: 데이터베이스 테이블, 컬럼, 제약조건 등 정의된 모든 모델 정보를 담고 있는 객체
metadata는 SQLAlchemy에서 데이터베이스의 구조와 관련된 정보를 담고 있는 객체다. 이 메타데이터는 데이터베이스 테이블, 컬럼, 제약조건 등 정의된 모든 모델 정보들을 포함한다.
각 모델 클래스는 Base를 통해 메타데이터에 등록되며, 이 정보를 통해 테이블 구조와 관계를 파악할 수 있다.

 

3. create_all(): 메타데이터에 정의된 모든 테이블을 데이터베이스에 생성

이 메소드를 호출할 때, 주어진 데이터베이스 엔진(여기서는 engine)에 연결하여 테이블을 생성한다.
bind 인자에 데이터베이스 엔진을 전달하며, 이를 통해 어떤 데이터베이스에 테이블을 생성할지 지정한다.


서버 실행 및 테이블 생성 확인

 

main.py 터미널에서 run.bat를 실행하고, SQL Shell을 켠다.

# 데이터베이스 리스트 보기
\l

# 특정 데이터베이스 접속
\c db명

# 해당 데이터베이스 내 테이블 보기
\dt

# 테이블 조회
SELECT * FROM 테이블명;

 

해당 데이터베이스(memo_app) 내에 memo 라는 테이블과 id, title, content 라는 컬럼이 잘 생성된 것을 확인할 수 있다.

 

 

여기까지 FastAPI와 데이터베이스를 연동하고, 테이블 생성 및 해당 테이블에 칼럼을 생성하는 것까지 진행되었다.

이제 CRUD 기능을 구현하여 사용자가 메모를 생성, 조회, 수정 및 삭제를 할 수 있도록 한다.


[참고]

https://puppy-foot-it.tistory.com/793

https://allna.tistory.com/31

가장 빠른 풀스택을 위한 플라스크 & FastAPI


다음 내용

 

[파이썬] FastAPI - 메모 앱 프로젝트 2: CRUD 구현

이전 내용 [파이썬] FastAPI - 메모 앱 프로젝트 1: 초기 설정, DB 연동이전 내용 [파이썬] FastAPI - 성능 개선 팁이전 내용 [FastAPI] 미들웨어(middleware) - 3: GZip이전 내용 [FastAPI] 미들웨어(middleware) - 2: CORS

puppy-foot-it.tistory.com

 

728x90
반응형