주제: 사용자 맞춤형 날씨 정보 제공 및 상호작용 플랫폼
대상: 날씨 정보 활용 및 상호작용에 관심이 있는 사용자
- 정확한 날씨 정보 제공: 기상청 데이터와 AI 분석을 통해 지역별 맞춤형 날씨 정보 전달
- 미션 수행과 커뮤니티 강화: 날씨 기반 미션과 커뮤니티 상호작용을 통해 사용자 참여 유도
- 긴급 상황 대응: 기상특보 채팅으로 실시간 정보 공유 및 대응
- ⚛️ React: 사용자 인터페이스(UI) 개발을 위한 라이브러리
- 🌱 Spring Boot: 강력한 백엔드 애플리케이션 개발 프레임워크
- 🐬 MySQL: 데이터 저장 및 관리에 사용된 관계형 데이터베이스
- 🚀 Redis: 캐싱 및 실시간 데이터 저장
- 💬 Kafka: 메시지 큐 및 데이터 스트리밍 도구로 실시간 채팅 및 알림 구현
- 🛠️ Jenkins: CI/CD 자동화를 위한 도구
- 📦 Docker: 애플리케이션 컨테이너화
- ☸️ Kubernetes: 컨테이너 오케스트레이션 및 관리
- 🐙 Argo: DevOps 워크플로우 관리
- ☁️ AWS: 클라우드 인프라 호스팅
- 🔀 Nginx: 리버스 프록시 및 웹 서버
- 🐍 Python: 데이터 처리 및 AI 모델 개발
- 🔗 LangChain: AI 어플리케이션 구축을 위한 프레임워크
- 🐙 GitHub: 버전 관리 및 소스 코드 관리
- 📝 Notion: 프로젝트 관리 및 문서화
- 🎮 Discord: 팀 커뮤니케이션
- 🎨 Figma: UI/UX 디자인
-
JWT 기반 사용자 인증
- 사용자 로그인/회원가입 시 JWT 토큰 발급 및 인증 관리.
- STOMP 헤더에 JWT 토큰을 포함해 실시간 채팅에서도 인증 처리.
- 토큰에서 사용자 ID를 추출하여 커뮤니티, 미션 등 다양한 기능에 활용.
-
회원가입 및 로그인
- 일반 회원가입 및 카카오 소셜 로그인 지원.
- 비밀번호 검증 및 닉네임 중복 방지 처리.
-
사용자 정보 관리
- 사용자 정보 수정, 닉네임 변경, 로그아웃 및 회원 탈퇴 기능 제공.
-
날씨 기반 맞춤형 미션 제공
- 기상 데이터를 활용하여 아침, 점심, 저녁 기준으로 최대 3개의 미션 생성.
- 예시 미션: "자전거를 타세요", "텀블러를 사용하세요".
- 각 미션마다 포인트 지급률 및 진행 상태 표시.
-
AI 기반 미션 인증
- 사용자가 미션에 맞는 사진을 첨부하면 AI가 해당 사진의 적합성을 검증.
- 인증 성공 시 포인트 지급 및 실패 시 재도전 가능.
-
포인트 및 랭킹 시스템
- 포인트를 기반으로 사용자 랭킹 제공.
- 순위 확인 및 검색 기능을 통해 사용자 경험 향상.
-
위치 기반 게시글
- 사용자의 현재 위치를 기준으로 반경 5km 내 게시글 표시.
- 위치 변경 시 카카오맵 API를 통해 새로운 위치 반영 및 게시글 업데이트.
-
게시글 작성
- 제목(20자) 및 본문(150자) 글자 수 제한을 통해 사용자 경험 최적화.
- 좋아요/싫어요 버튼으로 게시글 신뢰도 평가 가능.
-
내가 작성한 글 관리
- 사용자가 작성한 글의 리스트를 확인 및 삭제 가능.
- 기상특보에 따른 실시간 채팅방 생성
- 기상특보 발생 시 해당 지역의 사용자들을 위한 오픈 채팅방 자동 생성.
- 예: "강원도 건조/한파 경보 채팅방".
- 기상특보 데이터 업데이트:
- Spring Scheduler를 활용해 1시간마다 기상청 API 호출.
- 기상특보 발령 시 '시/도' 기준으로 실시간 단체 오픈채팅방 자동 생성.
- 실시간 채팅:
- Redis:
- 최신 채팅 메시지 100개를 캐싱하여 빠른 채팅 로드 제공.
- 사용자 간 실시간 메시지 교환 성능 향상.
- WebSocket + STOMP:
- 실시간 양방향 통신 구현.
- 채팅방 내 메시지 브로드캐스팅 및 실시간 알림 기능 제공.
- Redis:
- WebFlux와 R2DBC를 활용한 확장:
- WeatherWise-Server-Chatting 레포지토리에서 MSA 구조로 구현.
- WebFlux와 R2DBC를 사용해 비동기 처리로 확장성과 성능 향상.
문제 상황
- 기존 모놀리식 구조에서는 Spring MVC를 사용하여 초당 최대 400명의 사용자 요청을 처리했으나, 이 이상의 트래픽이 발생하면 서버가 과부하로 인해 다운되는 문제가 발생.
- 응답 속도가 느려지고 데이터의 정합성에도 문제가 생길 가능성이 높아짐.
1. MSA 도입과 WebFlux 전환
- 채팅 기능을 독립적인 MSA 서비스로 분리하여 Spring WebFlux를 도입.
- WebFlux의 비동기/논블로킹 특성을 활용해 높은 동시 처리 성능 확보.
- 기존 Servlet 기반의 동기 요청-응답 처리 방식에서 WebFlux 기반의 비동기 논블로킹 방식으로 전환
- 다수의 동시 연결 요청을 처리할 수 있는 확장성 확보
- WebFlux를 적용함으로써 이벤트 루프 기반의 효율적인 리소스 사용으로 응답 시간이 단축됨
- Kafka를 사용하여 메시지 큐 기반의 비동기 통신을 적용, 서비스 간 결합도를 낮추고 안정성 강화.
- 메시지 송수신에서 발생하던 I/O 병목 현상을 완화하기 위해 Kafka를 메시지 브로커로 활용
- WebSocket으로 수신된 메시지를 Kafka Producer로 처리해 분산 브로커에 저장
- Kafka Consumer가 메시지를 Redis에 저장하고, 채팅방 사용자에게 전달
- Kafka를 통해 메시지 큐를 관리함으로써 부하를 분산 처리하고 데이터 손실을 방지
- WebSocket에서 직접 Redis와 연결하는 대신 Kafka를 중간 계층으로 사용해 안정성과 성능 향상
- Redis 캐싱 최적화
- Redis를 사용해 채팅방의 최신 메시지 100개를 캐싱
- 사용자 요청 시 Redis에서 즉시 데이터를 제공해 응답 속도 향상
- 기존 Redis 저장 방식에서 동시성 이슈를 해결하기 위해 락(lock) 메커니즘 적용
- R2DBC로 데이터베이스 성능 개선
- R2DBC를 도입해 MySQL 데이터베이스와의 통신을 비동기 방식으로 전환
- 기존의 동기 JPA 접근 방식에서 발생하던 I/O 대기 시간을 줄여, 채팅 데이터 저장 시 처리 속도 개선
- 트랜잭션 처리가 간단한 채팅 시스템에 적합한 경량 데이터 처리 방식으로 전환
2. 데이터 정합성 보장
- WebFlux와 Kafka를 통해 대량의 데이터를 처리하면서도 4만 건 이상의 데이터 정합성을 100% 유지.
- 데이터 손실 없이 모든 메시지가 안정적으로 DB에 저장되도록 설계.
결과
- 처리량 증가: 초당 400명 → 1500명 이상의 사용자 요청 처리 가능.
- 응답 시간 단축: 평균 응답 시간 80% 이상 감소.
- 데이터 정합성: 100% 데이터 일치 보장.
- 다수의 동시 연결 환경에서도 메시지 손실 없이 실시간 채팅 가능.
기존 모놀리식 아키텍처 에서 마이크로서비스 아키텍처(MSA) 로 전환하는 과정을 설명합니다.
특히, 쿠폰 발급 서비스의 성능 문제를 해결하기 위해 Kafka를 활용한 비동기 메시지 처리 방식으로 전환한 사례를 중심으로 다룹니다.
- 특정 프로모션을 통해 사용자에게 쿠폰을 발급하는 이벤트입니다.
- 아래 발급 조건을 충족해야 쿠폰을 받을 수 있습니다.
- 한 사람당 한 개의 쿠폰만 가질 수 있다.
- 당일 미션 하나를 인증 받아야 한다.
- 이벤트 기간 동안, 매일 특정 시간에 오픈하며 총 지급 수량을 한정한다.
- 쿠폰 지급 수량은 당일 정해진 양을 초과할 수 없다.
모놀리식 아키텍처는 모든 기능이 단일 서비스 내에 통합되어 있어 아래와 같은 문제가 발생했습니다:
- 서버 마비: 트래픽이 급증하면 서버 자원이 고갈되어 기본 기능(예: 회원가입, 로그인)조차 정상적으로 작동하지 않음.
- TPS 한계: 평균 TPS 200에 도달 시 웹서버가 병목현상을 일으키며, 전체 서비스가 중단.
모놀리식 구조의 한계를 극복하고, 높은 트래픽 상황에서도 안정적인 서비스를 제공하기 위해 MSA를 도입했습니다.
- 각 기능을 독립적인 마이크로서비스로 분리.
- 특정 서비스 장애가 전체 시스템에 영향을 미치지 않도록 설계 가능.
- 초기에는 서비스 간 통신 방식으로 가장 익숙한 HTTP를 사용.
- 그러나 HTTP는 동기 요청 방식이기 때문에 모놀리식의 한계(서비스 간 결합도)와 장애 전파 문제를 해결하지 못함.
- 기존 HTTP 요청 방식의 결합도 높음과 장애 전파 위험을 해결하기 위해 Kafka를 도입.
- Kafka를 통해 비동기 메시지 기반 아키텍처로 전환.
- 비동기 처리
- 메시지를 큐에 저장하여 서비스 간 비동기적으로 데이터를 처리.
- 내결함성
- 메시지가 큐에 저장되므로 특정 서비스가 다운되더라도 메시지가 유지됨.
- 서비스 복구 후 메시지 재처리 가능.
- 높은 처리량
- Kafka는 높은 스루풋을 지원해 대량의 메시지를 효율적으로 처리.
- 확장성
- 메시지 브로커를 통해 서비스 간 결합도를 낮춰, 각 서비스를 독립적으로 확장 가능.
- 서비스 독립성 강화
- 서비스 간 직접적인 의존성을 제거하고, 메시지 브로커를 통한 간접적 통신으로 독립성 강화.
- 유연한 에러 처리
- 장애 발생 시 메시지를 큐에 저장하여 재처리하거나 다양한 방식으로 에러 처리 가능.
- 성능 향상
- 비동기 메시지 처리로 블로킹 없이 다수의 요청을 처리해 전체 시스템 성능 개선.
Kafka 기반 비동기 메시지 처리로 다음과 같은 성과를 달성했습니다:
- 성능 개선
- 트래픽 폭주 상황에서도 서비스 마비 없이 안정적 동작.
- 신뢰성 향상
- 서비스 다운 시에도 메시지가 큐에 저장되어 복구 후 처리가 가능.
- 확장성 강화
- 각 서비스를 독립적으로 스케일링 가능해 전체 시스템 유연성 증가.
- 데이터 정합성 유지
- 비동기 메시지 처리로 데이터 정합성을 유지하며, 고트래픽 상황에서도 안정적 데이터 처리 가능.
모놀리식 아키텍처에서 MSA로의 전환은 초기에는 복잡해 보일 수 있습니다. 그러나 높은 트래픽과 장애 상황에서 문제를 효과적으로 해결할 수 있는 강력한 방법입니다.
Kafka를 활용한 비동기 메시지 처리는:
- 서비스 간 결합도를 낮추고,
- 시스템 신뢰성과 확장성을 향상시키며,
- 안정적인 사용자 경험을 제공합니다.
이러한 전환을 통해 서비스 간 독립성을 확보하고, 높은 트래픽 상황에서도 확장성과 안정성을 겸비한 아키텍처를 구현할 수 있었습니다.
- Frontend Developer: 박설, 김지원
- Backend Developer: 박설, 김지원