2025/01/06 11

[CodeChef - 트러블 슈팅] 포인트 전쟁에서 살아남기! Redis로 실시간 속도 전투!

실시간 유저 랭킹 조회 DB에서의 조회와 Redis를 캐싱(Cacheable 사용)한 것에서의 비교분석 DB에서 유저 랭킹 조회 레디스에서 조회  위 그래프들을 표로 분석[내가 구현한 기능]포인트에 따른 실시간 유저 랭킹[주요 로직]실시간 유저 포인트 랭킹 기능에서 Redis의 Sorted Set 자료 구조와 TTL(Time to Live) 기능을 사용하여 빠른 조회 성능을 확보하고 데이터 일관성을 유지했습니다. Sorted Set을 통해 유저 포인트를 기준으로 자동 정렬된 상태로 랭킹을 관리하며, TTL을 설정해 캐시 데이터가 일정 시간이 지나면 자동으로 갱신되도록 구현했습니다.[배경]실시간 포인트 랭킹 조회 기능이 높은 트래픽 상황에서도 빠른 응답 속도를 유지할 수 있도록 최적화가 필요했습니다. 기존..

[CodeChef - 트러블 슈팅] 인덱싱: 데이터 속도 전쟁에서 살아남기!

[문제 인식]게시글 검색을 위해 풀 테이블 스캔을 하는건 너무 비효율적이고 성능 소비가 심하다.대량의 데이터가 생길수록 응답 속도는 더 큰 차이를 보인다. 그래서 풀 테이블 스캔이 아니라, 인덱스를 생성하여 데이터 조회 속도를 높이고, 리소스 사용을 최적화 한다.인덱스책의 색인처럼 특정 데이터를 빠르게 찾을 수 있도록 하는 특별한 데이터 구조이다.B-Tree 인덱스: 범위 검색, 정렬된 데이터 조회에 적합하여 대부분의 데이터베이스에서 기본적으로 사용된다.Hash 인덱스: 특정 값과 일치하는 데이터를 찾는 데 빠르며, 범위 검색에는 적합하지 않다.[선택 이유]검색 속도를 높인다: 인덱스가 있으면 특정 데이터 위치를 바로 찾아가니까 전체 테이블을 검색할 필요 없이 빠르게 결과를 얻는다.응답 시간을 줄인다: ..

[CodeChef - 트러블 슈팅] 실시간 알림의 비밀: RabbitMQ로 댓글 알림 시스템 구축하기

[내가 구현한 기능]사용자들이 게시글에 댓글을 작성할 때, 해당 댓글이 게시글 작성자에게 실시간으로 알림으로 전달되는 기능을 제공하기 위하여, 댓글 알림 기능을 WebSocket + Redis Pub/Sub에서 RabbitMQ와 WebSocket을 활용하여 실시간으로 전송하는 시스템을 구현했습니다. [주요 로직]댓글 생성 시 알림 발행: 댓글이 작성되면 해당 댓글 정보와 함께 게시글 작성자에게 알림을 보내도록 메시지를 발행합니다. RabbitMQ를 통한 메시지 라우팅: 댓글 알림 메시지는 RabbitMQ의 Direct Exchange를 통해 commentQueue에 라우팅됩니다. RabbitMQListener를 통해 WebSocket 전송: RabbitMQ의 commentQueue를 구독하는 Rabbit..

[CodeChef - 트러블 슈팅] EC2 독립 선언: 한 서버에 갇힌 서비스들을 해방하다.

[배경]EC2 분산 배포에 대한 설명현재 EC2 하나에 카프카, 엘라스틱서치, 레디스, 스프링부트 서비스를 모두 배포하는 구조에서, 해당 EC2 인스턴스에 장애가 발생하면 모든 서비스가 동시에 중단될 위험이 있습니다. 따라서 각 서비스를 개별 EC2 인스턴스에 배포하여 분산 및 고가용성을 보장할 필요성이 커졌습니다.[요구사항]각각의 서비스인 레디스, 카프카, 엘라스틱서치, 스프링부트를 각기 다른 EC2 인스턴스에 배포해야 합니다. 이를 통해 서비스 간 독립성을 보장하고, 한 인스턴스에 장애가 발생하더라도 다른 서비스는 정상적으로 동작할 수 있도록 하는 것이 목표입니다.[선택지]1. 각각 EC2에 배포각 서비스마다 별도의 EC2 인스턴스를 할당하여 배포합니다.장점:고가용성: 한 EC2에 문제가 생겨도 다른..

[CodeChef - 트러블 슈팅] 배포 지옥 탈출기: GitHub Actions로 만들어낸 자동화 천국.

[주요 로직]GitHub Actions 시나리오개발자가 main 브랜치에 푸시하면, GitHub Actions 워크플로우가 자동 실행된다. 해당 워크플로우는 다음 단계를 포함한다.리포지토리 체크아웃actions/checkout@v4를 통해 애플리케이션 코드 리포지토리를 체크아웃한다.EC2 SSH 설정EC2 연결에 필요한 EC2_HOST, EC2_USER, SSH_PRIVATE_KEY 환경 변수를 사용해 SSH 설정을 구성한다.SSH_PRIVATE_KEY를 파일로 저장해 SSH 접근 권한을 설정한다.자바 환경 구성actions/setup-java@v4를 사용해 자바 17 환경을 설치하고, Gradle 빌드를 위한 설정을 마친다.Gradle 빌드gradlew 파일에 실행 권한을 부여하고, ./gradlew ..

[CodeChef - 트러블 슈팅] 데이터 수호자들 : 동시성 이슈와의 싸움에서 살아남기.

동시성 제어 방식의 발전 과정 및 성능 분석이번 성능 테스트는 DB 바로 저장 방식에서 시작하여 낙관적 락, 비관적 락, 분산 락으로 발전하는 과정을 통해, 각 방식이 가진 성능적 특징과 개선 효과를 평가했습니다. 각 방식의 성능을 측정한 결과는 다음과 같습니다.DB 바로 저장 > 2. 낙관적 락 > 3. 비관적 락 > 4. 분산 락 순으로 개선하였으며, 각 방식의 주요 특징과 개선된 이유를 구체적으로 설명하겠습니다.1. DB 바로 저장DB 바로 저장 방식은 동시성 제어가 없이 여러 요청이 동시에 데이터베이스에 접근하는 방식입니다. 간단하게 구현할 수 있지만, 동시성 문제가 발생할 가능성이 큽니다.스레드 활성화 시간: 활성 스레드가 초반에 급격히 증가하다가 서서히 감소하는 경향을 보입니다. 여러 스레드가..

[CodeChef - 기술적 의사 결정] Redis Sentinel 도입이 필요한 이유

문제 상황단일 Redis 인스턴스 사용 시 다음과 같은 문제가 발생할 위험이 있었습니다:Redis 장애 시 데이터 유실 위험단일 Redis 인스턴스가 장애를 겪으면 캐시 데이터가 모두 유실될 위험이 있었습니다.조회수나 포인트 랭킹 같은 실시간 데이터가 손실되면, 시스템 신뢰도가 크게 떨어질 가능성이 있었습니다.고가용성 부족단일 Redis는 장애 복구 기능이 없어, 서비스 중단이 발생할 수 있었습니다.실시간 처리가 중요한 우리 프로젝트 특성상, Redis 장애 시에도 서비스가 안정적으로 유지되어야 했습니다.도입 이유 및 해결 방안Redis Sentinel은 Redis의 고가용성을 보장하며, 장애 발생 시에도 데이터 유실을 방지하고 서비스의 연속성을 유지할 수 있었습니다.자동 장애 조치Redis Sentin..

[CodeChef - 기술적 의사 결정] Redis 도입이 필요한 이유

문제 상황게시물 조회수와 포인트 랭킹 등과 같은, 데이터를 실시간으로 정확하게 처리해야 하는 것이 중요한 상황에서, 기존 시스템은 다음과 같은 문제(한계)를 가지고 있었습니다:DB 부하 및 응답 지연게시물 조회수와 포인트 랭킹(예: 실시간 유저 랭킹, 지난달 유저 랭킹 등) 등을 조회할 때 데이터베이스 조회가 느려졌습니다. 조회수가 많은 인기 게시물에서는 동시 조회 요청이 많이 쏟아지면서 DB에 과도한 부하가 발생했습니다.실시간 데이터 처리의 한계조회수를 DB에 저장하는 방식으로는 비정상적인 조회수 증가(어뷰징)를 실시간으로 확인하거나 조치하는 것이 어려웠습니다.Refresh Token 관리의 비효율성DB로 관리할 경우, 불필요한 부하와 비효율성이 발생하는, 사용자 인증을 위한 Refresh Token을..

[CodeChef - 기술적 의사 결정] Docker Hub? AWS ECR?

문제 상황프로젝트에서 Docker 이미지를 효율적으로 저장하고 배포할 레지스트리가 필요했습니다. 이를 통해 배포 프로세스를 표준화하고 관리 편의성을 확보하고자 했습니다. 레지스트리를 선택하는 과정에서, AWS ECR과 Docker Hub 중 어떤 것을 사용할지를 검토하게 되었습니다.도입 이유 및 해결 방안선택지Docker Hub: Docker의 기본 이미지 저장소로, 다양한 환경에서 접근이 가능하고 설정이 간단합니다.AWS ECR: AWS 전용의 Docker 이미지 레지스트리로, AWS 서비스와 긴밀히 통합된 보안 및 관리 기능을 제공합니다.Docker Hub를 선택한 이유Docker Hub를 이미지 레지스트리로 선택한 이유는 다음과 같습니다:사용성과 접근성: Docker Hub는 Docker 커뮤니티의..

[CodeChef - 기술적 의사 결정] CI/CD 툴, Jenkins? Github Actions?

문제 상황기존의 수동 배포 과정은 속도 저하와 반복적인 작업으로 인한 비효율성을 초래했습니다. 이를 개선하기 위해 자동화된 CI/CD 프로세스를 도입하여 배포 과정을 최적화할 필요가 있었습니다.도입 이유 및 해결 방안선택지JenkinsGitHub Actions배경 당시 EC2 프리 티어 인스턴스(메모리 1GB)를 사용 중이며, Docker와 Jenkins를 동시에 구동하려 했으나 메모리 부족으로 성능이 크게 저하되는 문제가 발생했습니다. Jenkins는 일반적으로 2GB 이상의 메모리를 요구하며 Docker로 실행할 때에도 메모리가 더 필요하여, 현재 인스턴스에서는 Docker와 Jenkins를 동시에 운영하기 어려웠습니다. 결과적으로 CI/CD 작업을 안정적으로 수행하려면 최소 4GB 이상의 메모리가 ..