욜로가 서비스는 도메인이 매우 간단하여 각 API 간에 접근하는 테이블이 매우 단순하다. 러닝크루 관련 API 일 경우 러닝크루 테이블만 접근하고, 참여자 관련 API 일 경우 러닝크루 및 참여자 테이블을 접근한다. 러닝크루에 참여자가 속해있는 구조이지만 러닝크루 자체의 기능 또한 존재하기 때문에 이러한 경우에는 참여자 테이블에 전혀 접근할 필요가 없다.
하지만 러닝크루 기능들 중에서 참여자 정보를 조회해야 하는 경우가 있다. 바로 ‘러닝크루 수정’ 기능이다. 러닝크루 기능들에는 생성, 조회, 수정, 삭제, 시작, 종료 등이 있다. 생성 시에도 참여자 정보를 저장해야 하지만 이는 필수적인 과정이므로 배제하고, 그 외의 기능에서는 러닝크루 자체의 정보에만 접근하면 처리할 수 있는 기능이기 때문에 러닝크루 테이블에만 접근한다. 하지만 러닝크루 수정 시에는 검증해야 하는 과정들이 많다.
대부분의 검증 과정에서는 러닝크루 테이블의 정보만으로 검증이 가능하나, Capacity(수용 인원) 를 검증할 때에는 참여자 테이블의 접근이 필요하다.
러닝크루 수정을 제외하고는 모든 과정에서 러닝크루 테이블에만 접근하면 되기 때문에 RunningCrew 와 Participants 의 FetchType 은 기본값인 LAZY
로 설정되어 있다. 즉, 수용 인원에 대한 검증을 수행하려 할 때 Participants 테이블에 SELECT 쿼리문을 실행한다는 의미이다.
Hibernate: # 러닝크루 테이블 조회
select
r1_0.id,
r1_0.archived,
r1_0.archived_at,
r1_0.arrival,
r1_0.capacity,
r1_0.created_at,
r1_0.deadline,
r1_0.departure,
r1_0.description,
r1_0.implemented_end_date,
r1_0.implemented_start_date,
r1_0.member_id,
r1_0.scheduled_end_date,
r1_0.scheduled_start_date,
r1_0.status,
r1_0.title,
r1_0.updated_at
from
running_crew r1_0
where
r1_0.id=?
and r1_0.archived
Hibernate: # 참여자 테이블 조회
select
v1_0.running_crew_id,
v1_0.id,
v1_0.archived,
v1_0.archived_at,
v1_0.created_at,
v1_0.member_id,
v1_0.status,
v1_0.updated_at
from
participant v1_0
where
v1_0.running_crew_id=?
Hibernate: # 러닝크루 테이블 수정
update
running_crew
set
archived=?,
archived_at=?,
arrival=?,
capacity=?,
created_at=?,
deadline=?,
departure=?,
description=?,
implemented_end_date=?,
implemented_start_date=?,
member_id=?,
scheduled_end_date=?,
scheduled_start_date=?,
status=?,
title=?,
updated_at=?
where
id=?
다른 API 와 비교해서 조회 시 쿼리문이 하나 더 실행된다는 점, 러닝크루 자체의 기능인데 참여자 테이블에 접근해야 한다는 점을 이유로 역정규화를 적용하기로 하였다.
정규화란 데이터의 중복을 최대한 줄이기 위해 테이블을 작은 단위로 나누는 방식이다. 역정규화는 반대로 중복 데이터를 허용하여 쓰기 성능은 낮아지지만 조회 성능을 높일 수 있다. 러닝크루 참여자에 대해 역정규화를 적용시켜본다면, 러닝크루 테이블에 ‘현재 참여중인 사용자의 수’ 컬럼을 추가하여 러닝크루에 참여 또는 탈퇴할 때 이에 대한 데이터를 같이 관리하는 것이다. 조회 성능은 높아지겠지만, 데이터를 중복적으로 저장하는 만큼 데이터의 무결성을 항상 지키도록 주의해야 한다.
Hibernate: # 러닝크루 테이블 조회
select
r1_0.id,
r1_0.archived,
r1_0.archived_at,
r1_0.arrival,
r1_0.capacity,
r1_0.created_at,
r1_0.deadline,
r1_0.departure,
r1_0.description,
r1_0.implemented_end_date,
r1_0.implemented_start_date,
r1_0.member_id,
r1_0.number_of_participants,
r1_0.scheduled_end_date,
r1_0.scheduled_start_date,
r1_0.status,
r1_0.title,
r1_0.updated_at
from
running_crew r1_0
where
r1_0.id=?
and r1_0.archived
Hibernate: # 러닝크루 테이블 수정
update
running_crew
set
archived=?,
archived_at=?,
arrival=?,
capacity=?,
created_at=?,
deadline=?,
departure=?,
description=?,
implemented_end_date=?,
implemented_start_date=?,
member_id=?,
number_of_participants=?,
scheduled_end_date=?,
scheduled_start_date=?,
status=?,
title=?,
updated_at=?
where
id=?
실행되는 쿼리문 | |
---|---|
역정규화 전 | - 러닝크루 테이블 조회 |