본문 바로가기

전체 글24

주문 대기열 시스템 설계: Redis Sorted Set의 내부 구조가 실시간 순번 조회를 가능하게 하는 원리 TL;DR — 트래픽 폭증 시 하류 시스템을 보호하면서 유저에게 공정한 순서를 보장하기 위해 Redis Sorted Set 기반의 주문 대기열을 구현했다. 처음에는 "Redis가 빠르니까"라는 이유만으로 충분하다고 생각했지만, 순번 조회(ZRANK)가 왜 O(log N)인지를 제대로 설명하지 못하는 자신을 발견했다. 그래서 Sorted Set의 내부 구현체인 스킵 리스트(Skip List)와 스팬(Span) 메커니즘까지 파고들었고, 그 과정에서 얻은 이해를 이 글에 정리한다. 1. 트래픽 제어의 필요성: Back-pressure평소 초당 100건이던 주문 요청이 블랙 프라이데이 시작 직후 초당 10,000건으로 폭증하는 상황을 가정해 보았다. 이 트래픽이 주문 API로 직접 유입되면 어떤 일이 벌어질지.. 2026. 4. 3.
이것이 Spring AI다 한빛미디어 서평단 활동을 위해서 책을 협찬받아 작성된 서평입니다Spring AI에 대한 관심이 시작된 곳, SpringCamp 2025사실 이 책을 집어든 건, 우연이 아니었습니다.지난 SpringCamp 2025에서 종훈님이 Spring AI 오픈소스 기여 경험을 발표하셨는데, 그 이야기가 꽤 오래 마음에 남았습니다. 프레임워크를 "쓰는" 입장에서만 바라보던 저에게, 직접 코드를 읽고 기여하고 커뮤니티와 소통하는 과정을 들려주신 건, 솔직히 부러움 반, 자극 반이었던 것 같습니다. 무엇보다 종훈님의 발표를 통해 Spring AI라는 프로젝트가 단순히 "Spring에서 ChatGPT 호출하기"가 아니라, 꽤 진지하게 추상화 계층을 설계하고 있는 프로젝트라는 인상을 받았습니다.그래서 이번에 서평 기회가 .. 2026. 4. 1.
Kafka를 붙일 때 가장 먼저 본 것은 왜 manual ack였을까 TL;DR: Kafka를 처음 붙일 때 나는 Producer 옵션보다 Consumer의 manual ack가 더 먼저 눈에 들어왔고, 그 지점에서야 "메시지를 받는 것"보다 "언제 처리 완료로 간주할 것인가"가 더 중요한 질문일 수 있겠다고 생각하게 됐다. Kafka를 공부하기 전에는 토픽을 만들고 Producer로 메시지를 보내는 쪽이 더 핵심이라고 생각했다. 그런데 이번에 실제 코드를 보면서 내 시선은 조금 다르게 움직였다. modules/kafka/.../KafkaConfig.kt에서 먼저 보인 것은 KafkaTemplate보ConcurrentKafkaListenerContainerFactory였고, 그 안에서도 ContainerProperties.AckMode.MANUAL 설정이 더 오래 남았다.. 2026. 3. 27.
뽀빠이 식당으로 보는 트래픽 몰림, Retry, 그리고 Idempotency 한 줄 요약같은 순간에 요청이 몰리면 시스템은 생각보다 쉽게 흔들릴 수 있습니다. 그래서 Exponential Backoff + Jitter, Token Bucket 같은 장치로 몰림을 나누어 보고, 결제처럼 상태를 바꾸는 요청에서는 Retry만 붙이기보다 Idempotency와 State를 함께 설계해야 한다고 생각합니다. 먼저 뽀빠이 식당 장면으로 Thundering Herd, Exponential Backoff + Jitter, Token Bucket을 가볍게 풀어 보고요. 그다음 결제 처리 예시를 보면서 Retry, Idempotency, Timeout, State가 왜 같이 묶여야 하는지 천천히 이어서 보려고 합니다. 사실 뽀빠이를 본적이 없습니다, 그저 그림이 귀여워서 예시로 삼아봤습니다왜 .. 2026. 3. 20.
읽기 최적화 관점을 중복 처리 이슈에 적용해 보면 무엇이 보이는가 TL;DR: 하나의 요청만 보냈다고 믿었던 결제 시스템이 왜 같은 거래를 두 번 처리하게 되었는지, 로그와 구조를 따라가며 끝까지 이해해 본 기록 이번 이슈를 다시 돌아보면서 가장 오래 남은 감정은, 나는 처음에 이 문제를 전혀 다른 방향으로 붙잡고 있었다는 약간의 당혹감이었다.처음의 나는 네트워크를 먼저 의심했다. 앞단 장비가 요청을 다시 보낸 것은 아닐까, 중간 프록시가 재전송한 것은 아닐까, 상대 시스템이 같은 요청을 잘못 두 번 처리한 것은 아닐까 같은 생각을 한동안 반복했다. 그렇게 생각한 이유는 분명했다. 내가 보고 있던 결제 시스템 로그에는 외부 적립 요청이 한 번만 찍혀 있었기 때문이다.그래서 처음에는 오히려 확신에 가까운 감정도 있었다. 적어도 내가 보고 있는 장면 안에서는 결제 시스템.. 2026. 3. 13.
인덱스와 캐시, 구조 개선을 통해 읽기 성능을 향상시키며 정리한 판단들 TL;DR: 이번 주차에서는 인덱스, likesCount 비정규화, 캐시, 쓰기 경로의 명시적 무효화를 통해 상품 조회 경로를 더 단순하게 만들고 읽기 성능을 개선하는 방향으로 구조를 정리했다. 이번 주차를 돌아보면서 내 머릿속에 가장 오래 남은 생각은, 읽기 성능 문제는 쿼리 하나만 고친다고 끝나지 않는다는 점이었다.상품 목록을 브랜드로 필터링하고, 좋아요 순으로 정렬하고, 같은 요청이 반복해서 들어오는 흐름을 보고 있으면, 문제는 단순히 더 빨라야 한다에 머무르지 않았다. 오히려 읽기 경로 자체를 더 단순하게 만들 필요가 있는 것 아닌가 하는 생각이 계속 남았다.이번 구현 과제는 바로 그 관점에서 인덱스와 캐시를 추가하고, likesCount를 비정규화하고, 쓰기 경로에 무효화 책임을 두면서 조회.. 2026. 3. 13.