[소프티어 부트캠프] 지도(공유) 기능에 대한 고찰
현대 ICT 평가원들께 받은 피드백
지도(공유) 기능에서 주변 사용자들이 많은 경우 서버에서 어떤 처리를 하는지?
-> 짧은 프로젝트 기간과 부족한 실력으로 인해 이 부분까지 고려하지 못하였고 부트캠프 과정이 끝난 이후 리팩토링 과정에서 해당 문제에 대해 해결책을 찾아본다.
기존 구현 방식
Redis Geo 을 이용하여 사용자들의 경위도 좌표 정보를 저장한다. 주변 사용자의 정보를 조회하는 API 요청이 왔을 때 사용자의 위치를 기준으로 반경 3km 에 위치한 사용자들의 id를 조회한다. 사용자 id 값을 활용하여 mysql 에 저장된 Todo(할 일) 데이터를 조회한 후 카테고리별 할 일 랭킹 데이터로 가공한다. 그렇게 가공된 카테고리별 Todo(할 일) 랭킹 정보와 주변 사용자 위치 정보를 클라이언트 측에 전달한다.
문제점
1. 반경 3km 이내 주변 사용자가 많다면 서버의 부담은 늘어난다. 요청 처리 속도가 늘어날 것이고 많은 데이터를 메모리에 올려야 하므로 Out of Memory 문제가 발생할 수 있다. 프론트엔드 측에서 많은 사용자 데이터를 랜더링해야 하므로 역시 성능에 문제가 생긴다.
2. 1번 문제의 해결책을 강구하기 앞서 카테고리 별 Todo(할 일)에 대한 랭킹 정보에 대한 정책의 변화가 필요에 보인다. 1번 문제를 해결하기 위해서는 3km 반경에 위치한 모든 사용자를 대상으로 카테고리 별 Todo에 대한 랭킹 정보를 가공하는 것은 불가능하다.
구상
1) 위치 정보를 저장하는 DB 변경(redis -> mysql)
변경이유로는
- 사용자 수가 많아지면, Redis로 저장 시 메모리 요구량이 커서 비용 문제가 발생한다.
- 장애 발생 시 데이터가 손실될 가능성이 존재한다.(AOF 파일을 통해서 복구를 할 수 있으나 레디스의 장점이 사라진다.)
- 지금 생각해보면 레디스에 저장되는 데이터의 셩격이 캐싱 데이터 아니면 세션 데이터(중요하지 않은, 없어져도 되는 데이터)라고 생각되는데 위치 데이터는 그런 성격보다는 영구적으로 저장되어야 하는 데이터에 더 가깝다는 생각이 들었다.
변경 내용으로는
mysql 의 spatial 데이터 타입을 활용하여 기존 Member 테이블에 속성을 추가한다.
2) 주변 사용자들의 카테고리별 할 일 랭킹을 미리 저장된 형태의 집계 테이블로 저장
요청이 왔을 때 주변 사용자들의 할 일 데이터로부터 카테고리별 할 일 랭킹 데이터를 가공하여 응답하는 것은 시간 비용의 소모가 큰 작업이라고 생각이 든다. 요청이 왔을 때 해당 데이터를 생성하는 것이 아닌 이미 존재하는 데이터를 조회하기 위한 집계 테이블을 생성한다.
집계테이블의 구성은 다음과 같다.
CREATE TABLE cell_category_count (
cell_id varchar(6) NOT NULL,
category_id bigint NOT NULL,
count int NOT NULL DEFAULT 0,
created_at datetime(6) DEFAULT NULL,
updated_at datetime(6) DEFAULT NULL,
PRIMARY KEY ('cell_id', 'category_id')
);
cell_id 는 geohash 길이 7(셀 영역의 너비는 153m X 153m) 를 사용한다. cell_id 와 category_id 복합키를 기본키로 사용한다.
3) 주변 사용자가 많을 경우 부하를 줄이기 위한 전략
대표적인 전략을 클러스터링 전략 과 우선순위 전략 두 가지가 존재한다.
클러스터링 전략은
지도 상의 사용자를 거리나 격자 단위로 그룹화하여, 일정 영역의 다수의 사용자가 있을 경우 한 개의 클러스터 마커로 표시한다. 확대(줌인)하는 경우 더 작은 클러스터 마커나 개별 마커로 표시한다.
우선순위 전략은
지도 상의 사용자 중 일부만 선별하여 보여주는 방식이다.
두 가지 전략 중 선택한 전략은 우선순위 전략이다. 클러스터링 전략의 경우 사용자가 많은 경우 확대(줌인)를 하여 개별 마커가 표시될 때 사용자의 할 일 정보를 확인할 수 있다. 우선순위 전략은 사용자 중 일부만 보여줌으로써 노출된 사용자의 할 일 정보를 확인할 수 있어 클러스터링 전략보다 사용성이 더 좋다고 판단된다.
우선순위 전략에서 보여줄 사용자를 결정하는 기준이 있어야 한다. 현재로서는 사용자를 유의마한 지표가 없다고 생각이 들지만 저장된 순서를 기준으로 보여줄 사용자를 선택한다면 공평하지 못하다는 생각이 든다. 따라서 Member 테이블의 updated_at 이라는 컬럼을 이용하여 최근 업데이트 한 사용자를 선택하여 보여준다.updated_at 이라는 컬럼을 사용한 이유는 Member 테이블에서 변경되는 데이터의 비중이 가장 큰 데이터가 위치 정보이기 때문이다.
사용자를 선별하는 시점의 기준은 일단은 100명으로 정한다. 기능 개발을 끝낸 후 사용성과 성능으로 합리적인 기준 값을 찾아간다.