graph-algorithm

1 개의 포스트

kakao

카카오톡 예약하기에서 그려 본 캘린더 (새 탭에서 열림)

카카오톡 예약하기는 카드 목록만으로는 재고와 예약을 한눈에 파악하기 어렵다는 문제를 해결하기 위해 타임 블록형 캘린더를 구현했다. 예약을 시작 시간과 종료 시간에 따라 정렬하고, 겹치는 예약을 그래프로 모델링한 뒤 DFS로 배치 깊이와 확장 가능 범위를 계산했다. 이후 루트 노드 간의 길이 차이로 남는 공간이 생기는 예외까지 보정해 예약 블록을 최대한 빈틈없이 배치했다. ## 캘린더 제작 배경과 요구사항 - 파트너센터의 예약 관리 화면은 예약을 카드 목록으로 보여주고 있었다. - 카드 목록은 많은 예약과 재고를 한눈에 비교하기 어렵다는 불편이 있었다. - 이를 해결하기 위해 예약과 재고를 시간축 위에서 확인할 수 있는 타임 블록형 캘린더를 제작했다. - 주요 요구사항은 다음과 같다. - 하나의 시간대에 최대 10개의 예약이 존재할 수 있다. - 하나의 예약은 최대 6시간을 차지한다. - 예약 블록 사이에 빈 공간을 최소화하면서 최대한 잘 보이게 배치해야 한다. ## 예약 배치 순서 ### 이용 시간이 이른 예약부터 정렬 - 예약이 입력된 순서가 아니라 시작 시간이 빠른 순서대로 배치했다. - 판매자가 하루를 시작할 때 가장 먼저 확인할 가능성이 높은 예약을 왼쪽 위에 배치하기 위한 결정이다. - 사용자의 시선이 일반적으로 왼쪽 위에서 오른쪽 아래로 이동한다는 시각적 우선순위도 고려했다. - 첫 번째 배치 규칙은 **“이용 시간이 이른 순서로 정렬한다”**이다. ### 같은 시간에는 소요 시간이 긴 예약부터 정렬 - 같은 시간대에 여러 예약이 겹치면 소요 시간이 긴 예약을 앞에 배치했다. - 긴 예약이 뒤로 밀리면 앞쪽 예약이 차지한 공간 때문에 긴 블록의 확장이 제한될 수 있다. - 긴 예약을 먼저 배치하면 이후 예약들이 남은 공간을 기준으로 배치되고, 각 예약이 확보할 수 있는 영역을 예측하기 쉬워진다. - 두 번째 배치 규칙은 **“같은 시간 내에서는 소요 시간이 긴 순서로 정렬한다”**이다. ## 예약을 그래프로 모델링 - 단순히 DOM 요소의 위치를 조정하는 대신, 예약 간의 겹침 관계를 그래프로 표현했다. - 각 예약을 그래프의 노드로 만들고, 서로 영향을 주는 예약을 연결했다. - 노드에는 예약 정보와 함께 이전 예약(`prevBooking`), 다음 예약(`nextBooking`) 같은 연결 관계를 저장했다. - 이 구조를 이용하면 예약이 어떤 경로로 연결되어 있고, 어느 정도까지 확장될 수 있는지 계산할 수 있다. ## DFS를 이용한 위치와 확장 범위 계산 - 각 노드에서 DFS를 수행해 다음 정보를 계산했다. - 그래프에서의 깊이 또는 레벨 - 연결된 예약 중 가장 끝에 있는 예약까지의 최대 거리(`maxLength`) - 깊이는 예약 블록의 가로 방향 위치를 결정하는 데 사용된다. - 최대 거리는 해당 예약이 오른쪽으로 얼마나 확장될 수 있는지 판단하는 기준이 된다. - 계산된 값을 바탕으로 각 노드의 다음 UI 속성을 구한다. - `left`: 블록의 시작 위치 - `width`: 블록이 차지할 가로 너비 - 그래프의 가장 왼쪽에 있는 노드부터 기준을 잡아 예약 블록을 배치하고 확장했다. ## 루트 노드 간 길이 차이로 발생한 예외 - 초기 알고리즘은 모든 예약이 연결된 그래프에서도 공간이 남는 경우를 완전히 처리하지 못했다. - 위쪽 루트 노드의 `maxLength`가 더 길고, 아래쪽 루트 노드의 `maxLength`가 짧으면 하위 그래프가 끝까지 확장되지 않았다. - 그 결과 예약 간 연결은 유지되지만 일부 빈 공간이 남는 문제가 발생했다. - 이 문제를 해결하기 위해 다음과 같은 보정 과정을 추가했다. - 현재 노드의 `left + width`보다 다음 노드의 `left`가 크면 두 노드 사이에 확장 가능한 공간이 있다고 판단한다. - 해당 노드와 연결된 예약들을 확인한다. - 여러 개의 빈 공간이 있으면 가장 작은 공간을 기준으로 연결된 노드들의 너비를 확장한다. - 이 과정을 반복해 예약 블록이 가능한 한 빈틈없이 영역을 채우도록 했다. ## 구현 과정에서 얻은 교훈 - 겉보기에는 단순한 UI라도 다양한 입력 데이터와 최악의 배치 상황을 고려해야 한다. - 타임 블록 캘린더는 예약의 정렬, 겹침 처리, 가로 확장, 예외 보정이 결합된 알고리즘 문제에 가깝다. - 그래프와 DFS 같은 자료구조·알고리즘이 실제 프런트엔드 UI 배치 문제를 해결하는 데 직접 활용될 수 있다. - 프런트엔드 개발자는 데이터를 화면에 어떻게 보여줄지 결정하는 책임과 권한을 함께 가진다. - 실제 서비스에서는 초기 알고리즘을 완성형으로 보기보다, 운영 중 발견되는 버그와 새로운 입력 패턴에 맞춰 지속적으로 개선해야 한다. 타임 블록 캘린더를 구현할 때는 먼저 예약을 시작 시간과 지속 시간 기준으로 안정적으로 정렬하고, 겹침 관계를 그래프로 모델링하는 방식이 유용하다. 이후 DFS로 배치 깊이와 확장 범위를 계산하되, 루트별 길이 차이로 생기는 잔여 공간과 같은 예외 케이스를 별도로 검증하는 것이 중요하다.