지난 시간까지 가상환경에 접속해서 JSON 데이터로 API 만들어보고, MariaDB랑 HeidiSQL 설치해서 JSON 데이터를 DB화하는 작업을 했었는데, 이번에는 DB화된 데이터를 FastAPI에 연동시켜서 API로 만드는 작업을 해보았다.😎
나는 분명 햇병아리 FE 개발자인데, 이렇게 점점 풀스택이 되어가나보다..😂
※ Fast API 가상환경 구축과 API 만들기 - https://hjinn0813.tistory.com/140
※ MariaDB, HeidiSQL 설치하기 - https://hjinn0813.tistory.com/141
MariaDB, HeidiSQL 기본 개념과 설치 방법
햇병아리 프론트엔드 개발자의 백엔드 도전은 API 만들기가 끝이 아니었다.
hjinn0813.tistory.com
VS code 원격접속, 가상환경 활성화
Fast API 작업을 SSH 원격접속으로 가상환경에 만들었으니, 이번에도 똑같이 가상환경에 접속해야했다.
가상환경 활성화하는 명령어를 돌아서면 까먹어서 여기에도 기록해둔다.✍
# 가상환경 활성화
source fastapi/bin/activate
SQL 관련 라이브러리 설치
pip install sqlalchemy pymysql
가상환경이 활성화된 상태에서 설치해야 한다.
설치하는 라이브러리들이 어떤 도구인지를 살펴보자면,
SQLAlchemy
파이썬 코드에서 DB와 연결하기 위해 사용한다.
ORM을 통해 SQL문을 python 코드로 작성할 수 있게 해준다.
ORM
Object Relational Mapping. 객체관계 매핑.
데이터베이스 내의 테이블들을 객체화하여 CRUD를 공통된 접근 기법으로 사용할 수 있다.
하나의 객체를 다루기 위해 여러 SQL 쿼리가 사용되니까 프로그램이 커지면 작성해야하는 쿼리도 많아지는데, 반복되는 쿼리를 객체 단위로 생성해놓으면 따로 쿼리를 작성할 필요없이 간접적으로 DB 조작이 가능해진다.
대표적인 ORM 라이브러리는 Python ORM, SQLAlchemy 등이 있다.
Fast API와 MariaDB 연결, 의존성 주입 설정
python-venv/fastapi가 나의 가상환경 디렉토리이고 하위의 app에 모든 파일이 들어있으니, 역시 필요한 파일들을 app 디렉토리에 만들었다. 가장 먼저 Fast API와 MariaDB를 연결하고 의존성 주입을 설정하는 database.py 파일을 만들었다.
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, Session
from fastapi import Depends
# DB 접속 정보 설정
DATABASE_URL = "mysql+pymysql://username:password@IP_address:3306/db_name"
- 일단 기능들을 제대로 사용하기 위한 import와 접속정보 설정이다.
- 첫 줄은 SQLAlchemy 엔진을 생성하여 DB와 연결시키기 위해서,
둘째줄은 SQLAlchemy 세션을 생성하여 DB와 상호작용하며 CRUD 작업을 진행하기 위해서,
셋째줄은 클라이언트의 요청에 따라 세션을 생성 및 종료하기 위해 작성한다. - DB 접속 정보 설정에서 사용자명, 비밀번호, IP 주소, 포트번호, DB 이름은 HeidiSQL에 로그인할 때 입력하는 정보들을 작성한다.
# SQLAlchemy 엔진과 세션 생성
engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
# 의존성 주입 콜백함수
def get_db() -> Session:
db = SessionLocal()
try:
yield db ## 세션 제공
finally:
db.close() ## 세션 종료
- 여기서는 실제로 어떤 데이터를 불러와서 어떻게 작업할지에 대한 내용이 작성된다.
일단 SQLAlchemy 엔진과 세션이 생성되었는데, '세션메이커'라는 메서드 안의 내용은 아래와 같은 의미를 갖고 있다- autocommit=False → 세션에서 쿼리 실행 시 자동으로 변경사항 커밋 해제.
개발자가 코드에서 session.commit()이라고 호출해야 변경사항 적용된다. - autoflush=False → 세션(작업)에서 변경된 내용 DB에 자동 저장 기능 해제
- bind=engine → 세션이 어떤 DB와 연결될지 지정. 사용하려는 DB 엔진이 뭔지 명확하게 알려주는 역할을 한다.
- autocommit=False → 세션에서 쿼리 실행 시 자동으로 변경사항 커밋 해제.
- 그리고 의존성 주입하는 콜백함수를 작성했다.
get_db() 함수는 데이터베이스 Session 객체를 반환하는 타입을 명시한다.
SessionLocal() 메서드를 호출하여 새로운 세션을 생성한다.
try문에서 yield 키워드로 클라이언트 요청 시 세션을 제공하고, finally문에서 db.close()로 종료한다.
데이터베이스 속성 정의
다음으로는 model.py 파일을 만들어서, DB에 어떤 속성이 어떤 데이터 타입을 가지고 있는지를 정의했다.
from sqlalchemy import String, Date, SmallInteger, Integer, Column
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class Player(Base):
__tablename__ = "altos"
id = Column(Integer, primary_key=True, index=True) ## 기본키로 index 번호 설정
name = Column(String, nullable=False)
birthday = Column(Date, nullable=False)
height = Column(SmallInteger)
backNo = Column(SmallInteger)
# 이하 생략
- 역시 가장 먼저 import부터 하면서 시작한다.
첫 줄은 DB에 설정되어있는 MySQL의 데이터 타입을 SQLAlchemy에 맞게 수정해서 불러왔고,
둘째줄은 모델 클래스를 만들기 위한 기본 클래스를 가져오는 부분이다. - 그 다음에 아래의 declarative_base()로 기본 클래스를 생성했다.
- 다음으로는 모델 클래스 생성.
실제 테이블에 입력될 속성들에는 무엇이 있고, 각자 어떤 데이터 타입을 갖고 있는지 설정했다.
여기서 가장 중요한 부분은, 특정 튜플을 식별하기 위한 고유한 값으로 기본키를 반드시 설정해야 한다.
https://hjinn0813.tistory.com/143 - HeidiSQL에서 데이터를 만들면 #라는 속성으로 id가 자동으로 생기길래, 모델 클래스 만들면서 id 가져오라는 코드를 작성하면 #에 있는 값이 자동으로 입력되는줄 알았다. 그런데 #라는 속성은 HeidiSQL 프로그램이 사용자의 편의를 위해 자동으로 만들어주는 거라서, id를 가져오려면 속성을 따로 만들어서 입력해야했다. 자동으로 입력시키는 방법이 있었지만 나는 데이터가 전부 입력된 상태에서 추가적으로 id 속성을 만든거라서 하나씩 직접 입력했다.😅
SQL 기본 개념과 용어 정리
MariaDB과 HeidiSQL에 대해서는 정리했는데 SQL에 대해서는 정리하지 않았다는걸 지금 알았다.
hjinn0813.tistory.com
API 엔드포인트 설정
다음은 api.py 파일에 엔드포인트 설정하기.
이 과정은 지난번 JSON 파일을 API로 만들 때와 코드가 비슷해서 크게 어렵지 않았다.
from fastapi import FastAPI, Depends
from sqlalchemy.orm import Session
from fastapi.middleware.cors import CORSMiddleware
from model import Player
from database import get_db
# FastAPI 어플리케이션 생성
app = FastAPI()
# CORS 설정
app.add_middleware(
CORSMiddleware, ## CORS 설정 적용
allow_origins=["*"], ## 허용할 도메인 리스트
allow_credentials=True, ## 인증 정보 요청 허용
allow_methods=["*"], ## 허용할 HTTP 메서드 리스트
allow_headers=["*"], ## 허용할 헤더 리스트
)
- 역시 import부터 하면서 시작한다.
클라이언트의 요청에 따라 세션을 생성/종료하기 위해 Depends를 가져왔고, sqlalchemy로 세션을 생성했다.
model.py에서 Player 클래스를 가져왔고, database.py에서 실제로 데이터를 불러오는 get_db 함수를 가져왔다.
CORS 설정은 나중에 프론트엔드(React)에서 API로 페이지 제작할 때 에러가 발생할까봐 미리 작성했다.
@app.get("/altos")
def read_altos(db: Session = Depends(get_db)):
altos = db.query(Player).all()
return altos
@app.get("/altos/{player_id}")
def get_detail(player_id: int, db: Session = Depends(get_db)):
altos = db.query(Player).filter(Player.id == player_id).first() # 특정 ID의 선수 조회
if altos is None:
return {"error": "Player not found"}
return altos
- 그리고 드디어 실제로 사용될 API 엔드포인트 생성하기.
- 가장 먼저 /players에 접속했을 때의 설정은,
db는 Session 타입의 변수이고, depends() 메서드로 get_db 함수에서 만든 데이터를 받아온다.
→ Fast API가 Python 3.5 버전의 '타입 힌트'를 기반으로 API 요청과 응답의 데이터 검증을 자동 수행하기 때문에, 변수의 데이터 타입이 명시되어있다.
query() 메서드는 SQLAlchemy라는 ORM으로 특정 테이블에 대한 쿼리문을 생성하고, 이를 기반으로 내부적으로 SQL 명령어를 실행한다. 그리하여 players라는 변수는 앞 줄에서 db 변수에 대해 정의한 내용을 토대로 player 모델 클래스에 해당하는 DB 테이블을 query()로 조회하고 all()로 전부 불러와서 반환한다. 이 부분에서 서버랑 통신해서 데이터를 가져온다. - /players/{player_id}의 경우에는 추가적으로 player_id 변수가 정수형이라고 명시했다.
filter() 메서드로 DB의 아이디와 Player 클래스의 아이디가 일치하는 선수를 찾고,
first()로 필터링된 결과 중에 첫번째 값을 반환한다.
아이디는 중복되지 않는 유니크한 값이라서 조건에 맞는 결과가 하나 뿐일테니 자연스레 특정 선수 1명이 출력된다.
Uvicorn 명령어로 결과 확인하기
# api.py 파일이 있는 디렉토리로 이동
cd fastapi/app
# 포트 열어서 확인하기
uvicorn SQL_api:app --reload --port 8001
# 포트 열면서 디버깅 기록 작성하기
uvicorn SQL_api:app --reload --port 8001 --log-level debug
JSON으로 API 만들 때에도 했던거지만 한번 더 기록한다.
나의 가상환경은 python-venv/fastapi 디렉토리에 있어서 상위 카테고리인 python-venv 위치에서 활성화 시켰다.
SQL_api.py 파일은 python-venv/fastapi/app에 있어서, cd 명령어로 API 파일이 있는 위치로 이동하고 포트를 열었다.
💡 참고로 포트 여는 명령어에서,
--reload는 코드가 바뀔 때마다 서버를 자동으로 다시 시작해달라는 옵션이다.
--log-level debug는 모든 디버깅 정보를 로그(기록)으로 남기겠다는 옵션인데, 이걸 설정하면 백엔드 코드에서 문제가 있을 경우에 vscode 터미널에서 확인할 수 있어서 편리하다.
포트를 열면 JSON 데이터로 API 만들었을 때처럼 브라우저에서 데이터가 정상적으로 보여야하는데, MySQL 서버 접속 권한이 없어서 500 Server Error가 발생했다. 그래서 MySQL 권한 문제를 해결하려고 또 고생을 약간 했는데, 이것까지 여기에 작성하면 분량이 너무 길어지니까 다음 포스팅에서 작성해보겠다!😉
https://hjinn0813.tistory.com/147
MySQL 권한 에러, DB 이관하기
지난 시간까지 Fast API와 MariaDB를 연동시켜서 가상환경에서 MariaDB에 있는 데이터들을 API로 만드는 작업을 했다. 포트를 열었는데 MySQL 권한 에러가 발생했다.
hjinn0813.tistory.com
참고한 글
https://velog.io/@jsyun0412/FastAPI-FastAPI%EC%99%80-DB-%EC%97%B0%EA%B2%B0
[FastAPI] FastAPI와 DB 연결
나는 BERT 감성분석 프로젝트를 진행하며, fast api를 활용하여 DB,백을 구축하였다. 지금 DB 실시간 연동을 위해 다시 코드를 뜯어보는 중인데, Fast API와 DB를 연결하는 방법에 대해 작성해보겠다.
velog.io
'💾 Backend > FastAPI' 카테고리의 다른 글
Fast API에서 비밀번호 검증하기 (0) | 2024.11.11 |
---|---|
Fast API에서 비밀번호 해싱하기 (0) | 2024.11.08 |
DB에 CRUD가 되는 게시판 만들기 - Backend (1) | 2024.11.04 |
Fast API 가상환경 구축하고 API 만들기 (2) | 2024.10.23 |
Fast API 기본 개념 정리 (1) | 2024.10.11 |