설계 방법
일단 필요하겠다 싶은 데이터를 브레인스토밍 형식으로 노트에 적었다.
이때 네이밍과 타입, 외래키에 대해서 전혀 생각하지 않고 그냥 생각이 나오는 대로 작성했다.
그러고 나서 타입을 결정하고 테이블 단위로 묶으며 외래 키를 고려해 스키마를 구성했다.
마지막으로 사용자 시나리오들을 여러 개 작성해서, 어떤 요청이 어디에 들어가는지 데이터의 흐름을 파악하려 노력했다.
이 과정에서 많은 수정이 이루어졌고, 정규화와 비정규화에 대해 많이 고민했다.
또한 JOIN 쿼리가 반드시 필요한 상황인지 비용을 따져가며,
이 요청이 정말 빈번하게 일어나는 요청인가?
에 대해 고려하며 최대한 호출 비용을 줄이는 데에 신경 썼다.
NoSQL을 도입하고 싶었지만, 이번 프로젝트 취지상 RDB만 사용하여 이 같은 테이블이 나오게 되었다.
회고
JOIN vs 정규화
처음 설계할 당시 room 테이블의 latitude, longitude, cleaning_fee, commission 컬럼이
room_info 테이블로 따로 떨어져 있었다.
일차적으로 맨 처음 화면에서 보이는 정보들을 room 테이블에,
사용자의 이벤트가 발생했을 때 보이는 정보들을 room_info 테이블에 분류한 것이 까닭이었다.
하지만 이렇게 비정규화하면 사용자의 이벤트가 발생했을 때 JOIN 쿼리의 사용이 불가피했다.
그래서 요청의 빈도수를 생각해 보았다.
처음 화면이 랜더링 될 때 room 테이블에서 SELECT 쿼리 (+ 데이터 필터링)
VS
사용자가 단일 숙소 클릭 시 room_info 테이블을 JOIN 하는 쿼리
전자가 1번이면 후자는 N번이다.
하여 JOIN이 N번 일어나는 건 성능상 좋지 않기 때문에 테이블을 정규화한 것이 지금의 상태이다.
실제로 30,000개의 요청을 넣은 실험 결과,
같은 조건에서 JOIN 쿼리의 Duration은 0.029 sec,
정규화한 테이블에서의 SELECT 쿼리의 Duration은 0.015 sec이었다.
하지만 지나고 보니 사용자의 이벤트를 한 가지 간과한 것을 깨달았다.
사용자가 지도를 드래그 & 드랍할 때마다 지도 범위 내의 숙소를 다시 랜더링 해야 하는 요구사항이 있었다.
이렇게 되면 1 : N의 요청이 아니라, N : M의 요청이 되기 때문에 다시 생각할 필요가 있었다.
사용자가 드래그 & 드랍으로 지도 이동하면 room 테이블에서 SELECT 쿼리 (+데이터 필터링)
VS
사용자가 단일 숙소 클릭 시 room_info 테이블을 JOIN 하는 쿼리
이렇게 두고 보면 전자가 압도적으로 요청이 많기 때문에,
테이블을 비정규화 시키고 JOIN을 날리는 게 비용이 적게 든다고 생각한다.
리팩토링을 위해 일단 드래그 & 드랍하면 쿼리 날리고 랜더링 하는 부분을 작성하고,
테이블을 비정규화해서 JOIN 쿼리를 날려야겠다.
JOIN vs 정규화 2
사용자가 어떤 숙소를 예약하면 예약 당시의 정보들을 스냅샷을 찍듯이 reservation 테이블에 저장한다.
그리고 예약 내역 페이지에 접속하면 reservation 테이블로 JOIN 쿼리를 날려
room 테이블의 숙소 이름, 정보 등의 데이터를 가져온다.
여기서 고민이었던 것이,
예약 당시 정보들을 숙소 이름, 정보 등의 데이터까지도 reservation 테이블에 저장할지였다.
이를 저장하면 room 테이블과 데이터 중복이 일어나고,
저장하지 않으면 JOIN 쿼리를 날려야 하기 때문에 고민이었다.
이번에도 마찬가지로 해당 요청이 빈번하게 일어나는지 생각해보았다.
한 명의 사용자가 그렇게 많은 수의 숙소를 예약할까?
생각해보니 그렇지 않을 것 같아서 JOIN의 부담보다 reservation 테이블의 용량 증가가 부담스럽게 느껴졌다.
그래서 나온 지금의 설계가 나왔다.
하지만 지나고 보니 이를 실제 서비스로 확장했을 때 생기는 변수로 인해 고려할게 늘어났다.
지금은 없는 요구사항이지만,
만약 숙소 사장님이 숙소의 정보를 변경한다면?
정직하지 않은 사장님이 숙소 정보에 사기를 친다면 이를 조회해서 적발할 수 있을까?
생각해보니 애초에 숙소 정보가 변경될 것이라 생각하지 않고 설계하였고,
현 상황에서 이 같은 문제들에 대처하게 된다면 아예 테이블 구조를 좀 바꿔야겠다고 생각이 들었다.
다음 프로젝트부터는 꼭 요구사항에 국한되지 않고,
실제 서비스에서 일어날 수 있는 경우를 조금씩 고려하면서 설계를 해보자.
'회고' 카테고리의 다른 글
웹 개인 프로젝트 회고 1 (0) | 2022.09.25 |
---|---|
[네이버 부스트캠프 웹·모바일 7기] 챌린지 수료 후기 (0) | 2022.08.16 |
[코테 후기] 2022 토스 NEXT (0) | 2022.08.16 |
[네이버 부스트캠프 웹·모바일 7기] 지원부터 합격까지 (0) | 2022.07.12 |
[코테 후기] 2022 현대모비스 알고리즘 경진대회 (0) | 2022.07.04 |
댓글