Skip to content

ko-dongwon/momo

Repository files navigation

MOMO [모임으로 모여라]

1. 프로젝트 소개

개발 기간 : 2025.07.17 ~ 2025.08.25

“같은 관심사를 가진 사람들과 어울리고 싶은데, 어디서 어떻게 찾아야 할지 모르겠나요?”
MOMO에서 당신과 같은 관심사를 가진 사람들을 만나보세요!

MOMO는 “어디서 어떻게 시작해야 할지 막막한” 이들을 위해, 같은 관심사를 가진 사람들을 연결하는 취미 기반 모임 플랫폼입니다.

핵심 가치

  • 쉬운 모임 개설·참가 : 몇 번의 클릭으로 모임 개설·참가
  • 편리한 결제 : 토스페이먼츠 연동으로 간편 정산
  • 알림 시스템 : 관심 모임, 주변 모임 생성 등 다양한 알림을 통해 모임을 참석, 관리

개발 컨벤션

GitHub 협업 규칙 메서드 명명 규칙 클래스 명명 규칙 RabbitMQ 네이밍

2. 기술 스택

애플리케이션

QueryDSL

인증 및 보안

Spring Security JWT

데이터베이스

MySQL Redis Elasticsearch

메시징

RabbitMQ

모니터링

OpenTelemetry Jaeger Prometheus Grafana Loki

CI/CD

GitHub Actions

클라우드

AWS EC2 AWS ECS AWS ECR

3. 아키텍처

🌟 월간 예상 비용 요약

  • 시나리오 : 예상 월간 사용자 1만명 , 월간 요청 수 600만건
  • 월간 예상 비용 : 약 $729.22

👉 더 자세한 내용은 클릭해주세요 : AWS 월간 비용 예상

ERD

4. ERD

ERD


6. 주요 서비스 플로우

모임 참가

  1. 사용자 모임 참가 신청
    사용자가 모임에 참가 신청하면 자격/정원/시간을 검증합니다.
  2. 결제 요청 이벤트 기록/발행
    유료 모임이면 결제 정보를 생성하고 PG로 결제 승인을 시도합니다. (무료면 즉시 참가 완료)
  3. 결과 반영
    결제가 성공하면 참가가 확정되고, 실패하면 신청이 취소 됩니다.
  4. 알림 및 기록
    결과를 사용자/호스트에게 알림으로 보내고, 이력을 저장/발행 합니다.

모임 생성

  1. 모임 등록
    호스트가 모임 정보를 입력하고 모임을 생성합니다.
  2. 알림 준비
    create 이벤트가 메세지 허브로 전달되고 메세지 허브에서 대상 사용자를 조회합니다. 이후 메세지를 가공/조합 합니다.
  3. 알림 발송
    알림 서비스에서 푸시/알림을 전송합니다.

8. 트러블 슈팅 & 성능 개선

1. 모임 참가 성능 개선 : 비동기 처리

🔍 문제 원인

  • 미팅 참가, 결제, 알림 작업을 단일 트랜잭션에서 처리하여 DB 커넥션 점유 시간이 길어짐.
  • 목표 성능 TPS 20 달성 실패

💡 문제 해결

  • 트랜잭션을 DB 작업에만 한정
  • 결제, 알림 작업은 Spring Event 기반 비동기 처리로 분리, 트랜잭션 커밋 이후 실행되도록 설계

📈 문제 해결 전후 비교

테스트 시나리오 : 5분간 초당 20회의 모임 참가 요청
테스트 환경 : AWS EC2(t2.small)

개선 전 테스트 결과
image

구분 평균 (ms) 최소값 (ms) 최대값 (ms) p95 오류 % 초당 요청 수 평균 DB 커넥션 사용시간(ms) 평균 DB 커넥션 획득 대기 시간(ms)
HTTP 요청 5000 563 10000 5000 0.00% 17.57/sec 536 2900

개선 후 테스트 결과
image

구분 평균 (ms) 최소값 (ms) 최대값 (ms) p95 오류 % 초당 요청 수 평균 DB 커넥션 사용시간(ms) 평균 DB 커넥션 획득 대기 시간(ms)
HTTP 요청 12 4 43 15 0.00% 20/sec 76 1.8

🌟 성능 개선 요약

  • 처리량 : 17.52 요청/초 → 20 요청/초 (약 14.2% 증가)
  • 평균 DB 커넥션 사용 시간 : 536ms → 76ms (약 85.7% 감소)
image

2. 도메인 간 변경 의존성 제거 : 공유 커널 패턴

🔍 문제 원인

  • 도메인 간 통신을 위해 WebClient 설정을 각 도메인에서 별도로 관리
  • 동일한 WebClient 설정이 각 도메인에서 중복 정의
  • 도메인 모듈이 비즈니스 로직 외에 기술적 설정까지 포함해 관심사 분리 약화
  • 설정 변경 시 모든 도메인을 수정해야 해 유지보수 부담 증가

💡 문제 해결

  • Global 패키지에 WebClient 설정을 통합하고, 각 도메인은 이를 주입받아 사용
  • 도메인은 WebClient 구현 세부사항에서 분리되어 비즈니스 로직에만 집중

🌟 개선 요약

  • 의존성 방향 제어 : DSM을 통해 순환 참조 0개, 단방향 의존 구조 검증 → 모든 도메인이 Global만 의존하고 서로 직접 의존하지 않음
  • 변경 의존성 제거 : 설정 변경이 단일 지점(Global)에서만 발생 → 유지보수 효율성 향상
image

3. 모임 목록 조회 성능 개선 (Elasticsearch 도입)

🔍 문제 원인

  • 기존 SQL의 LIKE %...% 방식으로 Full Table Scan 발생.

💡 문제 해결

  • ElasticSearch를 도입하여 역색인(Inverted Index) 기반 조회

📈 문제 해결 전후 비교

테스트 시나리오 : 1분간 초당 1000회 조회 데이터 수 : 5만건

개선 전 성능 테스트 결과

구분 표본 수 평균 (ms) 최소값 (ms) 최대값 (ms) p95 오류 % 초당 요청 수
HTTP 요청 14,879 4,013 15 10,829 7,490 6.72 244.5/sec

개선 후 성능 테스트 결과

구분 표본 수 평균 (ms) 최소값 (ms) 최대값 (ms) p95 오류 % 초당 요청 수
HTTP 요청 25,940 2,485 5 6,882 4,154 3.85% 395.1/sec

🌟 개선 요약

  • 평균 응답 시간: 4,013ms → 2,485ms (약 38.1% 감소)
  • 처리량: 244.5 요청/초 → 395.1 요청/초 (약 61.6% 증가)
image

4. Redis 캐싱을 통한 DB 부하 감소

블로그 글 : Redis 캐싱을 통한 모임 조회 성능 개선과 DB 부하 줄이기

🔍 문제 원인

  • 서비스 내 최다 호출 API인 모임 단건 조회가 모든 요청마다 DB를 직접 조회하여 부하 발생

💡 문제 해결

  • Redis 캐싱을 도입해 조회 요청을 캐시로 분산시켜 DB 부하 완화
  • 조회 속도 자체는 크게 개선되지 않았지만, DB 트래픽 감소

📈 문제 해결 전후 비교

캐싱 전 테스트 결과
image

metric 평균 (ms) 최소값 (ms) 최대값 (ms) p95 DB 쿼리 수 평균 DB CPU 사용률(%)
HTTP 요청 8 3 147 15 약 30,000개 6.42

캐싱 후 테스트 결과 image

metric 평균 (ms) 최소값 (ms) 최대값 (ms) p95 DB 쿼리 수 평균 DB CPU 사용률(%)
HTTP 요청 5 1 179 12 약 4,000개 3.43

🌟 성능 개선 요약

  • 총 쿼리의 개수 : 약 30,000 → 약 4,000개 (약 86.67% 감소)
  • 평균 CPU 사용률 : 약 6.42% → 약 3.43% (약 46.57% 감소)
  • p95 : 15ms → 12ms (약 20.00% 감소)
image

5. 트랜잭셔널 아웃박스 패턴을 통한 메시지 발행 보장

🔍 문제 원인

  • RabbitMQ 도입 후 메시지가 브로커로 전달되는 과정에서 메시지 유실 가능성 존재
  • DB 트랜잭션이 롤백되었음에도 이미 발행된 메시지를 되돌릴 수 없는 문제 발생

💡 문제 해결

  1. Spring Event - AFTER_COMMIT 적용
  • 트랜잭션 커밋 이후에만 이벤트가 발행되도록 제한하여, 롤백 시 메시지 발행 차단
  1. Transactional Outbox 패턴 도입
    • 메시지 생성을 DB 트랜잭션에 포함시켜 DB 작업과 메시지 생성의 원자성 보장
  2. RabbitMQ Publisher Confirm 활용
    • 메시지가 브로커에 정상적으로 도달했는지를 확인
    • Publisher Confirm 수신 시에만 성공 처리하여 메시지 유실 방지
  3. Spring Scheduler 기반 재발행 처리
    • Outbox 테이블에서 발행되지 않은 메시지를 주기적으로 확인
    • 누락된 메시지를 재발행하여 최종 일관성 보장

팀원 소개

         

차준호 (팀장)            김신영 (부팀장)            고동원 (팀원)

  유저 도메인, 배포 인프라          결제 도메인          인증/인가, 배포 인프라  

GitHub Blog      GitHub Blog      GitHub Blog


         

우지운 (팀원)            임호진 (팀원)            이의현 (팀원)

알림 도메인          모임 참가, 모니터링          모임 도메인

GitHub Blog      GitHub Blog      GitHub Blog

About

momo(모임으로 모여라)

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 6

Languages