Redis Stream을 적용한 선착순 이벤트 시스템 (2편)
·
프로젝트
Spring Boot + MySQL로 구현한 선착순 이벤트 시스템 (1편)“매일 오후 1시에 선착순 100명에게 도서를 증정하는 이벤트 시스템”을 개발하게 되었습니다. 처음엔 단순해 보였지만, 높은 동시성과 정확성이 요구되는 이 과제는 생각보다 많은 도전 과제hyodeng.tistory.com 1편에서는 Spring Boot와 MySQL만으로 선착순 이벤트 시스템을 구현하고 그 한계점을 분석했습니다. 이번 글에서는 Redis Stream을 활용하여 시스템을 어떻게 개선했는지 그리고 그 결과로 성능이 어떻게 향상 되었는지 공유하고자 합니다. Spring + MySQL 구조에서의 문제점단일 서버 환경의 Spring Boot + MySQL 구조로 시스템을 구현했을 때 심각한 병목 현상들이 발견되었습니다.DB ..
SQL 튜닝을 통한 API 성능 최적화 (2편)
·
프로젝트
SQL 튜닝을 통한 API 성능 최적화 (1편)현재 댕글 데이터베이스에는 데이터가 약 1,000개 이하로 적은 양이기 때문에 비효율적으로 작성된 쿼리로도 원하는 데이터를 빠른 속도로 가져올 수 있습니다. 하지만 서비스가 성장하면서 데hyodeng.tistory.com 대기 진료 견적서 상세 조회 (GET)테스트 환경 : Local MySQL 8.0 / Local 애플리케이션 서버 / 100만 개 데이터 기준문제 상황사용자가 진료 견적서에 대한 상세 데이터를 조회하기 위해서는 care_estimates 테이블에 들어있는 vet_id, pet_id 등의 id 를 통해 각 vets, pets 에 해당하는 다른 테이블의 정보를 가져와야 했습니다. 기존 구현에서는 세 개의 개별 쿼리를 순차적으로 실행하여 데이터를..
성장하는 서비스를 위한 DDD 기반 멀티 모듈 전환기
·
프로젝트
변화의 필요성댕글 서비스를 개발하면서 초기에는 빠른 기능 구현과 배포를 위해 일반적인 Spring Boot 기반의 모놀리식 아키텍처로 시작했습니다.com.daengle├── controller│ ├── UserController.java│ ├── GroomerController.java│ ├── VetController.java│ ├── PaymentController.java│ └── ...├── service│ ├── UserService.java│ ├── GroomerService.java│ └── ...├── repository│ ├── UserRepository.java│ └── ...├── entity│ ├── User.java│ ├── Groomer..
Spring MVC의 진입점을 파고들어 개선한 JWT 토큰 처리 시스템
·
프로젝트
시작은 불편함에서멀티 모듈로 구성된 댕글 서비스에서 Auth 모듈은 사용자 인증과 인가를 담당하는 핵심 모듈입니다.Spring Security + JWT + OAuth2.0을 기반으로 구축된 이 모듈은 처음에는 단순히 “동작하는 코드”를 만드는 데 초점을 맞췄습니다. 초기 구현에서는 로그인 성공 시 사용자 정보가 담긴 JWT 토큰을 생성하고, 보호된 엔드포인트에 접근할 때마다 이 토큰을 검증하는 방식이었습니다. 그러나 REST API를 개발하면서 사용자의 인증 상태나 권한을 확인해야 하는 엔드포인트가 늘어났고, 각 컨트롤러마다 토큰 처리 코드가 반복되었습니다. 초기 구현 방식@RestController@RequiredArgsConstructor@RequestMapping("/api/user")public..
Spring Boot + MySQL로 구현한 선착순 이벤트 시스템 (1편)
·
프로젝트
“매일 오후 1시에 선착순 100명에게 도서를 증정하는 이벤트 시스템”을 개발하게 되었습니다. 처음엔 단순해 보였지만, 높은 동시성과 정확성이 요구되는 이 과제는 생각보다 많은 도전 과제를 안겨주었습니다.이 글에서는 Spring Boot와 MySQL만으로 시작해 어떤 문제에 직면했고, 어떻게 이를 분석하고 개선해 나갔는지 경험을 공유하고자 합니다. 요구사항 분석프로젝트 시작 시 다음과 같은 요구사항을 확인했습니다.매일 오후 1시에 선착순 100명 한정 이벤트 진행1분에 10만 건의 요청을 10분간 처리 (초당 약 1,666건)중복 응모 방지정확히 100명까지만 선발다음날 오후 1시에 당첨자 발표가장 핵심적인 요구사항은 초당 1,666건의 요청 중에서 정확히 100명만 선발하고, 동일 사용자의 중복 응모를..
JPA와 MySQL로 구현한 동시성
·
프로젝트
현재 꾸미 서비스에는 좋아요/싫어요 기능의 동시성 제어를 위해 Redis를 사용하고 있었습니다.그러나 기능 분석 결과, Redis 사용이 오버 엔지니어링이라고 판단했습니다.Redis를 사용하지 않으려는 이유좋아요/싫어요 기능은 SNS 서비스와 달리 실시간성이 매우 중요한 기능이 아닙니다. 사용자들이 동시에 좋아요 버튼을 누르는 상황이 자주 발생하지 않으며, 초당 처리해야 할 트랜잭션 수가 많지 않습니다. 즉, 수 밀리초 단위의 즉각적인 반영보다는 좋아요 수의 정확성이 더 중요합니다. 추가적으로, Redis 사용으로 인한 여러 단점들이 존재했는데,추가 인프라 관리 오버헤드 발생Redis와 MySQL 간 데이터 동기화 로직 필요장애 상황에서 데이터 정합성 보장의 어려움시스템 복잡도 증가이번 기회에 JPA와 ..
SQL 튜닝을 통한 API 성능 최적화 (1편)
·
프로젝트
현재 댕글 데이터베이스에는 데이터가 약 1,000개 이하로 적은 양이기 때문에 비효율적으로 작성된 쿼리로도 원하는 데이터를 빠른 속도로 가져올 수 있습니다. 하지만 서비스가 성장하면서 데이터 양이 100만 개 혹은 그 이상으로 늘어난다면, 초기에 예상했던 것보다 현저히 느린 조회 속도로 사용자 경험을 저하시키게 되고, 이는 사용자 이탈까지 이어질 수 있습니다. 이러한 문제를 미연에 방지하기 위해, 인프라 확장이나 캐싱 시스템 도입과 같은 복잡한 해결책을 적용하기 전에, 가장 기본적이면서도 효과적인 방법인 SQL 튜닝을 시도해보았습니다. 성능 개선 효과를 검증하기 위해 100만 개의 더미 데이터를 데이터베이스에 삽입한 후, 서비스의 주요 기능 중 하나인 “일반 진료 대기 견적서 반려동물 정보 반환 API”..