전체 글 20

피크타임 1분 걸리던 상품 재고 조회, 구조 변경으로 300ms까지 줄인 이야기

1. 문제 관측: 푸시 알림 클릭 후 1분간의 상품 목록 로딩어느 날, MD 팀에서 발송한 이벤트 푸시 알림을 확인하던 중 이상한 현상을 발견했다.알림을 눌러 앱을 실행하자, 상품 목록이 로딩되는 데 약 1분 가까이 걸렸다. 보통 해당 페이지는 수백 개의 상품을 로드하더라도 1초 내외로 표시되는 것이 정상이다.그런데 이번에는 앱이 멈춘 듯한 상태로 머물러 있었고, 사용자가 중간에 이탈할 만한 수준의 지연이었다. 이벤트 페이지로 랜딩하는 푸시 알림이라는 점에서 문제의 영향 범위는 단순한 UI 불편을 넘어섰다.마케팅 효과 측면에서도 심각한 손실로 이어질 가능성이 높았다.단순히 일시적인 네트워크 지연이 아니라, 시스템적 병목이 의심되는 상황이었다. 운영 환경 로그를 함께 살펴본 결과, 앱 자체나 네트워크보다는..

트러블슈팅 2025.10.27

발급 쿠폰 갱신 작업에서 발생한 OOM 원인: JPA 1차 캐시 이야기

TL;DR 발급 쿠폰 갱신 작업 중 Task Queue 서버에서 OOM이 반복 발생했다. 원인은 JPA를 통한 read-modify-write 패턴으로 인해 JPA 1차 캐시에 대량 엔티티가 쌓이는 구조 때문이었다. 결국 QueryDsl Update로 전환, entityManager.clear()를 통해 캐시 부담을 제거했고, 메모리 사용량이 안정화되었다. 쿠폰에 수정이 발생한 경우 발급 쿠폰에 대해서 수정작업을 하는 큐가 발행된다. 어느 날 쿠폰 수정이 발생했고 Task Queue 서버에서 발급 쿠폰에 대해 갱신을 해야하는데 Task Queue 서버가 반복적으로 OOM(Out Of Memory) 에러로 종료되는 상황을 마주했다.처음에는 단순히 컨테이너 메모리가 부족해서 발생한 문제라고 생각했다. ..

트러블슈팅 2025.10.13

하나로 묶인 트랜잭션을 쪼개다: 이벤트 기반 주문 시스템 리팩토링기

TL;DR: 주문-결제-재고-쿠폰 처리를 하나의 트랜잭션에서 처리하다가 PG 장애시 전체 시스템이 마비되는 문제를 우려. API 분리 → 이벤트 기반 구조로 단계적 리팩토링을 진행했지만 이벤트 실패 복구와 중복 처리 방지 등 새로운 고민거리도 생겼다.as-is: 거대한 트랜잭션으로 다양한 관심사to-be: 이벤트를 통해 나눠진 비즈니스 관심사문제 발견: 점점 무거워지는 주문 흐름이커머스 주문 시스템을 구현하면서 처음에는 단순하게 생각했다. 사용자가 “주문하기” 버튼을 누르면 모든 처리를 한 번에 끝내는 것이 깔끔하지 않을까?// sudo code@Transactionalfun createOrder(request: CreateOrderRequest): OrderResponse { // 1. 주문 생성..

프로젝트 2025.09.25

Cache-Aside 적용기: DB 부하 감소와 응답 속도 안정화

TL;DR: 비정규화와 인덱스 최적화로 응답 속도를 줄였지만, 읽기 빈도가 높은 목록 조회 API는 여전히 매 요청마다 DB를 조회하고 있었다. 캐싱, Cache-Aside 패턴을 적용하여 DB 부하를 거의 0에 가깝게 줄였고, 응답 속도를 20ms 수준에서 안정화시켰다.문제 관측상품 목록 조회 API의 성능을 검증하기 위해, 상품 100만 건, 상품 좋아요 700만 건의 데이터를 준비하고 부하 테스트를 진행했다.초기 구현은 단순한 GROUP BY 쿼리로 좋아요 수를 계산하는 방식이었는데, 데이터가 많아지자 응답 속도가 크게 느려졌다.통합 실험결과 (캐시 적용 전)상품 100만건, 50명의 유저가 30초동안 매초 상품 목록 조회 요청 시나리오A → B: 인덱스 적용만으로 평균 응답 시간이 약 84배 단축..

프로젝트 2025.09.25

동시성 제어 전략 선택기: 상황에 맞는 락을 고르는 기준

TL;DR: 주문 시스템 구현 중 동시성 제어가 필요한 상황에서 비관적 락과 낙관적 락을 섞어 사용했다. 쿠폰 발급에는 비관적 락을, 쿠폰 사용에는 낙관적 락을 선택한 이유와 그 과정에서 깨달은 선택 기준을 정리했다.시작: “동시성? 그냥 synchronized 쓰면 되지 않을까?”이커머스 주문 시스템을 구현하면서 처음으로 진짜 동시성 문제를 마주했다. 여러 사용자가 동시에 같은 상품을 주문하거나, 같은 쿠폰을 사용하려 할 때 데이터 정합성을 어떻게 보장할지 고민이 시작됐다.처음엔 단순하게 생각했다. Java의 synchronized 키워드나 Spring의 @Transactional이면 충분하지 않을까? 하지만 곧 깨달았다. 이건 단일 서버, 단일 스레드 내에서만 유효한 방법이라는 걸.// 이런 식으로는..

프로젝트 2025.09.24

좋아요 수 집계 테이블 도입 고민기: 설계 단계에서의 선택

TL;DR: 상품 좋아요 기능 설계 중 실시간 COUNT vs 집계 테이블 사이에서 고민했고, 성능과 정합성의 트레이드오프를 정리하며 집계 테이블을 선택했다.시작: 좋아요 수? 그냥 COUNT면 되지 않을까?이커머스 시스템 설계를 하면서 상품 좋아요 기능이 필요했다. 요구사항을 보니 상품 목록에서 각 상품의 좋아요 수를 보여줘야 하고, 심지어 “좋아요 순 정렬”도 지원해야 했다.처음엔 단순하게 생각했다. ProductLike 테이블에서 실시간으로 COUNT 쿼리 날리면 되지 않을까?-- 이렇게 하면 되지 않을까?SELECT COUNT(*) FROM product_likes WHERE product_id = ? AND deleted = false;설계하면서 드는 의구심들1. 상품 목록 조회가 걱정됐다상품 ..

프로젝트 2025.09.24

Value Class 도입기: String에서 타입 안전성까지

TL;DR: String으로 처리하던 이메일, 로그인ID를 Value Class로 리팩토링하면서 타입 안전성과 도메인 표현력을 얻었지만, 어디까지 Value Class로 만들어야 하는지 기준을 고민해야 했다.시작: String이 모든 걸 해결해줄 거라 생각했다처음 회원가입 기능을 구현할 때는 단순했다. 테스트를 먼저 작성하며 이메일도 String, 로그인 ID도 String. 빠르게 구현하고 테스트도 통과했으니 문제없다고 생각했다. 그런데 코드가 늘어나면서 이상한 생각이 들기 시작했다.문제를 실감한 순간들1. 과도한 책임부여유효성 검증을 위해 User 클래스 내부에 대량의 검증 로직이 작성되고 있었다.@Entity class User( val uid: String, val email:..

프로젝트 2025.09.22

Java 21 JVM & GC Improvements #RoadTo21 정리

Java 21 JVM & GC Improvements #RoadTo21위 유튜브 영상을 기반으로 정리한 내용이다. Java 21의 JVM 및 GC 개선 사항Java 21은 JVM과 가비지 컬렉션 성능을 크게 향상시키는 중요한 업데이트를 포함하고 있다.1. JVM 성능 최적화의 변화Java 17에서 21로 넘어가면서 다양한 성능 최적화가 이루어졌다. 이 최적화는 메모리 관리와 스레드 작업뿐만 아니라, 스택과 힙 간의 전환 속도를 개선하여 Java 애플리케이션의 전반적인 효율을 높였다. 여기서 중요한 세 가지 성능 지표는 다음과 같다.처리량(Throughtput): 단위 시간당 처리할 수 있는 작업의 양지연 시간(Latency): 작업 요청과 응답 간의 지연 시간메모리 사용량(Memory Footprint)..

Programming 2024.11.10

Will AI replace programmers? | Cursor Team and Lex Fridman 정리

Will AI replace programmers? | Cursor Team and Lex Fridman위 유튜브 영상을 기반으로 정리한 내용이다. AI가 프로그래머를 대체할까?프로그래밍의 미래에 대한 질문이 점점 중요해지고 있다. AI가 발전하면서 프로그래머의 역할은 어떻게 변할까?1. 프로그래밍의 변화하는 역할Cursor 팀은 프로그래머의 통제력과 속도를 더욱 강화하는 미래를 그리고 있다. AI가 모든 소프트웨어를 생성하는 것이 아니라, 프로그래머가 중심이 되어 AI를 활용해 효율성을 높이는 방식에 중점을 둔다. 마치 AI가 협업하는 엔지니어링 부서와 같은 역할을 수행하게 된다고 볼 수 있다. 이 접근 방식은 단순히 AI에 명령을 내리는 것이 아니라, 중요한 결정을 내리는 과정에서 프로그래머가 구체적..

Programming 2024.11.06

Java 21 new feature: Virtual Threads #RoadTo21 정리

Java 21 new feature: Virtual Threads #RoadTo21위 유튜브 영상을 기반으로 정리한 내용이다. Java 21의 새로운 기능: 가상 스레드 (Virtual Threads)Java 21에서 도입된 가상 스레드는 고성능 멀티스레딩 환경을 구현하기 위한 획기적인 기능이다. 가상 스레드는 전통적인 커널 기반 스레드와 달리 가볍고, 대규모 병렬 작업을 효과적으로 지원한다. 이 글에서는 가상 스레드가 필요한 이유, 기본 동작 방식, 성능 상의 장점과 한계를 설명한다. 1. 왜 가상 스레드가 필요한가?기존의 스레드 모델에서는 플랫폼 스레드가 사용되었으며, 이러한 스레드는 커널 스레드를 기반으로 동작한다. 플랫폼 스레드의 문제는 메모리 사용과 생성 비용이 높다는 것이다. 스레드 하나가 2..

Programming 2024.11.06