전체 글

뭐든 공부하면 언젠간 다 도움이 될거야
· CS 정리
여러 컬럼을 묶어 인덱스를 만들 때 "어떤 컬럼을 앞에 둘까?"는 성능에 직접적인 영향을 줍니다. 순서를 잘못 정하면 인덱스를 만들어도 제대로 활용되지 않는 경우가 많습니다. 아래 기준들을 순서대로 점검해보면 도움이 됩니다.1. 등치(=) 조건 컬럼을 range(범위) 조건 컬럼보다 앞에복합 인덱스는 왼쪽부터 순서대로 값이 정렬되어 저장됩니다. = 조건은 인덱스에서 정확히 한 지점을 찾아가지만, BETWEEN, >, -- 쿼리WHERE status = 'active' AND created_at > '2026-01-01'-- 좋은 인덱스: (status, created_at)-- 나쁜 인덱스: (created_at, status)(created_at, status) 순서면 created_at 범위 검색 이..
· CS 정리
서비스를 운영하다 보면 평소에는 잘 동작하던 조회 API가 갑자기 느려지는 순간이 있다.SELECT *FROM ordersWHERE customer_id = 1004ORDER BY created_at DESCLIMIT 20;쿼리만 보면 단순해 보인다. 이런 상황에서 가장 먼저 떠오르는 해결책은 보통 이것이다.“인덱스를 추가하면 되지 않을까?”하지만 조회가 느린 원인은 인덱스 하나로 끝나지 않는다. 실행 계획이 잘못됐을 수도 있고, 읽는 데이터가 너무 많거나, 정렬과 조인 비용이 클 수도 있다. 쿼리가 아니라 락이나 커넥션 풀에서 기다리고 있을 가능성도 있다.따라서 느린 SELECT를 만났을 때는 감으로 인덱스를 추가하기보다 다음 순서로 원인을 좁혀야 한다.느린 요청 확인→ 실제 SQL과 실행 시간 확인→..
· CS 정리
Redis를 공부하다 보면 이런 설명을 자주 접하게 된다.Redis는 싱글 스레드 기반이지만 빠르다. 처음 들으면 조금 이상하다.싱글 스레드라면 요청이 여러 개 들어왔을 때 하나씩 처리해야 할 것 같은데, Redis는 수많은 클라이언트 연결을 동시에 처리할 수 있다.이걸 이해하려면 **이벤트 루프(Event Loop)**와 I/O Multiplexing이라는 개념을 알아야 한다.이번 글에서는 이벤트 루프가 왜 필요한지부터 시작해서, I/O Multiplexing과 epoll이 어떤 역할을 하는지, 그리고 이 구조가 Redis 같은 서버에서 어떻게 사용되는지까지 정리해보려고 한다.1. 가장 단순한 서버를 생각해보자서버에 클라이언트 요청이 들어왔다고 생각해보자.가장 단순하게 구현한다면 다음과 같은 구조를 생..
· CS 정리
서비스를 운영하다 보면 DNS 레코드를 변경해야 하는 경우가 있다.예를 들어 기존 서버에 장애가 발생해 새로운 서버로 트래픽을 전환한다고 생각해보자.기존example.com ↓10.0.0.1장애 발생 후example.com ↓10.0.0.2DNS의 A Record를 10.0.0.1에서 10.0.0.2로 변경하면 사용자들은 바로 새로운 서버로 접속하게 될까?여기서 등장하는 개념이 **DNS TTL(Time To Live)**이다.1. DNS TTL이란?DNS는 도메인 이름을 IP 주소로 변환해준다.example.com ↓ DNS 조회 ↓10.0.0.1그런데 사용자가 example.com에 접근할 때마다 매번 DNS 서버에 처음부터 질의한다면 불필요한 DNS 요청이 계속 발생하게 ..
· CS 정리
Cache-Aside의 기본 구조는 단순하다.캐시 조회→ Cache Miss→ DB 조회→ 캐시 저장하지만 요청이 많은 운영 환경에서는 Cache Miss 하나가 예상보다 큰 장애로 이어질 수 있다.대표적으로 다음 문제들을 고려해야 한다.Cache Stampede : 캐시 만료 순간 DB 요청이 폭증하는 문제Hot Key : 특정 Redis Key에 요청이 집중되는 문제Cache Penetration: 존재하지 않는 데이터를 반복 조회하는 문제Cache Avalanche : 많은 캐시가 동시에 만료되는 문제장애 전파 : Redis 장애가 DB 장애로 이어지는 문제각각 어떤 상황에서 발생하고, 실무에서는 어떻게 대응하는지 알아보자.Cache Stampede란?Cache Stam..
· CS 정리
Cache-Aside는 애플리케이션이 캐시와 데이터베이스를 직접 확인하고 관리하는 캐싱 전략입니다.데이터를 조회할 때 먼저 캐시를 확인합니다.클라이언트 ↓애플리케이션 ↓캐시 조회캐시에 데이터가 있으면 바로 반환합니다.캐시에 데이터 있음(Cache Hit)→ 캐시 데이터 반환캐시에 데이터가 없으면 데이터베이스에서 조회한 뒤, 결과를 캐시에 저장하고 반환합니다.캐시에 데이터 없음(Cache Miss)→ DB 조회→ 조회 결과를 캐시에 저장→ 데이터 반환전체 흐름은 다음과 같습니다.1. 캐시 조회2. 데이터가 있으면 반환3. 데이터가 없으면 DB 조회4. DB 조회 결과를 캐시에 저장5. 데이터 반환의사 코드로 표현하면 간단합니다.public Product getProduct(Long productId..
Saga 패턴이란?Saga 패턴은 여러 서비스에 걸친 하나의 비즈니스 작업을 여러 개의 로컬 트랜잭션으로 나누어 처리하는 분산 트랜잭션 패턴이다.각 서비스는 자신의 데이터베이스에서 로컬 트랜잭션을 커밋한다. 도중에 작업이 실패하면 앞에서 완료한 작업에 대해 보상 트랜잭션을 실행하거나, 재시도를 통해 남은 작업을 끝까지 완료한다.주문 생성 → 재고 예약 → 결제 승인 → 배송 요청Saga를 구성하는 트랜잭션은 역할에 따라 다음 세 종류로 구분할 수 있다.Compensable TransactionPivot TransactionRetryable Transaction1. Compensable TransactionCompensable Transaction은 실패했을 때 반대 작업을 통해 보상할 수 있는 트랜잭션이..
· CS 정리
들어가며온라인 쇼핑몰에서 상품을 주문하면 내부적으로 여러 작업이 실행됩니다.1. 주문 생성2. 재고 차감3. 결제 승인4. 배송 요청사용자에게는 하나의 ‘주문하기’ 작업이지만, MSA에서는 각 작업을 서로 다른 서비스가 처리할 수 있습니다.주문 서비스 → 주문 DB재고 서비스 → 재고 DB결제 서비스 → 결제 DB배송 서비스 → 배송 DB그렇다면 주문과 재고 처리는 성공했지만 결제가 실패하면 어떻게 해야 할까요?주문 생성 성공재고 차감 성공결제 승인 실패결제는 실패했지만 주문 데이터는 생성됐고 재고도 이미 감소했습니다. 이렇게 하나의 업무가 여러 시스템에 걸쳐 처리될 때 발생하는 데이터 정합성 문제가 분산 트랜잭션 문제입니다.트랜잭션이란?트랜잭션은 여러 작업을 하나의 논리적인 작업 단위로 묶는 것입니다...
· CS 정리
서비스를 운영하다 보면 데이터베이스에서 발생하는 작업은 크게 두 가지로 나뉜다.데이터를 변경하는 쓰기 작업: 주문 생성, 결제 승인, 회원정보 수정데이터를 보여주는 읽기 작업: 주문 목록 조회, 대시보드 표시, 상품 검색일반적인 시스템은 하나의 데이터 모델로 두 작업을 모두 처리한다. 구조가 단순한 대신, 서비스가 커질수록 문제가 생길 수 있다. 쓰기에는 데이터 정합성과 트랜잭션이 중요하지만, 읽기에는 빠른 응답과 다양한 조회 형태가 더 중요하기 때문이다.CQRS(Command Query Responsibility Segregation)는 이처럼 서로 다른 요구사항을 가진 쓰기와 읽기의 책임을 분리하는 아키텍처 패턴이다.Command와 QueryCQRS의 핵심은 이름에 들어 있다.Command: 시스템의..
· CS 정리
서비스를 만들다보면 외부 API를 호출할 일이 은근 많다.결제 API문자 발송 API카카오 알림톡 API다른 내부 서버 API 근데 만약 결제 API가 갑자기 느려지거나 죽어버리면 어떻게 될까?우리 서버는 결제 API 응답을 기다리게 되고,요청이 계속 쌓이고, PHP-FPM worker도 계속 잡혀있고,결국 결제 기능만 문제가 아니라 우리 서버 전체가 느려질 수도 있다.이런 상황에서 사용하는 패턴이 서킷 브레이커다.이름 그대로 전기 차단기랑 비슷하다.전기가 너무 많이 흐르면 차단기가 내려가듯이,외부 API 호출이 계속 실패하면 잠깐 요청을 막아버린다.서킷 브레이커가 없으면예를 들어 외부 배송 API를 호출한다고 해보자.우리 서버 -> 배송 API배송 API가 죽었다.그런데도 우리 서버는 요청이 올 때마다..
촉쵹한초코칩
개발자로 살아남기