꽥블로그
최신 글
-
API 서버인데 HttpSession이 heap을 먹고 있었다
API 서버인데 HttpSession이 heap을 먹고 있었다
2026.09.25세션을 쓰지 않는 조회 전용 API 서버에 세션이 쌓여 있었다. 원인은 인증 필터와 Spring Security 기본 세션 정책의 조합이었다.핵심증상 API 서버인데 만료 대기 중인 HttpSession 이 heap 상당 부분을 점유원인 sessionManagement 미설정 → 기본값 IF_REQUIRED + 커스텀 인증 필터가 매 요청 SecurityContextHolder 에 인증 정보를 설정 → 요청 종료 시 SecurityContextPersistenceFilter 가 세션에 저장 → 세션 생성반전 인증 자체는 쿠키로만 하고 세션을 읽지 않는다 → 만들어놓고 아무도 안 쓰는 세션해결 SessionCreationPolicy.STATELESS → Sec.. -
TimeLimiter를 readTimeout보다 짧게 두면 안 되는 이유
TimeLimiter를 readTimeout보다 짧게 두면 안 되는 이유
2026.09.25Hystrix에서 Resilience4j로 옮기고 나서 알게 된 것들. 라이브러리는 바뀌었는데 장애가 나는 자리는 그대로였다.시작@HystrixCommand를 떼고 Resilience4j의 CircuitBreaker와 TimeLimiter, ThreadPoolBulkhead로 바꾸고, Ribbon을 Spring Cloud LoadBalancer로 교체했다. 기존 Hystrix 값을 그대로 옮겨두면 격리 수준이 유지될 거라고 생각했다.그런데 남아 있던 문제가 두 개 있었다. 하나는 타임아웃 값의 순서가 뒤집힌 서비스가 있었다는 것, 다른 하나는 벌크헤드의 스레드 확장 규칙이 내가 생각한 것과 달랐다는 것이다.둘 다 "라이브러리가 알아서 해주겠지"라고 넘겼던 부분이었다.인터럽트로 깨지는 것과 안 깨지는 것먼.. -
$limit을 붙였는데 왜 안 빨라져? — MongoDB DOCS-11102
$limit을 붙였는데 왜 안 빨라져? — MongoDB DOCS-11102
2026.09.20$limit을 붙였는데 빨라지지 않았다 — 집계 파이프라인의 limit pushdown 조건TL;DR집계 파이프라인 끝에 $limit: 20을 붙여도, 앞에 $unwind나 $group이 있으면 $limit은 앞으로 내려가지 못한다. 옮기면 결과가 달라지기 때문에 옵티마이저가 옮길 수 없다. 스캔·비교 횟수는 그대로고, 줄어드는 건 정렬이 들고 있는 문서 수뿐이다.이 조건은 DOCS-11102에 명시된 문서화된 동작이다. 실제 서비스에서는 인덱스를 탈 수 있는 조건만 DB에 남기고 $unwind·$group·$sort를 애플리케이션으로 옮겨서 해결했다. 이후에도 같은 불변식($limit 앞에 문서 개수를 바꾸는 단계를 두지 않는다)이 깨지면 $limit은 다시 장식이 됐다.배경대상: 목록 조회 API. .. -
timeout 났는데 왜 커넥션이 안 돌아와?
timeout 났는데 왜 커넥션이 안 돌아와?
2026.08.17timeout 났는데 왜 커넥션이 안 돌아와? — spring-cloud-netflix #327 실전 대응기TL;DRHystrix가 먼저 timeout을 선언해도, Ribbon/Apache HttpClient 소켓이 아직 ReadTimeout까지 응답을 기다리고 있으면 커넥션은 풀에 반환되지 않는다. 피크에서는 이게 반복되며 HttpClient 풀·Hystrix 스레드풀이 고갈되고, 페이지 조립 BFF 전체가 Cascading Failure로 무너진다.이 패턴은 spring-cloud-netflix #327에 이미 보고된 known issue다. 실제 서비스에서는 API별 Hystrix timeout 세분화 + connectionRequestTimeout + Ribbon/Hystrix 정합으로 막았다. .. -
바이브 코딩 잘 활용하기
바이브 코딩 잘 활용하기
2025.12.25https://helloworld.kurly.com/blog/vibe-coding-with-claude-code/ 먼저 위 글을 참고했습니다. — LLM과 일할 때, 원하는 답을 얻기 위한 실전 가이드요즘 “바이브 코딩(Vibe Coding)”이라는 말이 자주 등장합니다. AI에게 자연어로 요구사항을 던지고, 코드를 생성하게 한 뒤 흐름에 몸을 맡기는 개발 방식입니다. 하지만 실무에서 바이브 코딩을 써본 사람이라면 이런 경험이 한 번쯤은 있을 것입니다. 분명 규칙을 다 써줬는데 일부가 빠져있다든지..처음엔 잘 지키다가, 대화가 길어지면 갑자기 구조가 바뀐다던지..최신 스택을 쓰자고 했는데 어느 순간 과거 패턴으로 돌아가는 경우입니다. 이건 AI가 충분히 성능을 못내줘서가 아니라,LLM의 구조적 특성을 .. -
MongoDB Covered Index 이해하기
MongoDB Covered Index 이해하기
2025.11.23대규모 데이터 환경에서 쿼리 성능을 최적화하는 핵심 기술 중 하나는 Covered Index(Index-only Query) 를 활용하는 것이다. Covered Index는 쿼리 처리에 필요한 모든 정보가 인덱스 안에 포함되어 있어 Document 본문을 읽을 필요가 없는 경우를 의미한다.즉, Disk I/O 없이 인덱스만으로 결과를 반환할 수 있어 속도와 리소스 효율성이 매우 뛰어나다. 1. Covered Index란 무엇인가?MongoDB에서 쿼리가 Covered Index가 되기 위한 조건은 다음과 같다:필터 조건이 인덱스 필드에 포함되어야 한다. find()의 where 조건 필드가 인덱스에 존재해야함 Projection 필드와 인덱스 필드가 일치해야 한다. 반환해야 하는 필드가 전부 인덱스에 포.. -
Spring AOP로 Controller 파라미터 자동 주입하기
Spring AOP로 Controller 파라미터 자동 주입하기
2025.11.16Spring AOP를 활용하면, Controller 파라미터에 특정 값을 자동으로 주입하거나 메서드 실행 전·후에 공통 로직을 삽입하는 흐름을 직접 구현할 수 있습니다.이번 글에서는 @CurrentUserId 라는 커스텀 어노테이션을 만들어, Controller 메서드에서 아래처럼 userId를 직접 받지 않아도 되도록 구성해보겠습니다.@GetMapping("/recommendations")public ResponseEntity> getRecommendations(@CurrentUserId Long userId)이 userId 값은 우리가 만든 AOP @Around 어드바이스가 자동으로 주입하게 됩니다.프로젝트 초기 Spring Initializr에서 기본 Dependencies를 추가한 뒤 프로젝트를 .. -
[대규모 시스템 설계 기초] 10장. 알림 시스템 설계
[대규모 시스템 설계 기초] 10장. 알림 시스템 설계
2025.11.09알림 시스템 설계 개요알림 시스템은 이벤트, 선물 중요할 만한 정보를 비동기적으로 제공합니다. 알림 시스템은 단순히 모바일 푸시 알림에 한정되지 않습니다. 단일 이벤트 트리거 기반 멀티 채널 알림 방송 시스템을 목표로 합니다. 1단계 문제 이해 및 설계 범위 확정대상은 푸시 알림, SMS 메시지, 그리고 이메일이 될 수 있습니다. 실시간 시스템임을 감안한다. 지원하는 단말은 iOS 단말, 안드로이드 단말, 그리고 랩톱/데스크톱입니다.기능적 요구사항지원 알림 유형: 푸시, SMS, 이메일비기능적 요구사항성능 특성: 연성 실시간(soft real-time) 시스템, 높은 부하 시 약간의 지연 허용사용자 설정: opt-out 기능(사용자가 알림을 받지 않도록하는 기능) 지원중요한건 확장성을 고려해 천만 건.. -
[대규모 시스템 설계 기초] 4장. 처리율 제한 장치의설계 - 3
[대규모 시스템 설계 기초] 4장. 처리율 제한 장치의설계 - 3
2025.11.02상세설계처리율 제한이란?처리율 제한(Rate Limiting)은 사용자가 일정 시간 동안 API를 호출할 수 있는 최대 요청 수를 제한하는것을 의미합니다. 특정 사용자의 과도한 요청으로 인한 서버 과부하 방지를 막아줍니다. 처리율 제한 규칙Lyft 는 처리율 제한에 오픈소스로 사용되고 있습니다. Envoy Proxy와 함께 사용하면 분산 환경에서도 중앙 집중적으로 요청 제한을 관리할 수 있습니다.Lyft는 마이크로서비스 아키텍처에서 이 Ratelimit 서비스를 광범위하게 활용하고 있습니다.공식 깃허브: https://github.com/envoyproxy/ratelimit GitHub - envoyproxy/ratelimit: Go/gRPC service designed to enable generic.. -
[대규모 시스템 설계 기초] 4장. 처리율 제한 장치의설계 - 2
[대규모 시스템 설계 기초] 4장. 처리율 제한 장치의설계 - 2
2025.10.19앞선 글에서는 Rate Limiter를 어디 레이어에 배치할 것인지(클라이언트 vs 서버 vs 게이트웨이 vs 인프라) 에 대해 이제 “어디에 둘 것인가”를 결정했다면, 다음 고민은 자연스럽게 이렇게 이어진다. 정확하고 성능 좋은 알고리즘은 무엇인가? Rate Limiter는 단순히 count++로 해결되지 않는다.Time Window, Token Bucket, Leaky Bucket, Sliding Log, Hybrid 방식 등 여러 알고리즘이 존재하며,각 방식은 정확도, 성능, 메모리, 구현 난이도, 분산 처리 가능 여부가 모두 다르다.또한 알고리즘을 선택했다 하더라도, 실제 시스템에서는 아래와 같은 아키텍처적 고민이 필요하다.중앙 저장소를 사용할 것인가? (Redis, DB, in-memory 등)..
모든 글
-
API 서버인데 HttpSession이 heap을 먹고 있었다
API 서버인데 HttpSession이 heap을 먹고 있었다
2026.09.25세션을 쓰지 않는 조회 전용 API 서버에 세션이 쌓여 있었다. 원인은 인증 필터와 Spring Security 기본 세션 정책의 조합이었다.핵심증상 API 서버인데 만료 대기 중인 HttpSession 이 heap 상당 부분을 점유원인 sessionManagement 미설정 → 기본값 IF_REQUIRED + 커스텀 인증 필터가 매 요청 SecurityContextHolder 에 인증 정보를 설정 → 요청 종료 시 SecurityContextPersistenceFilter 가 세션에 저장 → 세션 생성반전 인증 자체는 쿠키로만 하고 세션을 읽지 않는다 → 만들어놓고 아무도 안 쓰는 세션해결 SessionCreationPolicy.STATELESS → Sec.. -
TimeLimiter를 readTimeout보다 짧게 두면 안 되는 이유
TimeLimiter를 readTimeout보다 짧게 두면 안 되는 이유
2026.09.25Hystrix에서 Resilience4j로 옮기고 나서 알게 된 것들. 라이브러리는 바뀌었는데 장애가 나는 자리는 그대로였다.시작@HystrixCommand를 떼고 Resilience4j의 CircuitBreaker와 TimeLimiter, ThreadPoolBulkhead로 바꾸고, Ribbon을 Spring Cloud LoadBalancer로 교체했다. 기존 Hystrix 값을 그대로 옮겨두면 격리 수준이 유지될 거라고 생각했다.그런데 남아 있던 문제가 두 개 있었다. 하나는 타임아웃 값의 순서가 뒤집힌 서비스가 있었다는 것, 다른 하나는 벌크헤드의 스레드 확장 규칙이 내가 생각한 것과 달랐다는 것이다.둘 다 "라이브러리가 알아서 해주겠지"라고 넘겼던 부분이었다.인터럽트로 깨지는 것과 안 깨지는 것먼.. -
$limit을 붙였는데 왜 안 빨라져? — MongoDB DOCS-11102
$limit을 붙였는데 왜 안 빨라져? — MongoDB DOCS-11102
2026.09.20$limit을 붙였는데 빨라지지 않았다 — 집계 파이프라인의 limit pushdown 조건TL;DR집계 파이프라인 끝에 $limit: 20을 붙여도, 앞에 $unwind나 $group이 있으면 $limit은 앞으로 내려가지 못한다. 옮기면 결과가 달라지기 때문에 옵티마이저가 옮길 수 없다. 스캔·비교 횟수는 그대로고, 줄어드는 건 정렬이 들고 있는 문서 수뿐이다.이 조건은 DOCS-11102에 명시된 문서화된 동작이다. 실제 서비스에서는 인덱스를 탈 수 있는 조건만 DB에 남기고 $unwind·$group·$sort를 애플리케이션으로 옮겨서 해결했다. 이후에도 같은 불변식($limit 앞에 문서 개수를 바꾸는 단계를 두지 않는다)이 깨지면 $limit은 다시 장식이 됐다.배경대상: 목록 조회 API. .. -
timeout 났는데 왜 커넥션이 안 돌아와?
timeout 났는데 왜 커넥션이 안 돌아와?
2026.08.17timeout 났는데 왜 커넥션이 안 돌아와? — spring-cloud-netflix #327 실전 대응기TL;DRHystrix가 먼저 timeout을 선언해도, Ribbon/Apache HttpClient 소켓이 아직 ReadTimeout까지 응답을 기다리고 있으면 커넥션은 풀에 반환되지 않는다. 피크에서는 이게 반복되며 HttpClient 풀·Hystrix 스레드풀이 고갈되고, 페이지 조립 BFF 전체가 Cascading Failure로 무너진다.이 패턴은 spring-cloud-netflix #327에 이미 보고된 known issue다. 실제 서비스에서는 API별 Hystrix timeout 세분화 + connectionRequestTimeout + Ribbon/Hystrix 정합으로 막았다. .. -
바이브 코딩 잘 활용하기
바이브 코딩 잘 활용하기
2025.12.25https://helloworld.kurly.com/blog/vibe-coding-with-claude-code/ 먼저 위 글을 참고했습니다. — LLM과 일할 때, 원하는 답을 얻기 위한 실전 가이드요즘 “바이브 코딩(Vibe Coding)”이라는 말이 자주 등장합니다. AI에게 자연어로 요구사항을 던지고, 코드를 생성하게 한 뒤 흐름에 몸을 맡기는 개발 방식입니다. 하지만 실무에서 바이브 코딩을 써본 사람이라면 이런 경험이 한 번쯤은 있을 것입니다. 분명 규칙을 다 써줬는데 일부가 빠져있다든지..처음엔 잘 지키다가, 대화가 길어지면 갑자기 구조가 바뀐다던지..최신 스택을 쓰자고 했는데 어느 순간 과거 패턴으로 돌아가는 경우입니다. 이건 AI가 충분히 성능을 못내줘서가 아니라,LLM의 구조적 특성을 .. -
MongoDB Covered Index 이해하기
MongoDB Covered Index 이해하기
2025.11.23대규모 데이터 환경에서 쿼리 성능을 최적화하는 핵심 기술 중 하나는 Covered Index(Index-only Query) 를 활용하는 것이다. Covered Index는 쿼리 처리에 필요한 모든 정보가 인덱스 안에 포함되어 있어 Document 본문을 읽을 필요가 없는 경우를 의미한다.즉, Disk I/O 없이 인덱스만으로 결과를 반환할 수 있어 속도와 리소스 효율성이 매우 뛰어나다. 1. Covered Index란 무엇인가?MongoDB에서 쿼리가 Covered Index가 되기 위한 조건은 다음과 같다:필터 조건이 인덱스 필드에 포함되어야 한다. find()의 where 조건 필드가 인덱스에 존재해야함 Projection 필드와 인덱스 필드가 일치해야 한다. 반환해야 하는 필드가 전부 인덱스에 포.. -
Spring AOP로 Controller 파라미터 자동 주입하기
Spring AOP로 Controller 파라미터 자동 주입하기
2025.11.16Spring AOP를 활용하면, Controller 파라미터에 특정 값을 자동으로 주입하거나 메서드 실행 전·후에 공통 로직을 삽입하는 흐름을 직접 구현할 수 있습니다.이번 글에서는 @CurrentUserId 라는 커스텀 어노테이션을 만들어, Controller 메서드에서 아래처럼 userId를 직접 받지 않아도 되도록 구성해보겠습니다.@GetMapping("/recommendations")public ResponseEntity> getRecommendations(@CurrentUserId Long userId)이 userId 값은 우리가 만든 AOP @Around 어드바이스가 자동으로 주입하게 됩니다.프로젝트 초기 Spring Initializr에서 기본 Dependencies를 추가한 뒤 프로젝트를 ..