분류 전체보기 73

루프팩 L2 10주 회고 — “왜”를 다시 배우다

TL;DR: 기능보다 근거. 실패·복구까지 설계하고, 지표로 말하는 습관을 얻었다. 이제부터는 그 습관을 매일 쌓아 팀이 믿는 개발자로 간다.시작한 이유입사 1년. 회사 일이 바쁘다는 이유로 공부를 미뤘다. 학부 시절엔 설계와 아키텍처 얘기를 좋아했는데, 어느새 출퇴근 루틴에 익숙해진 내 모습이 보였다. 변화가 필요했다. 내 돈과 시간을 들여 선택한 과정이라 솔직히 무서웠다. 후회할까 봐. 결론은 후회 없음이다. 팀원들과 부딪히며 매일 “왜 이렇게 설계해야 하는가”를 다시 묻게 됐다. 의지가 돌아왔고, 재미도 돌아왔다.10주 동안 얻은 것기능보다 근거. 책임 경계와 실패·복구 시나리오를 먼저 적는다.운영을 버티는 기본기. 멱등성, 락 전략, 읽기·쓰기 분리, 재시도·서킷 브레이커를 실제 코드로 체득.체감..

Loopers 2025.09.19

WIL Redis 자료구조

WIL (2025-09-08 ~ 2025-09-14)Redis 자료구조 집중 요약 (Data Structures Only)이번 주는 자료구조 자체만 정리했다. 각 구조의 한 줄 설명, 언제 쓰는지, 핵심 명령과 복잡도, 주의점만 남겼다.0) TL;DRString / List / Set / Sorted Set(ZSET) / Hash / Stream / Bitmap·Bitfield / HyperLogLog / Geo기본 패턴만 알면 80%는 끝: 캐시(String), 큐(List), 중복 제거(Set), 랭킹(ZSET), 작은 객체(Hash), 이벤트 로그(Stream), 출석·플래그(Bitmap), 고유 수 추정(HLL), 반경 검색(Geo).1) 한눈 비교표 타입특징대표 시나리오핵심 명령삽입갱신/조회/범..

Loopers 2025.09.14

🔥 "랭킹 좀 만들어달라는데 Redis 메모리가..." - ZSET 랭킹 시스템 구축기

🔥 "랭킹 좀 만들어달라는데 Redis 메모리가..." - ZSET 랭킹 시스템 구축기TL;DR: "간단한 랭킹 좀 만들어주세요"라는 요청이 어떻게 다중 ZSET vs 단일 ZSET 설계 고민 → 가중치 실시간 변경 지옥 → 콜드 스타트 딜레마까지 이어졌는지. 실제 커밋 로그와 함께 보는 7일간의 현실.🚀 Day 1: 기존 구조에 한 줄만 추가하면 되겠네기획팀: "오늘의 인기상품 랭킹 보여주실 수 있나요?"나: "MetricsHandler에 랭킹 서비스 한 줄만 추가하면 될 것 같은데요?"프로젝트를 살펴보니 이미 완성된 이벤트 처리 구조가 있었다:// apps/commerce-streamer/src/main/java/com/loopers/handler/impl/MetricsHandler.java@Co..

Loopers 2025.09.11

"같은 주문이 두 번 결제됐습니다" 💸 - Kafka로 배운 분산 시스템의 잔혹한 현실

TL;DR :주문 이벤트가 다인스턴스에서 동시에 전송되며 중복 결제가 발생했다. 설정(acks=all, idempotence=true)만으로는 애플리케이션 레벨 경합을 막을 수 없었다.나는 Outbox + DB 원자적 선점 + 동기 전송(.get())으로 "처음부터 안전"을 선택했다.토픽은 max.in.flight=5, Consumer는 별도 테이블 기반 멱등성, DLT는 Table 우선으로 운영했다.결과적으로 유실/중복/순서 문제를 "설계로 산" 뒤, 성능 최적화를 진행할 수 있었다. 그날, 같은 주문이 두 번 결제되었다 😨[ERROR] Duplicate payment detectedpaymentId: 92134, orderId: 55120, amount: 39000Original: 2024-03-0..

Loopers 2025.09.05

🚨 “그냥 @EventListener면 끝?” — 이벤트, 언제·왜·어떻게 사용할 것인가 ⚙️

TL;DR“관심사 분리”용으로 가볍게 시작했다가, 도메인 사실을 안전하게 전파하고 추적 가능한 메타데이터를 더해 운영/관측성까지 챙기는 구조로 진화.핵심 선택은 AFTER_COMMIT + @Async + Envelope + Bridge + Policy/Sender 분리.이번 과제에서 데이터 플랫폼 싱크 = 알림톡이었고, 도메인 이벤트(PaymentCaptured)가 **봉투(Envelope)**로 표준화되어 알림 정책 → 전송자를 통해 **단일 싱크(알림톡)**로 흘러가게 설계했다. 1) 처음 생각: “@EventListener 붙이면 관심사 분리 완료”처음엔 정말 이렇게 시작했다. 도메인 로직(주문/결제) 뒤에 알림/집계/로그를 리스너로 뽑아내면 끝이라 믿었음.[Controller/Service] →..

Loopers 2025.08.29

Resilience와 보상 트랜잭션: 장애에 대응하는 방법

이번 주는 외부 결제(PG) 연동 안정성을 주제로,Resilience4j로 장애를 제어 가능한 범위로 줄이고,보상 트랜잭션으로 외부 자원과 로컬 DB의 정합성을 맞추며,Spring Events로 도메인 사건을 분리하는 방식을 학습했다.1. Resilience4j — 회복탄력성을 위한 첫 번째 생명선Resilience4j란 무엇인가?자바 기반 회복탄력성(Resilience) 라이브러리외부 시스템 호출 실패나 지연을 서비스 전반으로 확산되지 않도록 제어하는 다양한 패턴 제공왜 필요한가?네트워크·외부 API는 언제든 장애가 발생할 수 있다.단순 try-catch는 개별 호출만 잡아줄 뿐, 서비스 전체 안정성은 지켜주지 못한다.핵심은 “장애를 없애는 게 아니라, 장애를 제어 가능한 형태로 축소하는 것”.주요 동..

Loopers 2025.08.24

PG가 터져도 우리 서비스는 멀쩡해야 한다 🔥

PG가 터져도 우리 서비스는 멀쩡해야 한다 🔥Resilience4j로 결제 시스템 장애 방어선 구축한 썰TL;DRPG 시뮬레이터 연동하다가 외부 시스템 장애로 전체 서비스 마비 경험. Resilience4j의 Circuit Breaker, Retry, Bulkhead, Timeout 패턴으로 방어선 구축하고, 이벤트 기반 보상 트랜잭션과 스케줄러 복구로 완전체 만든 실전기. "PG 하나 죽어도 주문은 계속 받아야 한다"🚨 사건의 발단: PG 하나가 터지니까 전체가 다운됐다이번 6주차 과제에서 PG 시뮬레이터를 붙이면서 처음으로 "외부 의존성의 무서움"을 체감했습니다.PG 시뮬레이터 스펙 (현실적으로 잔인함)📊 PG 시뮬레이터 장애 시나리오- 요청 성공 확률: 60% (40%는 그냥 실패)- 요청 지..

Loopers 2025.08.22

WIL - 인덱스 -> 캐시 -> Redis

인덱스 → 캐시 → Redis 한눈에 보기인덱스: 쿼리 자체를 빠르게 만드는 구조.캐시: 반복 결과를 메모리에 두고 재사용해 부하/지연을 줄임.Redis: 캐시로도 쓰지만, 자료구조/원자연산/TTL까지 제공하는 인메모리 스토어.인덱스 — 무엇이고 왜 쓰나정의: RDB가 찾기/정렬/필터를 빠르게 하려는 자료구조(B+Tree 중심).핵심 포인트선택: 선두 컬럼 분포가 좋아야 스캔이 짧아짐.정렬 흡수: 인덱스 순서와 ORDER BY를 맞추면 filesort 회피.커버링: 필요한 컬럼이 인덱스 안에 있으면 테이블 접근 생략.인덱스 설계 요령복합 인덱스 순서 = 쿼리 의도WHERE a=? … ORDER BY b DESC, id DESC → (a, b DESC, id DESC)카디널리티: BOOLEAN/NULL 등..

카테고리 없음 2025.08.17

인덱스 걸었는데 왜 또 느려져요? → Redis로 해결한 썰

🚀 인덱스를 걸었는데 또 느려졌다? → Redis 캐시로 완전체 만든 썰 Part 2📱 인사말안뇽 여러분~ 지난번에 인덱스 최적화로 p95 개선한 썰 풀었는데 기억하시나요?[지난편 요약]WHERE만 보고 인덱스 걸었다가 filesort 지옥 맛봄 😵정렬 컬럼 + 타이브레이커(id) 포함한 전용 인덱스로 해결p95 기준 3~10배 성능 개선 달성! 🎉그런데... 트래픽이 더 늘어나니까 또 한계가 보이더라구요 😅그래서 이번엔 Redis 캐시까지 도입해서 완전체를 만들어봤습니다!K6 테스트로 정량 측정한 결과가 레전드급이라 공유해봅니다 🔥🤔 인덱스 최적화했는데 왜 또 느려졌을까?지난번 인덱스 개선 요약지난번에 이런 삽질을 했었죠:-- ❌ WHERE만 보고 만든 나쁜 인덱스CREATE INDEX i..

카테고리 없음 2025.08.15

인덱스를 걸었는데… 더 느려졌다? 🤯

인덱스를 걸었는데… 더 느려졌다? 🤯10만 건 이후, 인덱스의 배신과 선택의 이유TL;DR10만 건을 넘기면 평균보다 p95·p99 tail latency가 먼저 무너진다.WHERE 컬럼만 인덱싱하면 정렬을 못 받아 filesort로 샌다.정렬 컬럼 + 타이브레이커(id) 를 포함한 전용 인덱스로 정렬을 인덱스로 해결해야 한다.좋아요순은 인덱스만으론 부족. 드라이빙 테이블을 product_likes로 전환해야 한다.1) 증상: 평균은 멀쩡한데 p95가 터진다데이터 규모: 약 10만 건문제 구간:deep 페이지네이션(OFFSET 수백~수천)브랜드 필터 + 정렬 조합현상: 평균은 괜찮아 보여도 p95·p99가 급격히 악화원인들은 겹친다: 정렬 미지원, 카디널리티, 옵티마이저 선택, OFFSET 자체 비용2..

Loopers 2025.08.15