728x90
1. 도입
음악인들을 위한 합주실 예약 플랫폼을 설계하면서, 우리는 사용자들이 합주실 이름, 주소, 이용 가능 시간을 기준으로 손쉽게 탐색할 수 있는 기능이 필요하다는 것을 확인했다.
이에 따라, **합주실을 운영하는 관리자(사장님)**가 정보를 등록하고, **클라이언트(사용자)**가 다양한 기준으로 합주실을 탐색할 수 있도록 하는 모듈을 설계하게 되었다.
2. 설계 목표
- 운영자 입장: 합주실의 이름, 주소, 연락처, 운영시간, 방(Room) 정보 등을 등록
- 사용자 입장: 특정 시간에 예약 가능한 합주실을, 이름/주소를 기반으로 쉽게 검색
- MVP 우선: 너무 많은 복잡도를 초기에 가져가지 않도록 기능과 구조를 분리하고, 확장 가능한 형태로 시작
3. 초기 고민: 정렬 기준을 어떻게 할 것인가?
초기에는 사용자 편의성을 고려하여 다음과 같은 요구가 있었다:
“지정한 시간대에 예약 가능한 합주실을 가장 위에 보여주고 싶다.”
우리는 이 요구를 충족하기 위해 다음과 같은 기술들을 고민했다:
🔸 Redis Sorted Set
- 예약 가능 여부를 기준으로 studioId에 정렬 score를 부여
- 요청 시간대에 맞는 ZSET을 생성하고 빠르게 정렬 제공
- ✅ 정렬 속도는 빠르지만,
- ⛔️ 시간대마다 ZSET이 계속 쌓이기 때문에 TTL 관리와 일관성 보장이 어려움
🔸 ElasticSearch
- 검색 + 정렬 + 조건 필터링을 모두 해결할 수 있는 궁극기
- ✅ 부분 일치 검색, 거리 기반 정렬 등도 가능하지만
- ⛔️ 운영 복잡도가 커지고, MVP엔 과한 스펙
4. 기술적 현실: 정렬을 구현하면 생기는 문제들
예약 가능 여부는
Room→Slot→TimeManager모듈에 의존
→ 합주실만 보고 판단 불가능실시간 정렬을 구현하려면,
- 모든 방을 기준으로 예약 가능 여부를 계산
- 조건별 Redis ZSET or SearchView를 동기화
→ 캐싱과 동기화 로직 폭발
결국 성능, 일관성, 복잡도에서 모두 비용이 큼
5. 현실적인 선택: 정렬 대신 표기
우리는 결국 정렬 기능은 뒤로 미루고 다음과 같은 현실적인 MVP 선택을 했다.
⏳ "해당 시간에 예약 가능한지 여부만 Boolean으로 표기한다."
| 항목 | 결정 |
|---|---|
| 정렬 기능 | ❌ |
| 예약 가능 여부 표시 | ✅ |
| 이름/주소 기준 정렬 | ✅ |
6. 구현 설명
핵심 모듈: studio-searchview
public class StudioSearchView {
Long studioId;
String studioName;
String area;
Boolean hasParking;
Boolean isAvailable; // 해당 시간 기준 예약 가능한 방이 하나라도 있나?
}
이벤트 기반 갱신 흐름
| 이벤트 | 발생 모듈 | SearchView 갱신 항목 |
|---|---|---|
| studio.updated | Studio 모듈 | 이름, 주차정보 |
| address.updated | AddressService (Kafka) | 지역 필드 |
| room.availability.changed | TimeManager | isAvailable (시간 기반 계산 결과) |
사용자 요청 흐름 (MVP 기준)
- 사용자가 검색 조건 입력: 이름/주소 + 시간 범위
- BFF에서 SearchView 조회
- 조건에 맞는
isAvailable == true인 합주실만 필터링 - 정렬은 이름/주소 기준, 예약 가능 여부는 단순 표기
7. 회고 및 확장 가능성
MVP에서 제한한 부분
| 항목 | 이유 |
|---|---|
| 예약 가능 정렬 | Redis/ElasticSearch 기반 정렬 구조는 과도한 복잡도 |
| 슬롯 전체 캐싱 | 2주치 30분 단위 슬롯 저장은 불가능한 규모 |
| 검색 최적화 | MVP 기준에서는 full-text search도 제외 |
향후 확장 계획
| 기능 | 확장 방법 |
|---|---|
| 시간 기준 정렬 | Redis ZSET 또는 정렬 score 기반 projection |
| 부분 검색 (합주실명) | ElasticSearch 연동 |
| 지역 기반 지도 검색 | 위경도 + Geo Index 추가 |
| 실시간 예약 제한 | TimeManager의 Slot 검증 강화 |
| 유저 평점 기반 정렬 | SearchView에 평점 필드 추가 후 score 연산 |
마치며
“무엇을 만들 것인가”보다 더 중요한 건 “언제 무엇을 만들지 않을 것인가”다.
우리는 복잡한 정렬 기능 대신, 현재 사용자에게 가장 필요한 핵심 기능인 **“예약 가능 여부의 표시”**를 선택했다.
이 판단은 MVP를 빠르게 출시하고, 유저 피드백을 통해 진짜 필요한 확장 방향을 검증하기 위한 전략적 결정이었다.
728x90
'BindProject' 카테고리의 다른 글
| [Backend] Image모듈 개발기 2편: 이미지도 생명주기가 있다면 – 도메인 모델과 상태 설계 (0) | 2025.06.21 |
|---|---|
| [Backend] Image 모듈 개발기 1편: 왜 우리는 직접 이미지 업로드 모듈을 만들었는가? (0) | 2025.06.21 |
| [회고] Refresh Token 전략과 Redis 기반 설계, 그리고 트러블슈팅 회고 (1) | 2025.06.20 |
| [Backend] Auth모듈: JWT 로그아웃 설계와 Redis 기반 블랙리스트 구현 (1) | 2025.06.20 |
| [기획] 추후 목표 :Kafka 기반 이벤트 아키텍처 이식 설계 (0) | 2025.06.19 |