[파이썬] FastAPI - 메모 앱 프로젝트 1: 초기 설정, DB 연동
이전 내용
[파이썬] 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
가장 빠른 풀스택을 위한 플라스크 & FastAPI
다음 내용
[파이썬] FastAPI - 메모 앱 프로젝트 2: CRUD 구현
이전 내용 [파이썬] FastAPI - 메모 앱 프로젝트 1: 초기 설정, DB 연동이전 내용 [파이썬] FastAPI - 성능 개선 팁이전 내용 [FastAPI] 미들웨어(middleware) - 3: GZip이전 내용 [FastAPI] 미들웨어(middleware) - 2: CORS
puppy-foot-it.tistory.com