야구로 시작되는 특별한 만남
'캐치미' 는 KBO 야구팬들을 위한 직관 메이트 매칭 웹앱 서비스입니다.
팬들이 신뢰할 수 있는 환경에서 직관 메이트를 찾고, 경기장에서의 경험을 더욱 풍성하게 만드는 서비스입니다.
본 서비스는 KBO 경기 정보 제공, 직관 메이트 매칭, 굿즈 중고 거래 기능을 제공합니다.

- 혼자 야구 직관을 가기 망설여지는 분
- 같은 팀을 응원하는 새로운 팬들과 안전하게 교류하고 싶은 분
- 직관 메이트를 쉽게 찾아보고, 신뢰할 수 있는 환경에서 만나고 싶은 분
- 경기 정보와 날씨를 한눈에 확인하고 싶으신 분
- 직관의 순간을 기록하고, 메이트들과의 추억을 공유하고 싶은 분
- 야구 굿즈를 경기장에서 안전하게 거래하고 싶은 분
- 직관 메이트 매칭 – 취향과 스타일이 맞는 메이트를 찾고, 안전한 실시간 채팅으로 약속을 잡을 수 있어요.
- 스마트한 경기 정보 제공 – KBO 경기 일정, 순위, 현장 날씨까지 한눈에 확인할 수 있어요.
- 신뢰도 높은 프로필 시스템 – 매너 타율 시스템과 응원 스타일 설정으로 나에게 맞는 메이트를 쉽게 찾을 수 있어요.
- 직관 타임라인 – 내가 다녀온 경기의 티켓과 특별한 순간을 사진과 함께 기록할 수 있어요.
- 안전한 굿즈 거래 – 경기장에서의 굿즈 거래를 더 편리하고 안전하게 진행할 수 있어요.
- 지속적인 팬 네트워크 형성 – 팔로우 기능을 통해 한 번 만난 메이트와 지속적으로 소통할 수 있어요.


🚀 메인 페이지 | 👥 메이트 구인글 페이지 | 💬 메이트 채팅 페이지 |
---|---|---|
![]() |
![]() |
![]() |
🏏 굿즈 상품 등록 페이지 | ⚾️ 굿즈 거래 페이지 | 💬 굿즈 거래 채팅 페이지 |
---|---|---|
![]() |
![]() |
![]() |
🛠 3차례에 걸친 채팅 서비스 성능 최적화 - [블로그 기록]
CATCH Mi 프로젝트는 직관 메이트 매칭과 굿즈 중고거래를 핵심 서비스로 제공하며, 두 기능 모두 채팅을 중심으로 이루어집니다.
따라서 채팅 서비스의 성능은 사용자 경험에 직접적인 영향을 미치는 중요한 요소였습니다.
이를 위해 데이터베이스 마이그레이션, 페이지네이션 개선, 캐싱 도입 등 다양한 성능 최적화 작업을 수행하였고, JMeter 성능 테스트를 통해 검증하였습니다.
- 스레드 수: 100
- Ramp-up 시간: 50초
- 요청 횟수: 150회/스레드
- 총 샘플 수: 30,000
지표 | 값 |
---|---|
평균 응답시간 | 592ms |
95% 응답시간 | 736ms |
평균 TPS | 132.7/sec |
지표 | 값 | 개선율 |
---|---|---|
평균 응답시간 | 396ms | |
95% 응답시간 | 577ms | |
평균 TPS | 176.0/sec | 33% ↑ |
지표 | 값 | 개선율 |
---|---|---|
평균 응답시간 | 2ms | |
95% 응답시간 | 4ms | |
평균 TPS | 981.8/sec | 457% ↑ |
- MongoDB 마이그레이션 : TPS 33% 향상
- No-Offset 페이지네이션 + Redis : TPS 457% 추가 향상
- 결론적으로 3차례의 성능 개선을 거치며 기존보다 약 TPS 639.98% 향상
채팅 메시지 조회 속도가 대폭 개선되어 사용자들이 실시간으로 원활한 소통을 보장하여 보다 안정적인 서비스를 제공할 수 있었습니다.
1. 채팅방 이벤트 비동기 처리 — [블로그 기록]
- 채팅 이벤트 전송 로직이 메인 로직과 동기적으로 처리되어 응답 속도가 저하됨
- 비동기 처리 필요성 판단 → 메인 로직과 분리하여 성능 개선
- 트랜잭션 분리 필요 → 이벤트 로직 실패가 메인 로직에 영향을 주지 않도록 고려
- ThreadPoolTaskExecutor 설정 최적화
- EC2(t3a.small) 환경을 고려하여 스레드 풀을 직접 관리
- 효율적인 리소스 활용 및 응답 속도 개선
- 트랜잭션 분리 적용
@TransactionalEventListener
사용 → 메인 로직 커밋 후 이벤트 실행하여 데이터 일관성 보장@Transactional(propagation = Propagation.REQUIRES_NEW)
적용 → 이벤트 트랜잭션을 독립적으로 관리
2. Offset 페이지네이션 조회 성능 문제 — [블로그 기록]
- Offset 기반 페이지네이션 사용 시 후반부 페이지 조회 속도 급격히 저하
- 데이터 양이 많아질수록 Offset이 증가하면서 불필요한 스캔 비용 증가
- MongoDB Compound Index 설정 + No-Offset 페이지네이션 적용
COUNT 쿼리 제거
→ 불필요한 연산 최소화Offset 제거
→ 스캔 비용 절감 및 데이터 정합성 보장
- 조회 성능 개선 결과
- 첫 페이지: ⏳ 200ms → 30ms (약 6.6배 속도 개선)
- 마지막 페이지: ⏳ 400ms → 30ms (약 13.3배 속도 개선)
3. 빈번한 데이터베이스 접근으로 인한 서비스 성능 저하 문제 — [블로그 기록]
- 빈번한 데이터베이스 접근으로 인해 DB 과부하 발생
- 전체적인 서비스 성능 저하 우려
- 캐싱 도입 필요성 판단 → DB 부하 감소를 위한 전략 검토
- No-Offset 페이지네이션 유지 → 데이터 정렬이 가능한 캐싱 스토어 필요
- 채팅 데이터의 정합성 보장 → 일관성 유지가 가능한 캐싱 전략 필요
- Redis Sorted Set 활용 → 전송 시간을 기준으로 채팅 데이터 정렬하여 조회 성능 최적화
- Write-Through + Look-Aside 전략 적용 → 데이터 일관성 유지
- 성능 개선 결과 → 채팅 조회 응답 시간 30ms → 20ms(약 33% 개선)
4. 이기종 MongoDB와 MySQL 분산 트랜잭션 문제 — [블로그 기록]
- MongoDB와 JPA의 트랜잭션을 함께 관리하지 못하는 문제
- Spring의 기본 트랜잭션 매니저는 여러 데이터 소스 간 분산 트랜잭션을 지원하지 않음
- 여러 데이터 소스를 통합하는 방법 검토
ChainedTransactionManager
→ ❌ 정상적인 롤백 보장 불가 & DeprecatedJTA (Java Transaction API)
→ ❌ 설정 복잡 & 성능 오버헤드 발생
- JPA → 선언적 트랜잭션, MongoDB → 프로그래밍 방식 트랜잭션 제어
- TransactionTemplate을 활용하여 트랜잭션을 직접 관리 → 데이터 일관성 확보
5. 채팅 데이터베이스의 성능 및 확장성 문제 — [블로그 기록]
- MySQL 기반 채팅 데이터베이스에서 높은 I/O 비용 발생
- 수평 확장(Scale-out) 한계로 인해 트래픽 증가 시 성능 저하
- NoSQL(MongoDB)로의 마이그레이션 필요성 검토
- 읽기/쓰기 작업 중심 → 관계형 DB보다 NoSQL이 적합
- 유연한 스키마 구조 필요 → 다양한 데이터 포맷 저장 가능
- 낮은 지연시간 보장 & 대규모 트래픽 대응 가능
- MongoDB로 마이그레이션하여 확장성 및 조회 성능 개선
- 수평 확장 지원 → 높은 트래픽에도 안정적인 성능 유지
6. MongoDB Date 칼럼의 UTC 저장 문제 — [블로그 기록]
- MongoDB는 Date 타입을 UTC로 저장
- 시간대 변환 문제로 인해 데이터 해석 혼란 발생
- MongoDB는 서버 레벨에서 Time Zone 변경을 지원하지 않음
LocalDateTime → ZonedDateTime
변환 시도했으나, MongoDB는 ZonedDateTime을 지원하지 않음
- Spring Data MongoDB의 Custom Conversions 기능 활용
- KST 변환 컨버터 구현 → 시간 정보의 일관성 확보 및 개발 편의성 향상
7. Pageable 검증 코드 중복으로 인한 복잡도 증가 및 가독성 저하 문제
- 각 Controller마다 Pageable 검증 코드가 중복됨
- 코드 복잡도 증가 & 가독성 저하
- 페이징 요청을 검증하는 커스텀 어노테이션 및 리졸버 구현
- page, size 값이 누락되거나 유효하지 않을 경우 기본값 적용 → 안정성 및 유지보수성 향상
