요구 사항 | 기술 | 기술 선택 이유 | 자세한 내용 |
---|---|---|---|
동시성 제어 | 선택한 기술 : | ||
- Redis |
선택지 : - 낙관적 락 - 비관적 락 | [Redis를 통한 동시성 제어] 싱글 쓰레드로 동작하는 Redis의 특성과 원자적 연산이 가능한 DECRBY, INCRBY를 활용하여 동시성 문제를 해결하면서 주문 API의 속도를 향상 시켰습니다.
[낙관적 락]
테스트 결과, 많은 요청이 한번에 들어옴으로써 잦은 충돌이 발생할 경우 동시성 이슈를 해결할 수 없었습니다.
[비관적 락]
많은 요청에 대해서 완벽하게 동시성 이슈를 해결할 수 있었지만,
Openrun 프로젝트의 특성 상, 1개의 상품에 여러 클라이언트의 요청이 짧은 시간에 많이 들어옵니다. 이를 Database에 Lock을 걸어 사용하게 되면, 서버의 Scale Out 환경에서 더 많은 요청을 빠르게 처리하지 못할 것으로 판단하였습니다. | 기본 개념 :
‣
성능 테스트 : ‣
‣
| | 성능 테스트 | **선택한 기술 :
| [Apache Jmeter] JMeter는 오픈소스 도구이므로 라이센스 비용이 발생하지 않습니다. 그리고 사용하기 쉬운 그래픽 사용자 인터페이스를 제공합니다. 이를 통해 팀원들이 직관적으로 테스트 시나리오를 구성하고 결과를 확인할 수 있다고 판단해 JMeter를 사용했습니다.
[Cloud Watch] CloudWatch는 거의 실시간으로 메트릭 데이터를 제공합니다. 이를 통해 프로젝트 팀은 시스템의 상태를 즉각적으로 파악하고 필요한 조치를 취할 수 있습니다. 그리고 CloudWatch Alarms을 사용하여 특정 임계 값이 초과하면 알림을 받아 즉각 대응할 수 있습니다. | 기본 개념 : ‣
| | CI/CD | **선택한 기술 :
**선택지 :
[Jenkins]
Jenkins는 확장성이 뛰어나고 다양한 플러그인을 제공하는 등 많은 장점이 있습니다. 하지만 jenkins를 사용하면 별도의 서버가 필요하고, 이에 따른 유지 보수 비용이 발생 할 수 있다는 점. 연동과 설정이 상대적으로 복잡할 수 있다는 점 등의 이유로 github 저장소에 내장된 형태로 제공되고 자동으로 통합되는 GitHub Actions를 채택했습니다.
~~~~
[Docker] 프로젝트의 애플리케이션은 여러 환경에서 실행되어야 했으며, 개발, 테스트, 배포 과정이 일관되게 진행 되어야 했습니다. 또한, CI/CD 파이프 라인과의 통합을 통해 전체 프로세스의 자동화가 필요했습니다. Docker를 사용하면 다양한 환경에서 동일하게 실행될 수 있게 해줘 수평 확장에 이점이 있습니다. 그리고 GitHub Action과 Docker를 함께 사용함으로써, 코드 변경 감지 시 자동으로 Docker이미지를 빌드하고, 해당 이미지를 테스트, 배포하는 전체 프로세스를 자동화 할 수 있었습니다. | 기본 개념 : ‣ | | 검색 쿼리 최적화 및 속도 개선 | **선택한 기술 :
선택지 :
LIKE ‘%[입력단어]%
로 검색을 해야 하는데 INDEX의 특성앞 단에 %에 의해서 인덱스 생성이 불가 때문에 전문 검색에 특화된 Full Text Index를 적용 했습니다.
Full Text Index는 공백, 구두점 등을 기준으로 텍스트를 토큰 화 하기 때문에 문장이나 문구에서 개별 단어를 효과적으로 식별할 수 있습니다. 역 인덱싱 방식으로 검색에 해당 하는 데이터를 빠르게 조회합니다.[QueryDsl] 검색 과정에서 다양한 조건문에 대해 동적 쿼리를 작성할 때 유용하다 판단하여 채택 했습니다. JPQL로는 구현하기 복잡한 쿼리문을 queryDsl이 지원하는 매서드를 통해서 쉽게 구현가능하고 compile time에 에러를 확인, 편리한 Dto projections이 가능합니다.
[ELK]
검색 조건이 다양해 졌을 때 인덱스 조합을 모두 고려하지 않아도 빠른 검색을 지원해준다는 장점이 있었으나 적용에 필요한 리소스가 클 것으로 판단하여 프로젝트의 특성 상 상품 검색보다는 주문 성능의 향상에 집중하는 것이 맞다고 판단하여 제외함.
| 성능 개선 :
‣ |
| 상품 조회 성능 개선 | Redis | [Redis]
상품 조회는 프로젝트의 핵심 기능 중 하나로, 주문을 위해 필수로 거쳐야 하는 과정입니다. 우리는 자주 변경되지 않는 상품 정보를 cache에 저장하여, 데이터베이스에 직접적인 부하를 줄임과 동시에 사용자에게 빠른 응답 시간을 제공하고 싶어서 Redis를 사용하였습니다.
조회 전략 - Look Aside 상품 조회는 기본적으로 cache에 데이터를 먼저 확인합니다. 이후, cache에 데이터가 없다면 DB를 조회하고 이를 다시 cache에 저장하는 방식을 사용합니다. 다만, 당일 오픈런 상품의 경우, 다른 상품에 비해 조회량이 상대적으로 많을 것으로 판단하여, 자정을 기준으로 DB에 데이터를 cache에 미리 넣어두는 방식의 Cache-Warming전략을 사용하였습니다. | 레디스 개념 : ‣ | | 주문 성능 개선 | **선택한 기술: Apache Kafka Redis
선택지:
RabbitMQ
Redis pub/sub** | [Apache Kafka]
주문 API는 주문 상품 조회 → 상품 재고 관리 → 주문 생성
의 단계를 거칩니다. 세가지 단계를 모두 거친 뒤, 사용자에게 응답을 해줍니다. 위의 과정에서 상품의 재고가 충분하다면, 사용자는 주문에 성공을 한 것이므로, 상품의 재고 관리
, 주문 생성
과정을 비동기적으로 처리하여, 사용자들이 주문 후, 주문이 완료되기까지 기다리지 않고 다음 동작을 진행할 수 있도록 로직을 구성하였습니다.
Apache Kafka는 처리량이 매우 높으며, 수평 확장이 쉽다는 장점을 가지고 있습니다.
[Redis] - Write Through 특정 상품을 조회하면 상품의 재고가 redis에 저장됩니다. 이후, 주문 요청이 일어나면 cache에 저장된 해당 상품의 재고 값을 주문 수량만큼 변경하고, 비동기 처리 과정에선 redis의 남은 수량을 확인하며 상품의 현재 재고를 지속적으로 변경합니다.
[RabbitMQ]
장점 : Kafka에 비해 다양한 메세징 패턴을 지원해줍니다,
단점 : 확장성 및 성능 최적화를 위해 복잡한 설정이 필요할 수 있습니다.
[Redis pub/sub]
간단한 메세지 큐를 구현하기에 적합하다고 판단하였습니다.
AWS redis 프리티어는 많은 양의 주문 메세지를 처리하기에는 적합하지 않고,
다른 서비스에서 Redis를 적절량 활용하고 있기 때문에 Redis pub/sub 사용은 배제되었습니다. | 카프카 개념: ‣
성능 개선: ‣ | | Scheduler의 데이터 처리 작업 개선 | 선택한 기술: Spring Batch | [Spring Batch] 매일 자정에 수행 되는 스케줄러를 통한 데이터 처리 작업의 효율적인 트랜잭션 관리, 재시도 로직 작성, 성능 개선 등의 이유로 Spring Batch를 적용함. 수행하는 작업을 Step 으로 분리하면서 간편하게 트랜잭션을 분리 했고 각각의 Tasklet 혹은 chunk 단위로 재시도 로직을 작성 하는데 있어 편의성 및 코드 가독성이 높아짐. 또한 Cursor-based 방식을 사용해서 offset이 증가 할때 스케줄러의 데이터 저장 작업 속도가 극단적으로 저하 되는 상황 개선 가능 | | | 대용량 트래픽 분산 처리 Scale-out | auto scaling+load balancing | [Auto Scaling] 수직 확장(Scale-up)으로만 성능의 한계가 존재하며 성능을 높이기 위해 비싼 하드웨어로 업그레이드해도 가격 대비 성능 향상이 제한적입니다. 따라서 Scale-out을 통해 확장하고, 부하에 따라 서버를 Scale-in하여 서버 비용을 더 유연하게 조절할 수 있습니다.
[Load Balancing] 로드 밸런서는 서버로부터의 요청(트래픽)을 균등하게 분산하는 기술로, 부하 관리를 용이하게 해주며, 장애 시 복구와 확장성을 지원합니다. 이러한 특성은 Auto Scaling과 함께 사용하여 오픈레이스 프로젝트에 효과적으로 적용할 수 있습니다.
[+Scale-up] 추가로, 기본 서버/DB의 성능을 향상시키기 위해 프리티어 인스턴스에서 EC2 t3.micro 및 RDS t2.micro MySQL 인스턴스로 Scale-up을 수행했습니다.
따라서 스케일 아웃된 환경에서 스케일 업을 함으로써 높은 성능과 유연성을 얻을 수 있으며, 적당한 시점에 스케일 업을 수행하는 것은 전체 시스템의 효율성을 향상시킬 수 있습니다. | |