상태 흐름을 중심으로 동시성, 트랜잭션, 객체지향 설계를 구현하며 검증한 주문/결제 시스템
🔗 주문 내역 N+1 문제 개선: FETCH 조인과 IN
-
문제
- 주문 내역 조회 API 호출 시, 반복문 내부에서 연관된 도메인(결제, 배송 등)을 건별로 직접 조회하여 주문 데이터 개수(N)만큼 추가 쿼리가 발생하는 N+1 문제 확인
-
해결
-
IN절을 활용한 다건 조회 및JOIN FETCH를 적용하여 네트워크 쿼리 호출을 최소화하고,Collectors.toMap()을 통해 애플리케이션 메모리 상에서 시간 복잡도$O(1)$ 로 매핑되도록 최적화
-
-
결과
- 더미 데이터 100건 조회 기준 발생하는 쿼리 수를 301건에서 3건으로 줄이고, 소요 시간을 1.36s에서 462ms로 단축하여 약 66%의 조회 성능 개선 달성
🔗 재고 차감에서 갱신 손실을 해결하며 이해한 트랜잭션 락
- 문제
- 동시 주문 시 여러 트랜잭션이 동일한 재고를 수정하면서 갱신 손실이 발생하여 데이터 정합성이 깨지는 문제 확인
- 해결
- 비관적 락과 낙관적 락을 각각 적용하여 멀티스레드 테스트를 수행하고 처리 시간과 충돌 상황을 비교 분석
- 프로젝트 특성에서는 성능 차이가 크지 않았으며, 구현 복잡도와 데이터 정합성을 고려하여 비관적 락을 최종 선택
- 결과
- 다중 스레드 환경에서도 재고 데이터의 무결성을 안정적으로 보장하도록 개선
🔗 결제와 배송을 분리하며 이해한 트랜잭션 셀프 인보케이션
- 문제
- 결제 완료 후 배송 생성 기능을 설계하는 과정에서, 동일 클래스 내부 호출은 프록시를 거치지 않아
@Transactional의 전파 옵션이 적용되지 않는 셀프 인보케이션 문제를 확인
- 결제 완료 후 배송 생성 기능을 설계하는 과정에서, 동일 클래스 내부 호출은 프록시를 거치지 않아
- 해결
- 프록시 기반 트랜잭션 동작 원리를 분석한 뒤
ApplicationEventPublisher를 활용하여 결제 완료 이벤트를 발행하고, 배송 도메인이 독립적으로 처리하도록 변경
- 프록시 기반 트랜잭션 동작 원리를 분석한 뒤
- 결과
- 향후 트랜잭션 전파 문제를 예방하고, 결제와 배송 도메인의 책임과 결합도를 분리할 수 있는 구조를 적용
- 문제
- 서비스 계층에 비즈니스 규칙이 집중되어 재사용성과 유지보수성이 떨어지고 객체지향적인 설계가 어려운 구조
- 해결
- 엔티티가 자신의 상태 변경 규칙을 직접 수행하도록 도메인 모델 패턴(DDD)을 적용하고 서비스는 흐름만 조율하도록 역할을 분리
- 결과
- 엔티티의 응집도를 높이고 서비스 계층의 복잡도를 줄여 변경에 유연한 구조를 구축
- Backend: Java 17, Spring Boot 3.5.14, Spring Data JPA
- Database: MySQL 8.0
- Build Tool: Gradle
