SQLModel 자체가 비동기를 대단히 지원하지도 않아서 의미있는 내용을 담고 있지 않다.
그냥.. 그렇다 기대 노노
SQLModel을 사용하는 코드를 비동기로 다시 작성하다보니
이 라이브러리에서 비동기 프로그래밍이 좀 어렵다는 사실을 알았다.
아직 todo list에서 구현 예정 이라는 말 뿐이고, 좀 기다려야 할 것같다.
그래서 업데이트가 되기 전에 어떻게 비동기를 센스있게 다룰지 고민한다.
1. Model 클래스에서 해당 필드를 명시적으로 selectin or join으로 지정하기
class GameScreenshot(CreatedAtMixin, UpdatedAtMixin, SQLModel, table=True):
__tablename__: str = "game_screenshot"
id: int | None = Field(default=None, primary_key=True)
steam_file_id: int = Field(sa_column=Column(BigInteger(), unique=True))
url: str = Field(max_length=2048)
game_id: int = Field(foreign_key="game.id")
game: Game = Relationship(sa_relationship_kwargs={"lazy": "selectin"})
class Quiz(CreatedAtMixin, UpdatedAtMixin, SQLModel, table=True):
__tablename__: str = "quiz"
id: int | None = Field(default=None, primary_key=True)
screenshots: list[GameScreenshot] = Relationship(
link_model=QuizScreenshotLink, sa_relationship_kwargs={"lazy": "selectin"}
)
@property
def game(self) -> Game:
return self.screenshots[0].game
조회할때 쿼리는 이렇게 나온다.
— 조회
SELECT
quiz.updated_at,
quiz.created_at,
quiz.id
FROM quiz
WHERE quiz.created_at >= ? AND quiz.created_at <= ?
— screenshot 조회
SELECT
quiz_1.id AS quiz_1_id,
game_screenshot.updated_at AS game_screenshot_updated_at,
game_screenshot.created_at AS game_screenshot_created_at,
game_screenshot.id AS game_screenshot_id,
game_screenshot.steam_file_id AS game_screenshot_steam_file_id,
game_screenshot.url AS game_screenshot_url,
game_screenshot.game_id AS game_screenshot_game_id
FROM quiz AS quiz_1
JOIN quiz_screenshot_link AS quiz_screenshot_link_1
ON quiz_1.id = quiz_screenshot_link_1.quiz_id
JOIN game_screenshot
ON game_screenshot.id = quiz_screenshot_link_1.screenshot_id
WHERE quiz_1.id IN (?, ?, ?, ?, ?)
— game 조회
SELECT
game.id AS game_id,
game.updated_at AS game_updated_at,
game.created_at AS game_created_at,
game.steam_id AS game_steam_id,
game.name AS game_name,
game.kr_name AS game_kr_name
FROM game
WHERE game.id IN (?, ?, ?, ?, ?)
- 장점
- 기존 코드에서 손댈곳이 별로 없다
- 퀴즈를 가져올땐 항상 스크린샷을 가져와야 함
- 단점: 퀴즈만 조회하고 싶었는데 줄줄이 소세지처럼 가져오게됨
2. sql 구문을 만들때 옵션으로 지정하기
stmts = (
select(Quiz)
.where(Quiz.created_at >= start_datetime, Quiz.created_at <= end_datetime)
.options(selectinload(Quiz.screenshots)) # type: ignore
)
rs = await self._session.exec(stmts)
return rs.all()
- 장점: 필요힌 데이터만 가져올 수 있다
- 단점: 다른 곳에서 예기치 못한 implicit i/o오류가 나올 수 있다
결론은 아래를 택했다.
결국 내가 비동기를 택한 이유는 빠른 처리였는데, 왕쿼리 전략을 쓴다면 의미가 퇴색되는 것 같기 때문이다.
예기치 못한 오류는 테스트를 통해 검증하겠다. (아니면 lazy: raise 전략도 있다)
'프로그래밍 > 스팀 게임 퀴즈' 카테고리의 다른 글
# 2 프로젝트 설계에 대한 고민 (0) | 2024.01.15 |
---|---|
#14 프론트 엔드 구축 (0) | 2024.01.11 |
# 12 백엔드 코드를 비동기로 바꾸다. (0) | 2024.01.08 |
#8 HttpUrl vs str (0) | 2023.12.30 |
#7 테스트 코드 내 세션 관리 (0) | 2023.12.29 |