겨울 방학 때 연동 했던건데 이제 쓰네,, 기억날 때 바로바로 쓸걸 반성합니다
Fastapi에서 데이터베이스를 관리하는 방법을 먼저 알아본 후, PostgreSQL 연동하는 방법을 알아보자 🤓
PostgreSQL를 선택한 이유는?
PostgreSQL 강력한 관계형 데이터베이스 관리시스템(RDBMS)이다. 복잡한 쿼리, 확장 가능성, 다양한 데이터 타입 지원(특히 json) 등의 기능을 제공하기에 선택했다.
Fastapi에서 데이터베이스를 사용하는 방법 --> 모델로 데이터베이스 관리하기
Django에 비해 fastapi는 데이터베이스와의 통합을 직접적으로 관리하지 않지만, Python에서 사용 가능한 여러 데이터베이스 라이브러리와 잘 호환된다. fastapi에서 DB를 관리하는 파일은 주로 2개이다.
- database.py 파일: 데이터베이스와 관련된 설정을 하는 파일이다.
- models.py 파일: 모델 클래스들을 정의할 파일이다.
그럼 일일히 SQL 쿼리를 입력해야 할까? 데이터베이스를 사용하려면 SQL 쿼리라는 질의를 작성하고 실행하는 과정이 필요하다. 이때 ORM을 이용하면 파이썬 문법만으로 데이터베이스를 다룰 수 있다.
ORM(Object-Relational Mapping)
ORM은 객체-관계 매핑을 의미하며, 구체적으로 데이터베이스의 테이블을 객체로, 행을 객체의 인스턴스로, 컬럼을 객체의 속성으로 매핑한다. 모델을 사용하면 내부에서 SQL 쿼리를 자동으로 생성해 주어서 직접 작성하지 않아도 된다. 즉 파이썬만 알아도 데이터베이스 처리를 할 수 있다!
그 중 Python에서 가장 인기 있는 ORM 라이브러리 중 하나인 Alembic을 사용할 것이다.
Alembic은 SQLAlchemy의 구조를 사용하여 데이터베이스 스키마 변경(즉, 마이그레이션)을 버전 관리하는 방법을 제공한다
FastAPI의 의존성 주입(Dependency Injection)
반복되는 데이터베이스 세션 관리 작업을 자동화하고 코드를 깔끔하게 유지할 수 있다. 이 기능을 통해 데이터베이스 세션을 생성하고, API 요청이 완료된 후에 자동으로 세션을 종료하는 과정을 쉽게 구현할 수 있다. 우리가 사용하는 API는 데이터베이스를 사용해야 하기 때문에 이러한 패턴이 반복될거니까 의존성 주입을 통해서 깔끔하게 처리하는 것이다.
아래와 같이 의존성 주입을 위한 세션 생성기 함수를 사용한다.
SessionLocal 인스턴스를 사용하여 각 요청마다 데이터베이스 세션을 생성하고 요청이 처리되면 자동으로 세션을 닫는 함수를 생성한다. 그리고 get_db 함수를 경로 작업에 의존성으로 주입하여 데이터베이스 세션을 필요로 하는 모든 경로에서 사용할 수 있다.
#database.py
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from dotenv import load_dotenv
import os
load_dotenv()
DATABASE_URL = os.getenv("DATABASE_URL")
engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
의존성 주입을 사용하는 예시
from .database import get_db
@app.get("/questions/")
async def read_questions(db: Session = Depends(get_db)):
questions = db.execute(models.Question.select()).scalars().all()
return questions
Depends(get_db)는 FastAPI에게 함수가 호출될 때 get_db 함수에서 생성된 데이터베이스 세션을 db 매개변수로 사용하도록 지시한다. 함수가 호출 완료 후, 생성된 세션은 자동으로 종료된다.
이제 본격적으로 PostgreSQL과 연동하는 방법을 알아보자
1. PostgreSQL 데이터베이스 생성하기
연동하기 위해서는 먼저 DB 생성부터 해줘야한다.
로컬에서 DB를 만들 수도 있지만 나는 공용 DB를 사용하기 위해 GCP에서 인스턴스를 만들고 그 위에 postgresql를 설치해서 그것을 fastAPI와 연동해주었다.
구글클라우드플랫폼에 인스턴스를 만드는 방법은 구글링을 하면 잘 나옴으로 ... skip
인스턴스에서 postgresql를 접속하는 방법부터 작성하겠다
인스턴스를 만든 후 접속해주기 위해 로컬 터미널에서 키 생성
ssh-keygen -t rsa -f ~/.ssh/DBKEY -C wsw3727@gmail.com -b 4096
키 복붙하고 메타데이터에 저장
cat ~/.ssh/DBKEY.pub
권한변경
chmod 400 ~/.ssh/DBKEY
서버 접속
ssh -i ~/.ssh/DBKEY wsw3727@서버ip
postgresql 설치
sudo apt update
sudo apt install postgresql postgresql-contrib
postgresql.conf 수정: 서버가 모든 IP 주소에서의 연결을 수신하도록 설정해야 한다
sudo vim /etc/postgresql/12/main/postgresql.conf
아래와 같이 수정
listen_addresses = '*'
pg_hba.conf 수정: 클라이언트가 데이터베이스에 접근할 수 있도록 수정
sudo vim /etc/postgresql/12/main/pg_hba.conf
아래와 같이 수정
# TYPE DATABASE USER ADDRESS METHOD
host all all 0.0.0.0/0 md5
재시작
sudo systemctl restart postgresql
GCP 방화벽 규칙에서 5432 포트를 열어주고 netstat -atnl을 입력하면 5432가 아래와 같이 나와야함!
그 후 아래와 같이 데이터베이스를 생성해주면 된다
psql -U postgres
create database bubblow_db;
GRANT ALL PRIVILEGES ON DATABASE bubblow_db TO hansol;
2. FastAPI와 Postgresql 연동하기
1. Alembic 설정 및 초기화
드디어 연동이다,, 이제 서버로 돌아와서 터미널에 아래와 같이 alembic을 설치해주고 초기화를 해준다.
pip install alembic
alembic init migrations
그럼 alembic.ini파일이 생기는데 그 파일 안에 63줄을 아래와 같이 아까 생성한 접속 주소로 바꾸어준다
*주의* alembic.ini 파일은 .gitignore에 올려놓자.. 내 db가 털리지 않도록
sqlalchemy.url = postgresql://user:password@postgresserver/db
2. 마이그레이션 스크립트 생성
alembic revision --autogenerate -m "message"
그럼 스크립트 파일이 mygrations/versions에 생긴다 여기서 우리가 또 해야할 일! mygrations/env.py 를 수정해야 한다. 22번째 줄을 아래와 같이 수정하면 된다
import models
target_metadata = models.Base.metadata
3. 마이그레이션 반영
alembic upgrade head
4. database.py 수정
.env에 내 database_url을 올려놓고 아래와 같이 파일을 수정하면 끝이다
import os
load_dotenv()
DATABASE_URL = os.getenv("DATABASE_URL")
engine = create_engine(DATABASE_URL)
끝!
fastapi에서 데이터베이스를 다루는 방법, 그리고 연동을 알아보았다. 사실 보이는건 간단(?)하지만 마이그레이션 버전을 관리하는 데 시행착오가 있었다. 그럴 때는 그냥 db를 drop하고 다시 create를 해줬는데 drop하지 않고도 버전을 관리하는 방법을 좀 더 시도해봐야겠다,,
'졸업프로젝트' 카테고리의 다른 글
[졸업프로젝트 회고] 아쉬운점과 개선점 (1) | 2024.07.10 |
---|---|
[MLOps PipLine] model serving 하는 방법 (feat. FastAPI, docker) (3) | 2024.06.29 |
[졸업 프로젝트 Bubblow] 네이버뉴스 크롤링 하기 (4) | 2024.04.07 |
[졸업 프로젝트] Bubblow 소개 (7) | 2024.03.29 |