[Open WebUI] SCIM 그룹 변환에서 N+1 쿼리를 배치 조회로 제거
PR 링크: open-webui/open-webui#21005 상태: Merged | 변경: +11 / -12
들어가며
SCIM(System for Cross-domain Identity Management)은 사용자와 그룹 정보를 표준화된 형식으로 외부 시스템에 제공하는 프로토콜이다. Open WebUI의 group_to_scim 함수는 내부 그룹 모델을 SCIM 포맷으로 변환하는데, 기존 구현에서는 그룹 멤버 한 명마다 get_user_by_id를 개별 호출하는 전형적인 N+1 쿼리 패턴이 있었다. 그룹 멤버가 100명이면 101개의 쿼리가 발생하는 구조였다.
핵심 코드 분석
Before: 멤버마다 개별 쿼리
member_ids = Groups.get_group_user_ids_by_id(group.id, db) or []
members = []
for user_id in member_ids:
user = Users.get_user_by_id(user_id, db=db) # N번 쿼리
if user:
members.append(
SCIMGroupMember(
value=user.id,
ref=f"{request.base_url}api/v1/scim/v2/Users/{user.id}",
display=user.name,
)
)
After: 단일 배치 조회
member_ids = Groups.get_group_user_ids_by_id(group.id, db) or []
# Batch-fetch all users to avoid N+1 queries
users = Users.get_users_by_user_ids(member_ids, db=db) if member_ids else []
members = [
SCIMGroupMember(
value=user.id,
ref=f"{request.base_url}api/v1/scim/v2/Users/{user.id}",
display=user.name,
)
for user in users
]
왜 이게 좋은가
- 쿼리 수 감소: N+1 쿼리가 단 1개의 SQL
IN절 쿼리로 줄어든다. 멤버가 몇 명이든 데이터베이스 왕복은 한 번이다. - 코드 간결성: for 루프와 조건문이 리스트 컴프리헨션으로 대체되어 의도가 명확해졌다.
- 빈 리스트 가드:
if member_ids조건으로 멤버가 없을 때 불필요한 쿼리 자체를 방지한다.
N+1 문제는 ORM 기반 웹 애플리케이션에서 가장 흔한 성능 함정 중 하나다. 이 PR은 기존에 존재하던 get_users_by_user_ids 배치 메서드를 활용하는 것만으로 문제를 깔끔하게 해결했다.
참고 자료
관련 포스트
PR Analysis 의 다른글
- 이전글 [Grafana Loki] JSON 파서에서 bytes.Runes() 할당을 in-place UTF-8 디코딩으로 제거
- 현재글 : [Open WebUI] SCIM 그룹 변환에서 N+1 쿼리를 배치 조회로 제거
- 다음글 [Open WebUI] DB 쿼리 최적화: 루프 삭제를 벌크 연산으로 교체
댓글